http2.py revision a65ddc700c23475df28978a17f3b44e93f56ec80
1#############################################################################
2##                                                                         ##
3## http2.py --- HTTP/2 support for Scapy                                   ##
4##              see RFC7540 and RFC7541                                    ##
5##              for more informations                                      ##
6##                                                                         ##
7## Copyright (C) 2016  Florian Maury <florian.maury@ssi.gouv.fr>           ##
8##                                                                         ##
9## This file is part of Scapy                                              ##
10## Scapy is free software: you can redistribute it and/or modify it        ##
11## under the terms of the GNU General Public License version 2 as          ##
12## published by the Free Software Foundation.                              ##
13##                                                                         ##
14## This program is distributed in the hope that it will be useful, but     ##
15## WITHOUT ANY WARRANTY; without even the implied warranty of              ##
16## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       ##
17## General Public License for more details.                                ##
18##                                                                         ##
19#############################################################################
20"""http2 Module
21Implements packets and fields required to encode/decode HTTP/2 Frames
22and HPack encoded headers
23
24scapy.contrib.status=loads
25scapy.contrib.description=HTTP/2 (RFC 7540, RFC 7541)
26"""
27
28from __future__ import absolute_import
29from __future__ import print_function
30import abc
31import types
32import re
33from io import BytesIO
34import struct
35import scapy.modules.six as six
36from scapy.modules.six.moves import range
37
38# Only required if using mypy-lang for static typing
39# Most symbols are used in mypy-interpreted "comments".
40# Sized must be one of the superclasses of a class implementing __len__
41try:
42    from typing import Optional, List, Union, Callable, Any, Tuple, Sized
43except ImportError:
44    class Sized(object): pass
45
46import scapy.fields as fields
47import scapy.packet as packet
48import scapy.config as config
49import scapy.base_classes as base_classes
50import scapy.volatile as volatile
51import scapy.error as error
52
53########################################################################################################################
54################################################ HPACK Integer Fields ##################################################
55########################################################################################################################
56
57class HPackMagicBitField(fields.BitField):
58    """ HPackMagicBitField is a BitField variant that cannot be assigned another
59    value than the default one. This field must not be used where there is
60    potential for fuzzing. OTOH, this field makes sense (for instance, if the
61    magic bits are used by a dispatcher to select the payload class)
62    """
63
64    __slots__ = ['_magic']
65
66    def __init__(self, name, default, size):
67        # type: (str, int, int) -> None
68        """
69        @param str name: this field instance name.
70        @param int default: this field only valid value.
71        @param int size: this bitfield bitlength.
72        @return None
73        @raise AssertionError
74        """
75        assert(default >= 0)
76        # size can be negative if encoding is little-endian (see rev property of bitfields)
77        assert(size != 0)
78        self._magic = default
79        super(HPackMagicBitField, self).__init__(name, default, size)
80
81    def addfield(self, pkt, s, val):
82        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> Union[str, Tuple[str, int, int]]
83        """
84        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.
85        @param str|(str, int, long) s: either a str if 0 == size%8 or a tuple with the string to add this field to, the
86          number of bits already generated and the generated value so far.
87        @param int val: unused; must be equal to default value
88        @return str|(str, int, long): the s string extended with this field machine representation
89        @raise AssertionError
90        """
91        assert val == self._magic, 'val parameter must value {}; received: {}'.format(self._magic, val)
92        return super(HPackMagicBitField, self).addfield(pkt, s, self._magic)
93
94    def getfield(self, pkt, s):
95        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> Tuple[Union[Tuple[str, int], str], int]
96        """
97        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.
98        @param str|(str, int) s: either a str if size%8==0 or a tuple with the string to parse from and the number of
99          bits already consumed by previous bitfield-compatible fields.
100        @return (str|(str, int), int): Returns the remaining string and the parsed value. May return a tuple if there
101          are remaining bits to parse in the first byte. Returned value is equal to default value
102        @raise AssertionError
103        """
104        r = super(HPackMagicBitField, self).getfield(pkt, s)
105        assert (
106            isinstance(r, tuple)
107            and len(r) == 2
108            and isinstance(r[1], six.integer_types)
109        ), 'Second element of BitField.getfield return value expected to be an int or a long; API change detected'
110        assert r[1] == self._magic, 'Invalid value parsed from s; error in class guessing detected!'
111        return r
112
113    def h2i(self, pkt, x):
114        # type: (Optional[packet.Packet], int) -> int
115        """
116        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused
117        @param int x: unused; must be equal to default value
118        @return int; default value
119        @raise AssertionError
120        """
121        assert x == self._magic, \
122            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)
123        return super(HPackMagicBitField, self).h2i(pkt, self._magic)
124
125    def i2h(self, pkt, x):
126        # type: (Optional[packet.Packet], int) -> int
127        """
128        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused
129        @param int x: unused; must be equal to default value
130        @return int; default value
131        @raise AssertionError
132        """
133        assert x == self._magic, \
134            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)
135        return super(HPackMagicBitField, self).i2h(pkt, self._magic)
136
137    def m2i(self, pkt, x):
138        # type: (Optional[packet.Packet], int) -> int
139        """
140        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused
141        @param int x: must be the machine representatino of the default value
142        @return int; default value
143        @raise AssertionError
144        """
145        r = super(HPackMagicBitField, self).m2i(pkt, x)
146        assert r == self._magic, 'Invalid value parsed from m2i; error in class guessing detected!'
147        return r
148
149    def i2m(self, pkt, x):
150        # type: (Optional[packet.Packet], int) -> int
151        """
152        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused
153        @param int x: unused; must be equal to default value
154        @return int; default value
155        @raise AssertionError
156        """
157        assert x == self._magic, \
158            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)
159        return super(HPackMagicBitField, self).i2m(pkt, self._magic)
160
161    def any2i(self, pkt, x):
162        # type: (Optional[packet.Packet], int) -> int
163        """
164        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused
165        @param int x: unused; must be equal to default value
166        @return int; default value
167        @raise AssertionError
168        """
169        assert x == self._magic, \
170            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)
171        return super(HPackMagicBitField, self).any2i(pkt, self._magic)
172
173
174class AbstractUVarIntField(fields.Field):
175    """AbstractUVarIntField represents an integer as defined in RFC7541
176    """
177
178    __slots__ = ['_max_value', 'size', 'rev']
179    """
180    :var int size: the bit length of the prefix of this AbstractUVarIntField. It
181      represents the complement of the number of MSB that are used in the
182      current byte for other purposes by some other BitFields
183    :var int _max_value: the maximum value that can be stored in the
184      sole prefix. If the integer equals or exceeds this value, the max prefix
185      value is assigned to the size first bits and the multibyte representation
186      is used
187    :var bool rev: is a fake property, also emulated for the sake of
188      compatibility with Bitfields
189    """
190
191    def __init__(self, name, default, size):
192        # type: (str, Optional[int], int) -> None
193        """
194        @param str name: the name of this field instance
195        @param int|None default: positive, null or None default value for this field instance.
196        @param int size: the number of bits to consider in the first byte. Valid range is ]0;8]
197        @return None
198        @raise AssertionError
199        """
200        assert(default is None or (isinstance(default, six.integer_types) and default >= 0))
201        assert(0 < size <= 8)
202        super(AbstractUVarIntField, self).__init__(name, default)
203        self.size = size
204        self._max_value = (1 << self.size) - 1
205
206        # Configuring the fake property that is useless for this class but that is
207        # expected from BitFields
208        self.rev = False
209
210    def h2i(self, pkt, x):
211        # type: (Optional[packet.Packet], Optional[int]) -> Optional[int]
212        """
213        @param packet.Packet|None pkt: unused.
214        @param int|None x: the value to convert.
215        @return int|None: the converted value.
216        @raise AssertionError
217        """
218        assert(not isinstance(x, six.integer_types) or x >= 0)
219        return x
220
221    def i2h(self, pkt, x):
222        # type: (Optional[packet.Packet], Optional[int]) -> Optional[int]
223        """
224        @param packet.Packet|None pkt: unused.
225        @param int|None x: the value to convert.
226        @return: int|None: the converted value.
227        """
228        return x
229
230    def _detect_multi_byte(self, fb):
231        # type: (str) -> bool
232        """ _detect_multi_byte returns whether the AbstractUVarIntField is represented on
233          multiple bytes or not.
234
235          A multibyte representation is indicated by all of the first size bits being set
236
237        @param str fb: first byte, as a character.
238        @return bool: True if multibyte repr detected, else False.
239        @raise AssertionError
240        """
241        assert(len(fb) == 1)
242        return (ord(fb) & self._max_value) == self._max_value
243
244    def _parse_multi_byte(self, s):
245        # type: (str) -> int
246        """ _parse_multi_byte parses x as a multibyte representation to get the
247          int value of this AbstractUVarIntField.
248
249        @param str s: the multibyte string to parse.
250        @return int: The parsed int value represented by this AbstractUVarIntField.
251        @raise: AssertionError
252        @raise: Scapy_Exception if the input value encodes an integer larger than 1<<64
253        """
254
255        assert(len(s) >= 2)
256
257        l = len(s)
258
259        value = 0
260        i = 1
261        byte = ord(s[i])
262        # For CPU sake, stops at an arbitrary large number!
263        max_value = 1 << 64
264        # As long as the MSG is set, an another byte must be read
265        while byte & 0x80:
266            value += (byte ^ 0x80) << (7 * (i - 1))
267            if value > max_value:
268                raise error.Scapy_Exception(
269                    'out-of-bound value: the string encodes a value that is too large (>2^{64}): {}'.format(value)
270                )
271            i += 1
272            assert i < l, 'EINVAL: x: out-of-bound read: the string ends before the AbstractUVarIntField!'
273            byte = ord(s[i])
274        value += byte << (7 * (i - 1))
275        value += self._max_value
276
277        assert(value >= 0)
278        return value
279
280    def m2i(self, pkt, x):
281        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> int
282        """
283          A tuple is expected for the "x" param only if "size" is different than 8. If a tuple is received, some bits
284          were consumed by another field. This field consumes the remaining bits, therefore the int of the tuple must
285          equal "size".
286
287        @param packet.Packet|None pkt: unused.
288        @param str|(str, int) x: the string to convert. If bits were consumed by a previous bitfield-compatible field.
289        @raise AssertionError
290        """
291        assert(isinstance(x, str) or (isinstance(x, tuple) and x[1] >= 0))
292
293        if isinstance(x, tuple):
294            assert (8 - x[1]) == self.size, 'EINVAL: x: not enough bits remaining in current byte to read the prefix'
295            val = x[0]
296        else:
297            assert isinstance(x, str) and self.size == 8, 'EINVAL: x: tuple expected when prefix_len is not a full byte'
298            val = x
299
300        if self._detect_multi_byte(val[0]):
301            ret = self._parse_multi_byte(val)
302        else:
303            ret = ord(val[0]) & self._max_value
304
305        assert(ret >= 0)
306        return ret
307
308    def i2m(self, pkt, x):
309        # type: (Optional[packet.Packet], int) -> str
310        """
311        @param packet.Packet|None pkt: unused.
312        @param int x: the value to convert.
313        @return str: the converted value.
314        @raise AssertionError
315        """
316        assert(x >= 0)
317
318        if x < self._max_value:
319            return chr(x)
320        else:
321            # The sl list join is a performance trick, because string
322            # concatenation is not efficient with Python immutable strings
323            sl = [chr(self._max_value)]
324            x -= self._max_value
325            while x >= 0x80:
326                sl.append(chr(0x80 | (x & 0x7F)))
327                x >>= 7
328            sl.append(chr(x))
329            return ''.join(sl)
330
331    def any2i(self, pkt, x):
332        # type: (Optional[packet.Packet], Union[None, str, int]) -> Optional[int]
333        """
334          A "x" value as a string is parsed as a binary encoding of a UVarInt. An int is considered an internal value.
335          None is returned as is.
336
337        @param packet.Packet|None pkt: the packet containing this field; probably unused.
338        @param str|int|None x: the value to convert.
339        @return int|None: the converted value.
340        @raise AssertionError
341        """
342        if isinstance(x, type(None)):
343            return x
344        if isinstance(x, six.integer_types):
345            assert(x >= 0)
346            ret = self.h2i(pkt, x)
347            assert(isinstance(ret, six.integer_types) and ret >= 0)
348            return ret
349        elif isinstance(x, str):
350            ret = self.m2i(pkt, x)
351            assert (isinstance(ret, six.integer_types) and ret >= 0)
352            return ret
353        assert False, 'EINVAL: x: No idea what the parameter format is'
354
355    def i2repr(self, pkt, x):
356        # type: (Optional[packet.Packet], Optional[int]) -> str
357        """
358        @param packet.Packet|None pkt: probably unused.
359        @param x: int|None: the positive, null or none value to convert.
360        @return str: the representation of the value.
361        """
362        return repr(self.i2h(pkt, x))
363
364    def addfield(self, pkt, s, val):
365        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> str
366        """ An AbstractUVarIntField prefix always consumes the remaining bits
367          of a BitField;if no current BitField is in use (no tuple in
368          entry) then the prefix length is 8 bits and the whole byte is to
369          be consumed
370        @param packet.Packet|None pkt: the packet containing this field. Probably unused.
371        @param str|(str, int, long) s: the string to append this field to. A tuple indicates that some bits were already
372          generated by another bitfield-compatible field. This MUST be the case if "size" is not 8. The int is the
373          number of bits already generated in the first byte of the str. The long is the value that was generated by the
374          previous bitfield-compatible fields.
375        @param int val: the positive or null value to be added.
376        @return str: s concatenated with the machine representation of this field.
377        @raise AssertionError
378        """
379        assert(val >= 0)
380        if isinstance(s, str):
381            assert self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte'
382            return s + self.i2m(pkt, val)
383
384        # s is a tuple
385        assert(s[1] >= 0)
386        assert(s[2] >= 0)
387        assert (8 - s[1]) == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix'
388
389        if val >= self._max_value:
390            return s[0] + chr((s[2] << self.size) + self._max_value) + self.i2m(pkt, val)[1:]
391        # This AbstractUVarIntField is only one byte long; setting the prefix value
392        # and appending the resulting byte to the string
393        return s[0] + chr((s[2] << self.size) + ord(self.i2m(pkt, val)))
394
395    @staticmethod
396    def _detect_bytelen_from_str(s):
397        # type: (str) -> int
398        """ _detect_bytelen_from_str returns the length of the machine
399          representation of an AbstractUVarIntField starting at the beginning
400          of s and which is assumed to expand over multiple bytes
401          (value > _max_prefix_value).
402
403        @param str s: the string to parse. It is assumed that it is a multibyte int.
404        @return The bytelength of the AbstractUVarIntField.
405        @raise AssertionError
406        """
407        assert(len(s) >= 2)
408        l = len(s)
409
410        i = 1
411        while ord(s[i]) & 0x80 > 0:
412            i += 1
413            assert i < l, 'EINVAL: s: out-of-bound read: unfinished AbstractUVarIntField detected'
414        ret = i + 1
415
416        assert(ret >= 0)
417        return ret
418
419    def i2len(self, pkt, x):
420        # type: (Optional[packet.Packet], int) -> int
421        """
422        @param packet.Packet|None pkt: unused.
423        @param int x: the positive or null value whose binary size if requested.
424        @raise AssertionError
425        """
426        assert(x >= 0)
427        if x < self._max_value:
428            return 1
429
430        # x is expressed over multiple bytes
431        x -= self._max_value
432        i = 1
433        if x == 0:
434            i += 1
435        while x > 0:
436            x >>= 7
437            i += 1
438
439        ret = i
440        assert(ret >= 0)
441        return ret
442
443    def getfield(self, pkt, s):
444        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> Tuple[str, int]
445        """
446        @param packet.Packet|None pkt: the packet instance containing this field; probably unused.
447        @param str|(str, int) s: the input value to get this field value from. If size is 8, s is a string, else
448        it is a tuple containing the value and an int indicating the number of bits already consumed in the first byte
449        of the str. The number of remaining bits to consume in the first byte must be equal to "size".
450        @return (str, int): the remaining bytes of s and the parsed value.
451        @raise AssertionError
452        """
453        if isinstance(s, tuple):
454            assert(len(s) == 2)
455            temp = s  # type: Tuple[str, int]
456            ts, ti = temp
457            assert(ti >= 0)
458            assert 8 - ti == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix'
459            val = ts
460        else:
461            assert isinstance(s, str) and self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte'
462            val = s
463
464        if self._detect_multi_byte(val[0]):
465            l = self._detect_bytelen_from_str(val)
466        else:
467            l = 1
468
469        ret = val[l:], self.m2i(pkt, s)
470        assert(ret[1] >= 0)
471        return ret
472
473    def randval(self):
474        # type: () -> volatile.VolatileValue
475        """
476        @return volatile.VolatileValue: a volatile value for this field "long"-compatible internal value.
477        """
478        return volatile.RandLong()
479
480
481class UVarIntField(AbstractUVarIntField):
482    def __init__(self, name, default, size):
483        # type: (str, int, int) -> None
484        """
485        @param str name: the name of this field instance.
486        @param default: the default value for this field instance. default must be positive or null.
487        @raise AssertionError
488        """
489        assert(default >= 0)
490        assert(0 < size <= 8)
491
492        super(UVarIntField, self).__init__(name, default, size)
493        self.size = size
494        self._max_value = (1 << self.size) - 1
495
496        # Configuring the fake property that is useless for this class but that is
497        # expected from BitFields
498        self.rev = False
499
500    def h2i(self, pkt, x):
501        # type: (Optional[packet.Packet], int) -> int
502        """ h2i is overloaded to restrict the acceptable x values (not None)
503
504        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.
505        @param int x: the value to convert.
506        @return int: the converted value.
507        @raise AssertionError
508        """
509        ret = super(UVarIntField, self).h2i(pkt, x)
510        assert(not isinstance(ret, type(None)) and ret >= 0)
511        return ret
512
513    def i2h(self, pkt, x):
514        # type: (Optional[packet.Packet], int) -> int
515        """ i2h is overloaded to restrict the acceptable x values (not None)
516
517        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.
518        @param int x: the value to convert.
519        @return int: the converted value.
520        @raise AssertionError
521        """
522        ret = super(UVarIntField, self).i2h(pkt, x)
523        assert(not isinstance(ret, type(None)) and ret >= 0)
524        return ret
525
526    def any2i(self, pkt, x):
527        # type: (Optional[packet.Packet], Union[str, int]) -> int
528        """ any2i is overloaded to restrict the acceptable x values (not None)
529
530        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.
531        @param str|int x: the value to convert.
532        @return int: the converted value.
533        @raise AssertionError
534        """
535        ret = super(UVarIntField, self).any2i(pkt, x)
536        assert(not isinstance(ret, type(None)) and ret >= 0)
537        return ret
538
539    def i2repr(self, pkt, x):
540        # type: (Optional[packet.Packet], int) -> str
541        """ i2repr is overloaded to restrict the acceptable x values (not None)
542
543        @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.
544        @param int x: the value to convert.
545        @return str: the converted value.
546        """
547        return super(UVarIntField, self).i2repr(pkt, x)
548
549
550class FieldUVarLenField(AbstractUVarIntField):
551    __slots__ = ['_length_of', '_adjust']
552
553    def __init__(self, name, default, size, length_of, adjust=lambda x: x):
554        # type: (str, Optional[int], int, str, Callable[[int], int]) -> None
555        """ Initializes a FieldUVarLenField
556
557        @param str name: The name of this field instance.
558        @param int|None default: the default value of this field instance.
559        @param int size: the number of bits that are occupied by this field in the first byte of a binary string.
560          size must be in the range ]0;8].
561        @param str length_of: The name of the field this field value is measuring/representing.
562        @param callable adjust: A function that modifies the value computed from the "length_of" field.
563
564        adjust can be used for instance to add a constant to the length_of field
565         length. For instance, let's say that i2len of the length_of field
566         returns 2. If adjust is lambda x: x+1 In that case, this field will
567         value 3 at build time.
568        @return None
569        @raise AssertionError
570        """
571        assert(default is None or default >= 0)
572        assert(0 < size <= 8)
573
574        super(FieldUVarLenField, self).__init__(name, default, size)
575        self._length_of = length_of
576        self._adjust = adjust
577
578    def addfield(self, pkt, s, val):
579        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], Optional[int]) -> str
580        """
581        @param packet.Packet|None pkt: the packet instance containing this field instance. This parameter must not be
582          None if the val parameter is.
583        @param str|(str, int, long) s: the string to append this field to. A tuple indicates that some bits were already
584          generated by another bitfield-compatible field. This MUST be the case if "size" is not 8. The int is the
585          number of bits already generated in the first byte of the str. The long is the value that was generated by the
586          previous bitfield-compatible fields.
587        @param int|None val: the positive or null value to be added. If None, the value is computed from pkt.
588        @return str: s concatenated with the machine representation of this field.
589        @raise AssertionError
590        """
591        if val is None:
592            assert isinstance(pkt, packet.Packet), \
593                'EINVAL: pkt: Packet expected when val is None; received {}'.format(type(pkt))
594            val = self._compute_value(pkt)
595        return super(FieldUVarLenField, self).addfield(pkt, s, val)
596
597    def i2m(self, pkt, x):
598        # type: (Optional[packet.Packet], Optional[int]) -> str
599        """
600        @param packet.Packet|None pkt: the packet instance containing this field instance. This parameter must not be
601          None if the x parameter is.
602        @param int|None x: the positive or null value to be added. If None, the value is computed from pkt.
603        @return str
604        @raise AssertionError
605        """
606        if x is None:
607            assert isinstance(pkt, packet.Packet), \
608                'EINVAL: pkt: Packet expected when x is None; received {}'.format(type(pkt))
609            x = self._compute_value(pkt)
610        return super(FieldUVarLenField, self).i2m(pkt, x)
611
612    def _compute_value(self, pkt):
613        # type: (packet.Packet) -> int
614        """ Computes the value of this field based on the provided packet and
615        the length_of field and the adjust callback
616
617        @param packet.Packet pkt: the packet from which is computed this field value.
618        @return int: the computed value for this field.
619        @raise KeyError: the packet nor its payload do not contain an attribute
620          with the length_of name.
621        @raise AssertionError
622        @raise KeyError if _length_of is not one of pkt fields
623        """
624        fld, fval = pkt.getfield_and_val(self._length_of)
625        val = fld.i2len(pkt, fval)
626        ret = self._adjust(val)
627        assert(ret >= 0)
628        return ret
629
630########################################################################################################################
631################################################ HPACK String Fields ###################################################
632########################################################################################################################
633
634class HPackStringsInterface(six.with_metaclass(abc.ABCMeta, Sized)):
635    @abc.abstractmethod
636    def __str__(self): pass
637
638    @abc.abstractmethod
639    def origin(self): pass
640
641    @abc.abstractmethod
642    def __len__(self): pass
643
644
645class HPackLiteralString(HPackStringsInterface):
646    """ HPackLiteralString is a string. This class is used as a marker and
647    implements an interface in common with HPackZString
648    """
649    __slots__ = ['_s']
650
651    def __init__(self, s):
652        # type: (str) -> None
653        self._s = s
654
655    def __str__(self):
656        # type: () -> str
657        return self._s
658
659    def origin(self):
660        # type: () -> str
661        return self._s
662
663    def __len__(self):
664        # type: () -> int
665        return len(self._s)
666
667
668class EOS(object):
669    """ Simple "marker" to designate the End Of String symbol in the huffman table
670    """
671
672
673class HuffmanNode(object):
674    """ HuffmanNode is an entry of the binary tree used for encoding/decoding
675    HPack compressed HTTP/2 headers
676    """
677
678    __slots__ = ['l', 'r']
679    """@var l: the left branch of this node
680    @var r: the right branch of this Node
681
682    These variables can value None (leaf node), another HuffmanNode, or a
683     symbol. Symbols are either a character or the End Of String symbol (class
684     EOS)
685    """
686
687    def __init__(self, l, r):
688        # type: (Union[None, HuffmanNode, EOS, str], Union[None, HuffmanNode, EOS, str]) -> None
689        self.l = l
690        self.r = r
691
692    def __getitem__(self, b):
693        # type: (int) -> Union[None, HuffmanNode, EOS, str]
694        return self.r if b else self.l
695
696    def __setitem__(self, b, val):
697        # type: (int, Union[None, HuffmanNode, EOS, str]) -> None
698        if b:
699            self.r = val
700        else:
701            self.l = val
702
703    def __str__(self):
704        # type: () -> str
705        return self.__repr__()
706
707    def __repr__(self):
708        # type: () -> str
709        return '({}, {})'.format(self.l, self.r)
710
711
712class InvalidEncodingException(Exception):
713    """ InvalidEncodingException is raised when a supposedly huffman-encoded
714     string is decoded and a decoding error arises
715    """
716
717
718class HPackZString(HPackStringsInterface):
719    __slots__ = ['_s', '_encoded']
720
721    # From RFC 7541
722    # Tuple is (code,code bitlength)
723    # The bitlength is required to know how long the left padding
724    # (implicit 0's) there are
725    static_huffman_code = [
726        (0x1ff8, 13),
727        (0x7fffd8, 23),
728        (0xfffffe2, 28),
729        (0xfffffe3, 28),
730        (0xfffffe4, 28),
731        (0xfffffe5, 28),
732        (0xfffffe6, 28),
733        (0xfffffe7, 28),
734        (0xfffffe8, 28),
735        (0xffffea, 24),
736        (0x3ffffffc, 30),
737        (0xfffffe9, 28),
738        (0xfffffea, 28),
739        (0x3ffffffd, 30),
740        (0xfffffeb, 28),
741        (0xfffffec, 28),
742        (0xfffffed, 28),
743        (0xfffffee, 28),
744        (0xfffffef, 28),
745        (0xffffff0, 28),
746        (0xffffff1, 28),
747        (0xffffff2, 28),
748        (0x3ffffffe, 30),
749        (0xffffff3, 28),
750        (0xffffff4, 28),
751        (0xffffff5, 28),
752        (0xffffff6, 28),
753        (0xffffff7, 28),
754        (0xffffff8, 28),
755        (0xffffff9, 28),
756        (0xffffffa, 28),
757        (0xffffffb, 28),
758        (0x14, 6),
759        (0x3f8, 10),
760        (0x3f9, 10),
761        (0xffa, 12),
762        (0x1ff9, 13),
763        (0x15, 6),
764        (0xf8, 8),
765        (0x7fa, 11),
766        (0x3fa, 10),
767        (0x3fb, 10),
768        (0xf9, 8),
769        (0x7fb, 11),
770        (0xfa, 8),
771        (0x16, 6),
772        (0x17, 6),
773        (0x18, 6),
774        (0x0, 5),
775        (0x1, 5),
776        (0x2, 5),
777        (0x19, 6),
778        (0x1a, 6),
779        (0x1b, 6),
780        (0x1c, 6),
781        (0x1d, 6),
782        (0x1e, 6),
783        (0x1f, 6),
784        (0x5c, 7),
785        (0xfb, 8),
786        (0x7ffc, 15),
787        (0x20, 6),
788        (0xffb, 12),
789        (0x3fc, 10),
790        (0x1ffa, 13),
791        (0x21, 6),
792        (0x5d, 7),
793        (0x5e, 7),
794        (0x5f, 7),
795        (0x60, 7),
796        (0x61, 7),
797        (0x62, 7),
798        (0x63, 7),
799        (0x64, 7),
800        (0x65, 7),
801        (0x66, 7),
802        (0x67, 7),
803        (0x68, 7),
804        (0x69, 7),
805        (0x6a, 7),
806        (0x6b, 7),
807        (0x6c, 7),
808        (0x6d, 7),
809        (0x6e, 7),
810        (0x6f, 7),
811        (0x70, 7),
812        (0x71, 7),
813        (0x72, 7),
814        (0xfc, 8),
815        (0x73, 7),
816        (0xfd, 8),
817        (0x1ffb, 13),
818        (0x7fff0, 19),
819        (0x1ffc, 13),
820        (0x3ffc, 14),
821        (0x22, 6),
822        (0x7ffd, 15),
823        (0x3, 5),
824        (0x23, 6),
825        (0x4, 5),
826        (0x24, 6),
827        (0x5, 5),
828        (0x25, 6),
829        (0x26, 6),
830        (0x27, 6),
831        (0x6, 5),
832        (0x74, 7),
833        (0x75, 7),
834        (0x28, 6),
835        (0x29, 6),
836        (0x2a, 6),
837        (0x7, 5),
838        (0x2b, 6),
839        (0x76, 7),
840        (0x2c, 6),
841        (0x8, 5),
842        (0x9, 5),
843        (0x2d, 6),
844        (0x77, 7),
845        (0x78, 7),
846        (0x79, 7),
847        (0x7a, 7),
848        (0x7b, 7),
849        (0x7ffe, 15),
850        (0x7fc, 11),
851        (0x3ffd, 14),
852        (0x1ffd, 13),
853        (0xffffffc, 28),
854        (0xfffe6, 20),
855        (0x3fffd2, 22),
856        (0xfffe7, 20),
857        (0xfffe8, 20),
858        (0x3fffd3, 22),
859        (0x3fffd4, 22),
860        (0x3fffd5, 22),
861        (0x7fffd9, 23),
862        (0x3fffd6, 22),
863        (0x7fffda, 23),
864        (0x7fffdb, 23),
865        (0x7fffdc, 23),
866        (0x7fffdd, 23),
867        (0x7fffde, 23),
868        (0xffffeb, 24),
869        (0x7fffdf, 23),
870        (0xffffec, 24),
871        (0xffffed, 24),
872        (0x3fffd7, 22),
873        (0x7fffe0, 23),
874        (0xffffee, 24),
875        (0x7fffe1, 23),
876        (0x7fffe2, 23),
877        (0x7fffe3, 23),
878        (0x7fffe4, 23),
879        (0x1fffdc, 21),
880        (0x3fffd8, 22),
881        (0x7fffe5, 23),
882        (0x3fffd9, 22),
883        (0x7fffe6, 23),
884        (0x7fffe7, 23),
885        (0xffffef, 24),
886        (0x3fffda, 22),
887        (0x1fffdd, 21),
888        (0xfffe9, 20),
889        (0x3fffdb, 22),
890        (0x3fffdc, 22),
891        (0x7fffe8, 23),
892        (0x7fffe9, 23),
893        (0x1fffde, 21),
894        (0x7fffea, 23),
895        (0x3fffdd, 22),
896        (0x3fffde, 22),
897        (0xfffff0, 24),
898        (0x1fffdf, 21),
899        (0x3fffdf, 22),
900        (0x7fffeb, 23),
901        (0x7fffec, 23),
902        (0x1fffe0, 21),
903        (0x1fffe1, 21),
904        (0x3fffe0, 22),
905        (0x1fffe2, 21),
906        (0x7fffed, 23),
907        (0x3fffe1, 22),
908        (0x7fffee, 23),
909        (0x7fffef, 23),
910        (0xfffea, 20),
911        (0x3fffe2, 22),
912        (0x3fffe3, 22),
913        (0x3fffe4, 22),
914        (0x7ffff0, 23),
915        (0x3fffe5, 22),
916        (0x3fffe6, 22),
917        (0x7ffff1, 23),
918        (0x3ffffe0, 26),
919        (0x3ffffe1, 26),
920        (0xfffeb, 20),
921        (0x7fff1, 19),
922        (0x3fffe7, 22),
923        (0x7ffff2, 23),
924        (0x3fffe8, 22),
925        (0x1ffffec, 25),
926        (0x3ffffe2, 26),
927        (0x3ffffe3, 26),
928        (0x3ffffe4, 26),
929        (0x7ffffde, 27),
930        (0x7ffffdf, 27),
931        (0x3ffffe5, 26),
932        (0xfffff1, 24),
933        (0x1ffffed, 25),
934        (0x7fff2, 19),
935        (0x1fffe3, 21),
936        (0x3ffffe6, 26),
937        (0x7ffffe0, 27),
938        (0x7ffffe1, 27),
939        (0x3ffffe7, 26),
940        (0x7ffffe2, 27),
941        (0xfffff2, 24),
942        (0x1fffe4, 21),
943        (0x1fffe5, 21),
944        (0x3ffffe8, 26),
945        (0x3ffffe9, 26),
946        (0xffffffd, 28),
947        (0x7ffffe3, 27),
948        (0x7ffffe4, 27),
949        (0x7ffffe5, 27),
950        (0xfffec, 20),
951        (0xfffff3, 24),
952        (0xfffed, 20),
953        (0x1fffe6, 21),
954        (0x3fffe9, 22),
955        (0x1fffe7, 21),
956        (0x1fffe8, 21),
957        (0x7ffff3, 23),
958        (0x3fffea, 22),
959        (0x3fffeb, 22),
960        (0x1ffffee, 25),
961        (0x1ffffef, 25),
962        (0xfffff4, 24),
963        (0xfffff5, 24),
964        (0x3ffffea, 26),
965        (0x7ffff4, 23),
966        (0x3ffffeb, 26),
967        (0x7ffffe6, 27),
968        (0x3ffffec, 26),
969        (0x3ffffed, 26),
970        (0x7ffffe7, 27),
971        (0x7ffffe8, 27),
972        (0x7ffffe9, 27),
973        (0x7ffffea, 27),
974        (0x7ffffeb, 27),
975        (0xffffffe, 28),
976        (0x7ffffec, 27),
977        (0x7ffffed, 27),
978        (0x7ffffee, 27),
979        (0x7ffffef, 27),
980        (0x7fffff0, 27),
981        (0x3ffffee, 26),
982        (0x3fffffff, 30)
983    ]
984
985    static_huffman_tree = None
986
987    @classmethod
988    def _huffman_encode_char(cls, c):
989        # type: (Union[str, EOS]) -> Tuple[int, int]
990        """ huffman_encode_char assumes that the static_huffman_tree was
991        previously initialized
992
993        @param str|EOS c: a symbol to encode
994        @return (int, int): the bitstring of the symbol and its bitlength
995        @raise AssertionError
996        """
997        if isinstance(c, EOS):
998            return cls.static_huffman_code[-1]
999        else:
1000            assert(len(c) == 1)
1001        return cls.static_huffman_code[ord(c)]
1002
1003    @classmethod
1004    def huffman_encode(cls, s):
1005        # type: (str) -> Tuple[int, int]
1006        """ huffman_encode returns the bitstring and the bitlength of the
1007        bitstring representing the string provided as a parameter
1008
1009        @param str s: the string to encode
1010        @return (int, int): the bitstring of s and its bitlength
1011        @raise AssertionError
1012        """
1013        i = 0
1014        ibl = 0
1015        for c in s:
1016            val, bl = cls._huffman_encode_char(c)
1017            i = (i << bl) + val
1018            ibl += bl
1019
1020        padlen = 8 - (ibl % 8)
1021        if padlen != 8:
1022            val, bl = cls._huffman_encode_char(EOS())
1023            i = (i << padlen) + (val >> (bl - padlen))
1024            ibl += padlen
1025
1026        ret = i, ibl
1027        assert(ret[0] >= 0)
1028        assert (ret[1] >= 0)
1029        return ret
1030
1031    @classmethod
1032    def huffman_decode(cls, i, ibl):
1033        # type: (int, int) -> str
1034        """ huffman_decode decodes the bitstring provided as parameters.
1035
1036        @param int i: the bitstring to decode
1037        @param int ibl: the bitlength of i
1038        @return str: the string decoded from the bitstring
1039        @raise AssertionError, InvalidEncodingException
1040        """
1041        assert(i >= 0)
1042        assert(ibl >= 0)
1043
1044        if isinstance(cls.static_huffman_tree, type(None)):
1045            cls.huffman_compute_decode_tree()
1046        assert(not isinstance(cls.static_huffman_tree, type(None)))
1047
1048        s = []
1049        j = 0
1050        interrupted = False
1051        cur = cls.static_huffman_tree
1052        cur_sym = 0
1053        cur_sym_bl = 0
1054        while j < ibl:
1055            b = (i >> (ibl - j - 1)) & 1
1056            cur_sym = (cur_sym << 1) + b
1057            cur_sym_bl += 1
1058            elmt = cur[b]
1059
1060            if isinstance(elmt, HuffmanNode):
1061                interrupted = True
1062                cur = elmt
1063                if isinstance(cur, type(None)):
1064                    raise AssertionError()
1065            elif isinstance(elmt, EOS):
1066                raise InvalidEncodingException('Huffman decoder met the full EOS symbol')
1067            elif isinstance(elmt, str):
1068                interrupted = False
1069                s.append(elmt)
1070                cur = cls.static_huffman_tree
1071                cur_sym = 0
1072                cur_sym_bl = 0
1073            else:
1074                raise InvalidEncodingException('Should never happen, so incidentally it will')
1075            j += 1
1076
1077        if interrupted:
1078            # Interrupted values true if the bitstring ends in the middle of a
1079            # symbol; this symbol must be, according to RFC7541 par5.2 the MSB
1080            # of the EOS symbol
1081            if cur_sym_bl > 7:
1082                raise InvalidEncodingException('Huffman decoder is detecting padding longer than 7 bits')
1083            eos_symbol = cls.static_huffman_code[-1]
1084            eos_msb = eos_symbol[0] >> (eos_symbol[1] - cur_sym_bl)
1085            if eos_msb != cur_sym:
1086                raise InvalidEncodingException('Huffman decoder is detecting unexpected padding format')
1087        return ''.join(s)
1088
1089    @classmethod
1090    def huffman_conv2str(cls, bit_str, bit_len):
1091        # type: (int, int) -> str
1092        """ huffman_conv2str converts a bitstring of bit_len bitlength into a
1093        binary string. It DOES NOT compress/decompress the bitstring!
1094
1095        @param int bit_str: the bitstring to convert.
1096        @param int bit_len: the bitlength of bit_str.
1097        @return str: the converted bitstring as a bytestring.
1098        @raise AssertionError
1099        """
1100        assert(bit_str >= 0)
1101        assert(bit_len >= 0)
1102
1103        byte_len = bit_len/8
1104        rem_bit = bit_len % 8
1105        if rem_bit != 0:
1106            bit_str <<= 8 - rem_bit
1107            byte_len += 1
1108
1109        # As usual the list/join tricks is a performance trick to build
1110        # efficiently a Python string
1111        s = []  # type: List[str]
1112        i = 0
1113        while i < byte_len:
1114            s.insert(0, chr((bit_str >> (i*8)) & 0xFF))
1115            i += 1
1116        return ''.join(s)
1117
1118    @classmethod
1119    def huffman_conv2bitstring(cls, s):
1120        # type: (str) -> Tuple[int, int]
1121        """ huffman_conv2bitstring converts a string into its bitstring
1122        representation. It returns a tuple: the bitstring and its bitlength.
1123        This function DOES NOT compress/decompress the string!
1124
1125        @param str s: the bytestring to convert.
1126        @return (int, int): the bitstring of s, and its bitlength.
1127        @raise AssertionError
1128        """
1129        i = 0
1130        ibl = len(s) * 8
1131        for c in s:
1132            i = (i << 8) + ord(c)
1133
1134        ret = i, ibl
1135        assert(ret[0] >= 0)
1136        assert(ret[1] >= 0)
1137        return ret
1138
1139    @classmethod
1140    def huffman_compute_decode_tree(cls):
1141        # type: () -> None
1142        """ huffman_compute_decode_tree initializes/builds the static_huffman_tree
1143
1144        @return None
1145        @raise InvalidEncodingException if there is an encoding problem
1146        """
1147        cls.static_huffman_tree = HuffmanNode(None, None)
1148        i = 0
1149        for entry in cls.static_huffman_code:
1150            parent = cls.static_huffman_tree
1151            for idx in range(entry[1] - 1, -1, -1):
1152                b = (entry[0] >> idx) & 1
1153                if isinstance(parent[b], str):
1154                    raise InvalidEncodingException('Huffman unique prefix violation :/')
1155                if idx == 0:
1156                    parent[b] = chr(i) if i < 256 else EOS()
1157                elif parent[b] is None:
1158                    parent[b] = HuffmanNode(None, None)
1159                parent = parent[b]
1160            i += 1
1161
1162    def __init__(self, s):
1163        # type: (str) -> None
1164        self._s = s
1165        i, ibl = type(self).huffman_encode(s)
1166        self._encoded = type(self).huffman_conv2str(i, ibl)
1167
1168    def __str__(self):
1169        # type: () -> str
1170        return self._encoded
1171
1172    def origin(self):
1173        # type: () -> str
1174        return self._s
1175
1176    def __len__(self):
1177        # type: () -> int
1178        return len(self._encoded)
1179
1180
1181class HPackStrLenField(fields.Field):
1182    """ HPackStrLenField is a StrLenField variant specialized for HTTP/2 HPack
1183
1184    This variant uses an internal representation that implements HPackStringsInterface.
1185    """
1186    __slots__ = ['_length_from', '_type_from']
1187
1188    def __init__(self, name, default, length_from, type_from):
1189        # type: (str, HPackStringsInterface, Callable[[packet.Packet], int], str) -> None
1190        super(HPackStrLenField, self).__init__(name, default)
1191        self._length_from = length_from
1192        self._type_from = type_from
1193
1194    def addfield(self, pkt, s, val):
1195        # type: (Optional[packet.Packet], str, HPackStringsInterface) -> str
1196        return s + self.i2m(pkt, val)
1197
1198    @staticmethod
1199    def _parse(t, s):
1200        # type: (bool, str) -> HPackStringsInterface
1201        """
1202        @param bool t: whether this string is a huffman compressed string.
1203        @param str s: the string to parse.
1204        @return HPackStringsInterface: either a HPackLiteralString or HPackZString, depending on t.
1205        @raise InvalidEncodingException
1206        """
1207        if t:
1208            i, ibl = HPackZString.huffman_conv2bitstring(s)
1209            return HPackZString(HPackZString.huffman_decode(i, ibl))
1210        return HPackLiteralString(s)
1211
1212    def getfield(self, pkt, s):
1213        # type: (packet.Packet, str) -> Tuple[str, HPackStringsInterface]
1214        """
1215        @param packet.Packet pkt: the packet instance containing this field instance.
1216        @param str s: the string to parse this field from.
1217        @return (str, HPackStringsInterface): the remaining string after this field was carved out & the extracted
1218          value.
1219        @raise KeyError if "type_from" is not a field of pkt or its payloads.
1220        @raise InvalidEncodingException
1221        """
1222        l = self._length_from(pkt)
1223        t = pkt.getfieldval(self._type_from) == 1
1224        return s[l:], self._parse(t, s[:l])
1225
1226    def i2h(self, pkt, x):
1227        # type: (Optional[packet.Packet], HPackStringsInterface) -> str
1228        fmt = ''
1229        if isinstance(x, HPackLiteralString):
1230            fmt = "HPackLiteralString({})"
1231        elif isinstance(x, HPackZString):
1232            fmt = "HPackZString({})"
1233        return fmt.format(x.origin())
1234
1235    def h2i(self, pkt, x):
1236        # type: (packet.Packet, str) -> HPackStringsInterface
1237        return HPackLiteralString(x)
1238
1239    def m2i(self, pkt, x):
1240        # type: (packet.Packet, str) -> HPackStringsInterface
1241        """
1242        @param packet.Packet pkt: the packet instance containing this field instance.
1243        @param str x: the string to parse.
1244        @return HPackStringsInterface: the internal type of the value parsed from x.
1245        @raise AssertionError
1246        @raise InvalidEncodingException
1247        @raise KeyError if _type_from is not one of pkt fields.
1248        """
1249        t = pkt.getfieldval(self._type_from)
1250        l = self._length_from(pkt)
1251
1252        assert t is not None and l is not None, 'Conversion from string impossible: no type or length specified'
1253
1254        return self._parse(t == 1, x[:l])
1255
1256    def any2i(self, pkt, x):
1257        # type: (Optional[packet.Packet], Union[str, HPackStringsInterface]) -> HPackStringsInterface
1258        """
1259        @param packet.Packet|None pkt: the packet instance containing this field instance.
1260        @param str|HPackStringsInterface x: the value to convert
1261        @return HPackStringsInterface: the Scapy internal value for this field
1262        @raise AssertionError, InvalidEncodingException
1263        """
1264        if isinstance(x, str):
1265            assert(isinstance(pkt, packet.Packet))
1266            return self.m2i(pkt, x)
1267        assert(isinstance(x, HPackStringsInterface))
1268        return x
1269
1270    def i2m(self, pkt, x):
1271        # type: (Optional[packet.Packet], HPackStringsInterface) -> str
1272        return str(x)
1273
1274    def i2len(self, pkt, x):
1275        # type: (Optional[packet.Packet], HPackStringsInterface) -> int
1276        return len(x)
1277
1278    def i2repr(self, pkt, x):
1279        # type: (Optional[packet.Packet], HPackStringsInterface) -> str
1280        return repr(self.i2h(pkt, x))
1281
1282########################################################################################################################
1283################################################ HPACK Packets #########################################################
1284########################################################################################################################
1285
1286class HPackHdrString(packet.Packet):
1287    """ HPackHdrString is a packet that that is serialized into a RFC7541 par5.2
1288    string literal repr.
1289    """
1290    name = 'HPack Header String'
1291    fields_desc = [
1292        fields.BitEnumField('type', None, 1, {0: 'Literal', 1: 'Compressed'}),
1293        FieldUVarLenField('len', None, 7, length_of='data'),
1294        HPackStrLenField(
1295            'data', HPackLiteralString(''),
1296            length_from=lambda pkt: pkt.getfieldval('len'),
1297            type_from='type'
1298        )
1299    ]
1300
1301    def guess_payload_class(self, payload):
1302        # type: (str) -> base_classes.Packet_metaclass
1303        # Trick to tell scapy that the remaining bytes of the currently
1304        # dissected string is not a payload of this packet but of some other
1305        # underlayer packet
1306        return config.conf.padding_layer
1307
1308    def self_build(self, field_pos_list=None):
1309        # type: (Any) -> str
1310        """self_build is overridden because type and len are determined at
1311        build time, based on the "data" field internal type
1312        """
1313        if self.getfieldval('type') is None:
1314            self.type = 1 if isinstance(self.getfieldval('data'), HPackZString) else 0
1315        return super(HPackHdrString, self).self_build(field_pos_list)
1316
1317
1318class HPackHeaders(packet.Packet):
1319    """HPackHeaders uses the "dispatch_hook" trick of Packet_metaclass to select
1320    the correct HPack header packet type. For this, the first byte of the string
1321    to dissect is snooped on.
1322    """
1323    @classmethod
1324    def dispatch_hook(cls, s=None, *_args, **_kwds):
1325        # type: (Optional[str], *Any, **Any) -> base_classes.Packet_metaclass
1326        """dispatch_hook returns the subclass of HPackHeaders that must be used
1327        to dissect the string.
1328        """
1329        if s is None:
1330            return config.conf.raw_layer
1331        fb = ord(s[0])
1332        if fb & 0x80 != 0:
1333            return HPackIndexedHdr
1334        if fb & 0x40 != 0:
1335            return HPackLitHdrFldWithIncrIndexing
1336        if fb & 0x20 != 0:
1337            return HPackDynamicSizeUpdate
1338        return HPackLitHdrFldWithoutIndexing
1339
1340    def guess_payload_class(self, payload):
1341        # type: (str) -> base_classes.Packet_metaclass
1342        return config.conf.padding_layer
1343
1344
1345class HPackIndexedHdr(HPackHeaders):
1346    """ HPackIndexedHdr implements RFC 7541 par6.1
1347    """
1348    name = 'HPack Indexed Header Field'
1349    fields_desc = [
1350        HPackMagicBitField('magic', 1, 1),
1351        UVarIntField('index', 2, 7)  # Default "2" is ":method GET"
1352    ]
1353
1354
1355class HPackLitHdrFldWithIncrIndexing(HPackHeaders):
1356    """ HPackLitHdrFldWithIncrIndexing implements RFC 7541 par6.2.1
1357    """
1358    name = 'HPack Literal Header With Incremental Indexing'
1359    fields_desc = [
1360        HPackMagicBitField('magic', 1, 2),
1361        UVarIntField('index', 0, 6),  # Default is New Name
1362        fields.ConditionalField(
1363            fields.PacketField('hdr_name', None, HPackHdrString),
1364            lambda pkt: pkt.getfieldval('index') == 0
1365        ),
1366        fields.PacketField('hdr_value', None, HPackHdrString)
1367    ]
1368
1369
1370class HPackLitHdrFldWithoutIndexing(HPackHeaders):
1371    """ HPackLitHdrFldWithIncrIndexing implements RFC 7541 par6.2.2
1372    and par6.2.3
1373    """
1374    name = 'HPack Literal Header Without Indexing (or Never Indexing)'
1375    fields_desc = [
1376        HPackMagicBitField('magic', 0, 3),
1377        fields.BitEnumField(
1378            'never_index', 0, 1,
1379            {0: "Don't Index", 1: 'Never Index'}
1380        ),
1381        UVarIntField('index', 0, 4),  # Default is New Name
1382        fields.ConditionalField(
1383            fields.PacketField('hdr_name', None, HPackHdrString),
1384            lambda pkt: pkt.getfieldval('index') == 0
1385        ),
1386        fields.PacketField('hdr_value', None, HPackHdrString)
1387    ]
1388
1389
1390class HPackDynamicSizeUpdate(HPackHeaders):
1391    """ HPackDynamicSizeUpdate implements RFC 7541 par6.3
1392    """
1393    name = 'HPack Dynamic Size Update'
1394    fields_desc = [
1395        HPackMagicBitField('magic', 1, 3),
1396        UVarIntField('max_size', 0, 5)
1397    ]
1398
1399########################################################################################################################
1400############################################# HTTP/2 Frames ############################################################
1401########################################################################################################################
1402
1403class H2FramePayload(packet.Packet):
1404    """ H2FramePayload is an empty class that is a super class of all Scapy
1405    HTTP/2 Frame Packets
1406    """
1407
1408############################################# HTTP/2 Data Frame Packets ################################################
1409
1410class H2DataFrame(H2FramePayload):
1411    """ H2DataFrame implements RFC7540 par6.1
1412    This packet is the Data Frame to use when there is no padding.
1413    """
1414    type_id = 0
1415    END_STREAM_FLAG = 0  # 0x1
1416    PADDED_FLAG = 3  # 0x8
1417    flags = {
1418        END_STREAM_FLAG: fields.MultiFlagsEntry('ES', 'End Stream'),
1419        PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded')
1420    }
1421
1422    name = 'HTTP/2 Data Frame'
1423    fields_desc = [
1424        fields.StrField('data', '')
1425    ]
1426
1427
1428class H2PaddedDataFrame(H2DataFrame):
1429    """ H2DataFrame implements RFC7540 par6.1
1430    This packet is the Data Frame to use when there is padding.
1431    """
1432    __slots__ = ['s_len']
1433
1434    name = 'HTTP/2 Padded Data Frame'
1435    fields_desc = [
1436        fields.FieldLenField('padlen', None, length_of='padding', fmt="B"),
1437        fields.StrLenField('data', '',
1438            length_from=lambda pkt: pkt.get_data_len()
1439        ),
1440        fields.StrLenField('padding', '',
1441            length_from=lambda pkt: pkt.getfieldval('padlen')
1442        )
1443    ]
1444
1445    def get_data_len(self):
1446        # type: () -> int
1447        """ get_data_len computes the length of the data field
1448
1449        To do this computation, the length of the padlen field and the actual
1450        padding is subtracted to the string that was provided to the pre_dissect
1451        fun of the pkt parameter
1452        @return int; length of the data part of the HTTP/2 frame packet provided as parameter
1453        @raise AssertionError
1454        """
1455        padding_len = self.getfieldval('padlen')
1456        fld, fval = self.getfield_and_val('padlen')
1457        padding_len_len = fld.i2len(self, fval)
1458
1459        ret = self.s_len - padding_len_len - padding_len
1460        assert(ret >= 0)
1461        return ret
1462
1463    def pre_dissect(self, s):
1464        # type: (str) -> str
1465        """pre_dissect is filling the s_len property of this instance. This
1466        property is later used during the getfield call of the "data" field when
1467        trying to evaluate the length of the StrLenField! This "trick" works
1468        because the underlayer packet (H2Frame) is assumed to override the
1469        "extract_padding" method and to only provide to this packet the data
1470        necessary for this packet. Tricky, tricky, will break some day probably!
1471        """
1472        self.s_len = len(s)
1473        return s
1474
1475
1476############################################# HTTP/2 Header Frame Packets ##############################################
1477
1478class H2AbstractHeadersFrame(H2FramePayload):
1479    """Superclass of all variants of HTTP/2 Header Frame Packets.
1480    May be used for type checking.
1481    """
1482
1483class H2HeadersFrame(H2AbstractHeadersFrame):
1484    """ H2HeadersFrame implements RFC 7540 par6.2 Headers Frame
1485    when there is no padding and no priority informations
1486
1487    The choice of decomposing into four classes is probably preferable to having
1488    numerous conditional fields based on the underlayer :/
1489    """
1490    type_id = 1
1491    END_STREAM_FLAG = 0  # 0x1
1492    END_HEADERS_FLAG = 2  # 0x4
1493    PADDED_FLAG = 3  # 0x8
1494    PRIORITY_FLAG = 5  # 0x20
1495    flags = {
1496        END_STREAM_FLAG: fields.MultiFlagsEntry('ES', 'End Stream'),
1497        END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers'),
1498        PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded'),
1499        PRIORITY_FLAG: fields.MultiFlagsEntry('+', 'Priority')
1500    }
1501
1502    name = 'HTTP/2 Headers Frame'
1503    fields_desc = [
1504        fields.PacketListField('hdrs', [], HPackHeaders)
1505    ]
1506
1507
1508class H2PaddedHeadersFrame(H2AbstractHeadersFrame):
1509    """ H2PaddedHeadersFrame is the variant of H2HeadersFrame where padding flag
1510    is set and priority flag is cleared
1511    """
1512    __slots__ = ['s_len']
1513
1514    name = 'HTTP/2 Headers Frame with Padding'
1515    fields_desc = [
1516        fields.FieldLenField('padlen', None, length_of='padding', fmt='B'),
1517        fields.PacketListField('hdrs', [], HPackHeaders,
1518            length_from=lambda pkt: pkt.get_hdrs_len()
1519        ),
1520        fields.StrLenField('padding', '',
1521            length_from=lambda pkt: pkt.getfieldval('padlen')
1522        )
1523    ]
1524
1525    def get_hdrs_len(self):
1526        # type: () -> int
1527        """ get_hdrs_len computes the length of the hdrs field
1528
1529        To do this computation, the length of the padlen field and the actual
1530        padding is subtracted to the string that was provided to the pre_dissect
1531        fun of the pkt parameter.
1532        @return int; length of the data part of the HTTP/2 frame packet provided as parameter
1533        @raise AssertionError
1534        """
1535        padding_len = self.getfieldval('padlen')
1536        fld, fval = self.getfield_and_val('padlen')
1537        padding_len_len = fld.i2len(self, fval)
1538
1539        ret = self.s_len - padding_len_len - padding_len
1540        assert(ret >= 0)
1541        return ret
1542
1543    def pre_dissect(self, s):
1544        # type: (str) -> str
1545        """pre_dissect is filling the s_len property of this instance. This
1546        property is later used during the parsing of the hdrs PacketListField
1547        when trying to evaluate the length of the PacketListField! This "trick"
1548        works because the underlayer packet (H2Frame) is assumed to override the
1549        "extract_padding" method and to only provide to this packet the data
1550        necessary for this packet. Tricky, tricky, will break some day probably!
1551        """
1552        self.s_len = len(s)
1553        return s
1554
1555
1556class H2PriorityHeadersFrame(H2AbstractHeadersFrame):
1557    """ H2PriorityHeadersFrame is the variant of H2HeadersFrame where priority flag
1558    is set and padding flag is cleared
1559    """
1560    __slots__ = ['s_len']
1561
1562    name = 'HTTP/2 Headers Frame with Priority'
1563    fields_desc = [
1564        fields.BitField('exclusive', 0, 1),
1565        fields.BitField('stream_dependency', 0, 31),
1566        fields.ByteField('weight', 0),
1567        # This PacketListField will consume all remaining bytes; not a problem
1568        # because the underlayer (H2Frame) overrides "extract_padding" so that
1569        # this Packet only get to parser what it needs to
1570        fields.PacketListField('hdrs', [], HPackHeaders),
1571    ]
1572
1573
1574class H2PaddedPriorityHeadersFrame(H2AbstractHeadersFrame):
1575    """ H2PaddedPriorityHeadersFrame is the variant of H2HeadersFrame where
1576    both priority and padding flags are set
1577    """
1578    __slots__ = ['s_len']
1579
1580    name = 'HTTP/2 Headers Frame with Padding and Priority'
1581    fields_desc = [
1582        fields.FieldLenField('padlen', None, length_of='padding', fmt='B'),
1583        fields.BitField('exclusive', 0, 1),
1584        fields.BitField('stream_dependency', 0, 31),
1585        fields.ByteField('weight', 0),
1586        fields.PacketListField('hdrs', [], HPackHeaders,
1587            length_from=lambda pkt: pkt.get_hdrs_len()
1588        ),
1589        fields.StrLenField('padding', '',
1590            length_from=lambda pkt: pkt.getfieldval('padlen')
1591        )
1592    ]
1593
1594    def get_hdrs_len(self):
1595        # type: () -> int
1596        """ get_hdrs_len computes the length of the hdrs field
1597
1598        To do this computation, the length of the padlen field, the priority
1599        information fields and the actual padding is subtracted to the string
1600        that was provided to the pre_dissect fun of the pkt parameter.
1601        @return int: the length of the hdrs field
1602        @raise AssertionError
1603        """
1604
1605        padding_len = self.getfieldval('padlen')
1606        fld, fval = self.getfield_and_val('padlen')
1607        padding_len_len = fld.i2len(self, fval)
1608        bit_cnt = self.get_field('exclusive').size
1609        bit_cnt += self.get_field('stream_dependency').size
1610        fld, fval = self.getfield_and_val('weight')
1611        weight_len = fld.i2len(self, fval)
1612        ret = (self.s_len
1613            - padding_len_len
1614            - padding_len
1615            - (bit_cnt / 8)
1616            - weight_len
1617        )
1618        assert(ret >= 0)
1619        return ret
1620
1621    def pre_dissect(self, s):
1622        # type: (str) -> str
1623        """pre_dissect is filling the s_len property of this instance. This
1624        property is later used during the parsing of the hdrs PacketListField
1625        when trying to evaluate the length of the PacketListField! This "trick"
1626        works because the underlayer packet (H2Frame) is assumed to override the
1627        "extract_padding" method and to only provide to this packet the data
1628        necessary for this packet. Tricky, tricky, will break some day probably!
1629        """
1630        self.s_len = len(s)
1631        return s
1632
1633########################################### HTTP/2 Priority Frame Packets ##############################################
1634
1635class H2PriorityFrame(H2FramePayload):
1636    """ H2PriorityFrame implements RFC 7540 par6.3
1637    """
1638    type_id = 2
1639    name = 'HTTP/2 Priority Frame'
1640    fields_desc = [
1641        fields.BitField('exclusive', 0, 1),
1642        fields.BitField('stream_dependency', 0, 31),
1643        fields.ByteField('weight', 0)
1644    ]
1645
1646################################################# HTTP/2 Errors ########################################################
1647
1648class H2ErrorCodes(object):
1649    """ H2ErrorCodes is an enumeration of the error codes defined in
1650    RFC7540 par7.
1651    This enumeration is not part of any frame because the error codes are in
1652    common with H2ResetFrame and H2GoAwayFrame.
1653    """
1654
1655    NO_ERROR = 0x0
1656    PROTOCOL_ERROR = 0x1
1657    INTERNAL_ERROR = 0x2
1658    FLOW_CONTROL_ERROR = 0x3
1659    SETTINGS_TIMEOUT = 0x4
1660    STREAM_CLOSED = 0x5
1661    FRAME_SIZE_ERROR = 0x6
1662    REFUSED_STREAM = 0x7
1663    CANCEL = 0x8
1664    COMPRESSION_ERROR = 0x9
1665    CONNECT_ERROR = 0xa
1666    ENHANCE_YOUR_CALM = 0xb
1667    INADEQUATE_SECURITY = 0xc
1668    HTTP_1_1_REQUIRED = 0xd
1669
1670    literal = {
1671        NO_ERROR: 'No error',
1672        PROTOCOL_ERROR: 'Protocol error',
1673        INTERNAL_ERROR: 'Internal error',
1674        FLOW_CONTROL_ERROR: 'Flow control error',
1675        SETTINGS_TIMEOUT: 'Settings timeout',
1676        STREAM_CLOSED: 'Stream closed',
1677        FRAME_SIZE_ERROR: 'Frame size error',
1678        REFUSED_STREAM: 'Refused stream',
1679        CANCEL: 'Cancel',
1680        COMPRESSION_ERROR: 'Compression error',
1681        CONNECT_ERROR: 'Control error',
1682        ENHANCE_YOUR_CALM: 'Enhance your calm',
1683        INADEQUATE_SECURITY: 'Inadequate security',
1684        HTTP_1_1_REQUIRED: 'HTTP/1.1 required'
1685    }
1686
1687
1688########################################### HTTP/2 Reset Frame Packets #################################################
1689
1690class H2ResetFrame(H2FramePayload):
1691    """ H2ResetFrame implements RFC 7540 par6.4
1692    """
1693    type_id = 3
1694    name = 'HTTP/2 Reset Frame'
1695    fields_desc = [
1696        fields.EnumField('error', 0, H2ErrorCodes.literal, fmt='!I')
1697    ]
1698
1699
1700########################################### HTTP/2 Settings Frame Packets ##############################################
1701
1702class H2Setting(packet.Packet):
1703    """ H2Setting implements a setting, as defined in RFC7540 par6.5.1
1704    """
1705    SETTINGS_HEADER_TABLE_SIZE = 0x1
1706    SETTINGS_ENABLE_PUSH = 0x2
1707    SETTINGS_MAX_CONCURRENT_STREAMS = 0x3
1708    SETTINGS_INITIAL_WINDOW_SIZE = 0x4
1709    SETTINGS_MAX_FRAME_SIZE = 0x5
1710    SETTINGS_MAX_HEADER_LIST_SIZE = 0x6
1711
1712    name = 'HTTP/2 Setting'
1713    fields_desc = [
1714        fields.EnumField('id', 0, {
1715            SETTINGS_HEADER_TABLE_SIZE: 'Header table size',
1716            SETTINGS_ENABLE_PUSH: 'Enable push',
1717            SETTINGS_MAX_CONCURRENT_STREAMS: 'Max concurrent streams',
1718            SETTINGS_INITIAL_WINDOW_SIZE: 'Initial window size',
1719            SETTINGS_MAX_FRAME_SIZE: 'Max frame size',
1720            SETTINGS_MAX_HEADER_LIST_SIZE: 'Max header list size'
1721        }, fmt='!H'),
1722        fields.IntField('value', 0)
1723    ]
1724
1725    def guess_payload_class(self, payload):
1726        # type: (str) -> base_classes.Packet_metaclass
1727        return config.conf.padding_layer
1728
1729
1730class H2SettingsFrame(H2FramePayload):
1731    """ H2SettingsFrame implements RFC7540 par6.5
1732    """
1733    type_id = 4
1734    ACK_FLAG = 0  # 0x1
1735    flags = {
1736        ACK_FLAG: fields.MultiFlagsEntry('A', 'ACK')
1737    }
1738
1739    name = 'HTTP/2 Settings Frame'
1740    fields_desc = [
1741        fields.PacketListField('settings', [], H2Setting)
1742    ]
1743
1744    def __init__(self, *args, **kwargs):
1745        """__init__ initializes this H2SettingsFrame
1746
1747        If a _pkt arg is provided (by keyword), then this is an initialization
1748        from a string to dissect and therefore the length of the string to
1749        dissect have distinctive characteristics that we might want to check.
1750        This is possible because the underlayer packet (H2Frame) overrides
1751        extract_padding method to provided only the string that must be parsed
1752        by this packet!
1753        @raise AssertionError
1754        """
1755
1756        # RFC7540 par6.5 p36
1757        assert(
1758            len(args) == 0 or (
1759                isinstance(args[0], str)
1760                and len(args[0]) % 6 == 0
1761            )
1762        ), 'Invalid settings frame; length is not a multiple of 6'
1763        super(H2SettingsFrame, self).__init__(*args, **kwargs)
1764
1765######################################## HTTP/2 Push Promise Frame Packets #############################################
1766
1767class H2PushPromiseFrame(H2FramePayload):
1768    """ H2PushPromiseFrame implements RFC7540 par6.6. This packet
1769    is the variant to use when the underlayer padding flag is cleared
1770    """
1771    type_id = 5
1772    END_HEADERS_FLAG = 2  # 0x4
1773    PADDED_FLAG = 3  # 0x8
1774    flags = {
1775        END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers'),
1776        PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded')
1777    }
1778
1779    name = 'HTTP/2 Push Promise Frame'
1780    fields_desc = [
1781        fields.BitField('reserved', 0, 1),
1782        fields.BitField('stream_id', 0, 31),
1783        fields.PacketListField('hdrs', [], HPackHeaders)
1784    ]
1785
1786
1787class H2PaddedPushPromiseFrame(H2PushPromiseFrame):
1788    """ H2PaddedPushPromiseFrame implements RFC7540 par6.6. This
1789    packet is the variant to use when the underlayer padding flag is set
1790    """
1791    __slots__ = ['s_len']
1792
1793    name = 'HTTP/2 Padded Push Promise Frame'
1794    fields_desc = [
1795        fields.FieldLenField('padlen', None, length_of='padding', fmt='B'),
1796        fields.BitField('reserved', 0, 1),
1797        fields.BitField('stream_id', 0, 31),
1798        fields.PacketListField('hdrs', [], HPackHeaders,
1799            length_from=lambda pkt: pkt.get_hdrs_len()
1800        ),
1801        fields.StrLenField('padding', '',
1802            length_from=lambda pkt: pkt.getfieldval('padlen')
1803        )
1804    ]
1805
1806    def get_hdrs_len(self):
1807        # type: () -> int
1808        """ get_hdrs_len computes the length of the hdrs field
1809
1810        To do this computation, the length of the padlen field, reserved,
1811        stream_id and the actual padding is subtracted to the string that was
1812        provided to the pre_dissect fun of the pkt parameter.
1813        @return int: the length of the hdrs field
1814        @raise AssertionError
1815        """
1816        fld, padding_len = self.getfield_and_val('padlen')
1817        padding_len_len = fld.i2len(self, padding_len)
1818        bit_len = self.get_field('reserved').size
1819        bit_len += self.get_field('stream_id').size
1820
1821        ret = (self.s_len
1822            - padding_len_len
1823            - padding_len
1824            - (bit_len/8)
1825        )
1826        assert(ret >= 0)
1827        return ret
1828
1829    def pre_dissect(self, s):
1830        # type: (str) -> str
1831        """pre_dissect is filling the s_len property of this instance. This
1832        property is later used during the parsing of the hdrs PacketListField
1833        when trying to evaluate the length of the PacketListField! This "trick"
1834        works because the underlayer packet (H2Frame) is assumed to override the
1835        "extract_padding" method and to only provide to this packet the data
1836        necessary for this packet. Tricky, tricky, will break some day probably!
1837        """
1838        self.s_len = len(s)
1839        return s
1840
1841############################################### HTTP/2 Ping Frame Packets ##############################################
1842
1843class H2PingFrame(H2FramePayload):
1844    """ H2PingFrame implements the RFC 7540 par6.7
1845    """
1846    type_id = 6
1847    ACK_FLAG = 0  # 0x1
1848    flags = {
1849        ACK_FLAG: fields.MultiFlagsEntry('A', 'ACK')
1850    }
1851
1852    name = 'HTTP/2 Ping Frame'
1853    fields_desc = [
1854        fields.LongField('opaque', 0)
1855    ]
1856
1857    def __init__(self, *args, **kwargs):
1858        """
1859        @raise AssertionError
1860        """
1861        # RFC7540 par6.7 p42
1862        assert(
1863            len(args) == 0 or (
1864                isinstance(args[0], str)
1865                and len(args[0]) == 8
1866            )
1867        ), 'Invalid ping frame; length is not 8'
1868        super(H2PingFrame, self).__init__(*args, **kwargs)
1869
1870
1871############################################# HTTP/2 GoAway Frame Packets ##############################################
1872
1873class H2GoAwayFrame(H2FramePayload):
1874    """ H2GoAwayFrame implements the RFC 7540 par6.8
1875    """
1876    type_id = 7
1877
1878    name = 'HTTP/2 Go Away Frame'
1879    fields_desc = [
1880        fields.BitField('reserved', 0, 1),
1881        fields.BitField('last_stream_id', 0, 31),
1882        fields.EnumField('error', 0, H2ErrorCodes.literal, fmt='!I'),
1883        fields.StrField('additional_data', '')
1884    ]
1885
1886###################################### HTTP/2 Window Update Frame Packets ##############################################
1887
1888class H2WindowUpdateFrame(H2FramePayload):
1889    """ H2WindowUpdateFrame implements the RFC 7540 par6.9
1890    """
1891    type_id = 8
1892
1893    name = 'HTTP/2 Window Update Frame'
1894    fields_desc = [
1895        fields.BitField('reserved', 0, 1),
1896        fields.BitField('win_size_incr', 0, 31)
1897    ]
1898
1899    def __init__(self, *args, **kwargs):
1900        """
1901        @raise AssertionError
1902        """
1903        # RFC7540 par6.9 p46
1904        assert(
1905            len(args) == 0 or (
1906                isinstance(args[0], str)
1907                and len(args[0]) == 4
1908            )
1909        ), 'Invalid window update frame; length is not 4'
1910        super(H2WindowUpdateFrame, self).__init__(*args, **kwargs)
1911
1912####################################### HTTP/2 Continuation Frame Packets ##############################################
1913
1914class H2ContinuationFrame(H2FramePayload):
1915    """ H2ContinuationFrame implements the RFC 7540 par6.10
1916    """
1917    type_id = 9
1918    END_HEADERS_FLAG = 2  # Ox4
1919    flags = {
1920        END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers')
1921    }
1922
1923    name = 'HTTP/2 Continuation Frame'
1924    fields_desc = [
1925        fields.PacketListField('hdrs', [], HPackHeaders)
1926    ]
1927
1928########################################## HTTP/2 Base Frame Packets ###################################################
1929
1930class H2Frame(packet.Packet):
1931    """ H2Frame implements the frame structure as defined in RFC 7540 par4.1
1932
1933    This packet may have a payload (one of the H2FramePayload) or none, in some
1934    rare cases such as settings acknowledgement)
1935    """
1936    name = 'HTTP/2 Frame'
1937    fields_desc = [
1938        fields.X3BytesField('len', None),
1939        fields.EnumField('type', None, {
1940            0: 'DataFrm',
1941            1: 'HdrsFrm',
1942            2: 'PrioFrm',
1943            3: 'RstFrm',
1944            4: 'SetFrm',
1945            5: 'PushFrm',
1946            6: 'PingFrm',
1947            7: 'GoawayFrm',
1948            8: 'WinFrm',
1949            9: 'ContFrm'
1950        }, "b"),
1951        fields.MultiFlagsField('flags', set(), 8, {
1952                H2DataFrame.type_id: H2DataFrame.flags,
1953                H2HeadersFrame.type_id: H2HeadersFrame.flags,
1954                H2PushPromiseFrame.type_id: H2PushPromiseFrame.flags,
1955                H2SettingsFrame.type_id: H2SettingsFrame.flags,
1956                H2PingFrame.type_id: H2PingFrame.flags,
1957                H2ContinuationFrame.type_id: H2ContinuationFrame.flags,
1958            },
1959            depends_on=lambda pkt: pkt.getfieldval('type')
1960        ),
1961        fields.BitField('reserved', 0, 1),
1962        fields.BitField('stream_id', 0, 31)
1963    ]
1964
1965    def guess_payload_class(self, payload):
1966        # type: (str) -> base_classes.Packet_metaclass
1967        """ guess_payload_class returns the Class object to use for parsing a payload
1968        This function uses the H2Frame.type field value to decide which payload to parse. The implement cannot be
1969        performed using the simple bind_layers helper because sometimes the selection of which Class object to return
1970        also depends on the H2Frame.flags value.
1971
1972        @param payload:
1973        @return:
1974        """
1975        if len(payload) == 0:
1976            return packet.NoPayload
1977
1978        t = self.getfieldval('type')
1979        if t == H2DataFrame.type_id:
1980            if H2DataFrame.flags[H2DataFrame.PADDED_FLAG].short in self.getfieldval('flags'):
1981                return H2PaddedDataFrame
1982            return H2DataFrame
1983
1984        if t == H2HeadersFrame.type_id:
1985            if H2HeadersFrame.flags[H2HeadersFrame.PADDED_FLAG].short in self.getfieldval('flags'):
1986                if H2HeadersFrame.flags[H2HeadersFrame.PRIORITY_FLAG].short in self.getfieldval('flags'):
1987                    return H2PaddedPriorityHeadersFrame
1988                else:
1989                    return H2PaddedHeadersFrame
1990            elif H2HeadersFrame.flags[H2HeadersFrame.PRIORITY_FLAG].short in self.getfieldval('flags'):
1991                    return H2PriorityHeadersFrame
1992            return H2HeadersFrame
1993
1994        if t == H2PriorityFrame.type_id:
1995            return H2PriorityFrame
1996
1997        if t == H2ResetFrame.type_id:
1998            return H2ResetFrame
1999
2000        if t == H2SettingsFrame.type_id:
2001            return H2SettingsFrame
2002
2003        if t == H2PushPromiseFrame.type_id:
2004            if H2PushPromiseFrame.flags[H2PushPromiseFrame.PADDED_FLAG].short in self.getfieldval('flags'):
2005                return H2PaddedPushPromiseFrame
2006            return H2PushPromiseFrame
2007
2008        if t == H2PingFrame.type_id:
2009            return H2PingFrame
2010
2011        if t == H2GoAwayFrame.type_id:
2012            return H2GoAwayFrame
2013
2014        if t == H2WindowUpdateFrame.type_id:
2015            return H2WindowUpdateFrame
2016
2017        if t == H2ContinuationFrame.type_id:
2018            return H2ContinuationFrame
2019
2020        return config.conf.padding_layer
2021
2022    def extract_padding(self, s):
2023        # type: (str) -> Tuple[str, str]
2024        """
2025        @param str s: the string from which to tell the padding and the payload data apart
2026        @return (str, str): the padding and the payload data strings
2027        @raise AssertionError
2028        """
2029        assert isinstance(self.len, six.integer_types) and self.len >= 0, 'Invalid length: negative len?'
2030        assert len(s) >= self.len, 'Invalid length: string too short for this length'
2031        return s[:self.len], s[self.len:]
2032
2033    def post_build(self, p, pay):
2034        # type: (str, str) -> str
2035        """
2036        @param str p: the stringified packet
2037        @param str pay: the stringified payload
2038        @return str: the stringified packet and payload, with the packet length field "patched"
2039        @raise AssertionError
2040        """
2041        # This logic, while awkward in the post_build and more reasonable in
2042        # a self_build is implemented here for performance tricks reason
2043        if self.getfieldval('len') is None:
2044            assert(len(pay) < (1 << 24)), 'Invalid length: payload is too long'
2045            p = struct.pack('!L', len(pay))[1:] + p[3:]
2046        return super(H2Frame, self).post_build(p, pay)
2047
2048class H2Seq(packet.Packet):
2049    """ H2Seq is a helper packet that contains several H2Frames and their
2050    payload. This packet can be used, for instance, while reading manually from
2051    a TCP socket.
2052    """
2053    name = 'HTTP/2 Frame Sequence'
2054    fields_desc = [
2055        fields.PacketListField('frames', [], H2Frame)
2056    ]
2057
2058    def guess_payload_class(self, payload):
2059        # type: (str) -> base_classes.Packet_metaclass
2060        return config.conf.padding_layer
2061
2062
2063packet.bind_layers(H2Frame, H2DataFrame, {'type': H2DataFrame.type_id})
2064packet.bind_layers(H2Frame, H2PaddedDataFrame, {'type': H2DataFrame.type_id})
2065packet.bind_layers(H2Frame, H2HeadersFrame, {'type': H2HeadersFrame.type_id})
2066packet.bind_layers(H2Frame, H2PaddedHeadersFrame, {'type': H2HeadersFrame.type_id})
2067packet.bind_layers(H2Frame, H2PriorityHeadersFrame, {'type': H2HeadersFrame.type_id})
2068packet.bind_layers(H2Frame, H2PaddedPriorityHeadersFrame, {'type': H2HeadersFrame.type_id})
2069packet.bind_layers(H2Frame, H2PriorityFrame, {'type': H2PriorityFrame.type_id})
2070packet.bind_layers(H2Frame, H2ResetFrame, {'type': H2ResetFrame.type_id})
2071packet.bind_layers(H2Frame, H2SettingsFrame, {'type': H2SettingsFrame.type_id})
2072packet.bind_layers(H2Frame, H2PingFrame, {'type': H2PingFrame.type_id})
2073packet.bind_layers(H2Frame, H2PushPromiseFrame, {'type': H2PushPromiseFrame.type_id})
2074packet.bind_layers(H2Frame, H2PaddedPushPromiseFrame, {'type': H2PaddedPushPromiseFrame.type_id})
2075packet.bind_layers(H2Frame, H2GoAwayFrame, {'type': H2GoAwayFrame.type_id})
2076packet.bind_layers(H2Frame, H2WindowUpdateFrame, {'type': H2WindowUpdateFrame.type_id})
2077packet.bind_layers(H2Frame, H2ContinuationFrame, {'type': H2ContinuationFrame.type_id})
2078
2079
2080########################################## HTTP/2 Connection Preface ###################################################
2081# From RFC 7540 par3.5
2082H2_CLIENT_CONNECTION_PREFACE = '505249202a20485454502f322e300d0a0d0a534d0d0a0d0a'.decode('hex')
2083
2084
2085########################################################################################################################
2086################################################### HTTP/2 Helpers #####################################################
2087########################################################################################################################
2088
2089class HPackHdrEntry(Sized):
2090    """ HPackHdrEntry is an entry of the HPackHdrTable helper
2091
2092    Each HPackHdrEntry instance is a header line (name and value). Names are
2093    normalized (lowercased), according to RFC 7540 par8.1.2
2094    """
2095    __slots__ = ['_name', '_len', '_value']
2096
2097    def __init__(self, name, value):
2098        # type: (str, str) -> None
2099        """
2100        @raise AssertionError
2101        """
2102        assert(len(name) > 0)
2103
2104        self._name = name.lower()
2105        self._value = value
2106
2107        # 32 bytes is an RFC-hardcoded value: see RFC 7541 par4.1
2108        self._len = (32 + len(self._name) + len(self._value))
2109
2110    def name(self):
2111        # type: () -> str
2112        return self._name
2113
2114    def value(self):
2115        # type: () -> str
2116        return self._value
2117
2118    def size(self):
2119        # type: () -> int
2120        """ size returns the "length" of the header entry, as defined in
2121        RFC 7541 par4.1.
2122        """
2123        return self._len
2124
2125    __len__ = size
2126
2127    def __str__(self):
2128        # type: () -> str
2129        """ __str__ returns the header as it would be formated in textual format
2130        """
2131        if self._name.startswith(':'):
2132            return "{} {}".format(self._name, self._value)
2133        else:
2134            return "{}: {}".format(self._name, self._value)
2135
2136
2137class HPackHdrTable(Sized):
2138    """ HPackHdrTable is a helper class that implements some of the logic
2139    associated with indexing of headers (read and write operations in this
2140    "registry". THe HPackHdrTable also implements convenience functions to easily
2141    convert to and from textual representation and binary representation of
2142    a HTTP/2 requests
2143    """
2144    __slots__ = [
2145        '_dynamic_table',
2146        '_dynamic_table_max_size',
2147        '_dynamic_table_cap_size',
2148        '_regexp'
2149    ]
2150    """:var _dynamic_table: the list containing entries requested to be added by
2151    the peer and registered with a register() call
2152    :var _dynamic_table_max_size: the current maximum size of the dynamic table
2153    in bytes. This value is updated with the Dynamic Table Size Update messages
2154    defined in RFC 7541 par6.3
2155    :var _dynamic_table_cap_size: the maximum size of the dynamic table in
2156    bytes. This value is updated with the SETTINGS_HEADER_TABLE_SIZE HTTP/2
2157    setting.
2158    """
2159
2160    # Manually imported from RFC 7541 Appendix A
2161    _static_entries = {
2162        1: HPackHdrEntry(':authority', ''),
2163        2: HPackHdrEntry(':method', 'GET'),
2164        3: HPackHdrEntry(':method', 'POST'),
2165        4: HPackHdrEntry(':path', '/'),
2166        5: HPackHdrEntry(':path', '/index.html'),
2167        6: HPackHdrEntry(':scheme', 'http'),
2168        7: HPackHdrEntry(':scheme', 'https'),
2169        8: HPackHdrEntry(':status', '200'),
2170        9: HPackHdrEntry(':status', '204'),
2171        10: HPackHdrEntry(':status', '206'),
2172        11: HPackHdrEntry(':status', '304'),
2173        12: HPackHdrEntry(':status', '400'),
2174        13: HPackHdrEntry(':status', '404'),
2175        14: HPackHdrEntry(':status', '500'),
2176        15: HPackHdrEntry('accept-charset', ''),
2177        16: HPackHdrEntry('accept-encoding', 'gzip, deflate'),
2178        17: HPackHdrEntry('accept-language', ''),
2179        18: HPackHdrEntry('accept-ranges', ''),
2180        19: HPackHdrEntry('accept', ''),
2181        20: HPackHdrEntry('access-control-allow-origin', ''),
2182        21: HPackHdrEntry('age', ''),
2183        22: HPackHdrEntry('allow', ''),
2184        23: HPackHdrEntry('authorization', ''),
2185        24: HPackHdrEntry('cache-control', ''),
2186        25: HPackHdrEntry('content-disposition', ''),
2187        26: HPackHdrEntry('content-encoding', ''),
2188        27: HPackHdrEntry('content-language', ''),
2189        28: HPackHdrEntry('content-length', ''),
2190        29: HPackHdrEntry('content-location', ''),
2191        30: HPackHdrEntry('content-range', ''),
2192        31: HPackHdrEntry('content-type', ''),
2193        32: HPackHdrEntry('cookie', ''),
2194        33: HPackHdrEntry('date', ''),
2195        34: HPackHdrEntry('etag', ''),
2196        35: HPackHdrEntry('expect', ''),
2197        36: HPackHdrEntry('expires', ''),
2198        37: HPackHdrEntry('from', ''),
2199        38: HPackHdrEntry('host', ''),
2200        39: HPackHdrEntry('if-match', ''),
2201        40: HPackHdrEntry('if-modified-since', ''),
2202        41: HPackHdrEntry('if-none-match', ''),
2203        42: HPackHdrEntry('if-range', ''),
2204        43: HPackHdrEntry('if-unmodified-since', ''),
2205        44: HPackHdrEntry('last-modified', ''),
2206        45: HPackHdrEntry('link', ''),
2207        46: HPackHdrEntry('location', ''),
2208        47: HPackHdrEntry('max-forwards', ''),
2209        48: HPackHdrEntry('proxy-authenticate', ''),
2210        49: HPackHdrEntry('proxy-authorization', ''),
2211        50: HPackHdrEntry('range', ''),
2212        51: HPackHdrEntry('referer', ''),
2213        52: HPackHdrEntry('refresh', ''),
2214        53: HPackHdrEntry('retry-after', ''),
2215        54: HPackHdrEntry('server', ''),
2216        55: HPackHdrEntry('set-cookie', ''),
2217        56: HPackHdrEntry('strict-transport-security', ''),
2218        57: HPackHdrEntry('transfer-encoding', ''),
2219        58: HPackHdrEntry('user-agent', ''),
2220        59: HPackHdrEntry('vary', ''),
2221        60: HPackHdrEntry('via', ''),
2222        61: HPackHdrEntry('www-authenticate', ''),
2223    }
2224
2225    # The value of this variable cannot be determined at declaration time. It is
2226    # initialized by an init_static_table call
2227    _static_entries_last_idx = None
2228    _regexp = None
2229
2230    @classmethod
2231    def init_static_table(cls):
2232        # type: () -> None
2233        cls._static_entries_last_idx = max(cls._static_entries)
2234
2235    def __init__(self, dynamic_table_max_size=4096, dynamic_table_cap_size=4096):
2236        # type: (int, int) -> None
2237        """
2238        @param int dynamic_table_max_size: the current maximum size of the dynamic entry table in bytes
2239        @param int dynamic_table_cap_size: the maximum-maximum size of the dynamic entry table in bytes
2240        @raises AssertionError
2241        """
2242        if isinstance(type(self)._static_entries_last_idx, type(None)):
2243            type(self).init_static_table()
2244
2245        assert dynamic_table_max_size <= dynamic_table_cap_size, \
2246            'EINVAL: dynamic_table_max_size too large; expected value is less or equal to dynamic_table_cap_size'
2247
2248        self._dynamic_table = []  # type: List[HPackHdrEntry]
2249        self._dynamic_table_max_size = dynamic_table_max_size
2250        self._dynamic_table_cap_size = dynamic_table_cap_size
2251
2252    def __getitem__(self, idx):
2253        # type: (int) -> HPackHdrEntry
2254        """Gets an element from the header tables (static or dynamic indifferently)
2255
2256        @param int idx: the index number of the entry to retrieve. If the index
2257        value is superior to the last index of the static entry table, then the
2258        dynamic entry type is requested, following the procedure described in
2259        RFC 7541 par2.3.3
2260        @return HPackHdrEntry: the entry defined at this requested index. If the entry does not exist, KeyError is
2261          raised
2262        @raise KeyError, AssertionError
2263        """
2264        assert(idx >= 0)
2265        if idx > type(self)._static_entries_last_idx:
2266            idx -= type(self)._static_entries_last_idx + 1
2267            if idx >= len(self._dynamic_table):
2268                raise KeyError(
2269                    'EINVAL: idx: out-of-bound read: {}; maximum index: {}'.format(idx, len(self._dynamic_table))
2270                )
2271            return self._dynamic_table[idx]
2272        return type(self)._static_entries[idx]
2273
2274    def resize(self, ns):
2275        # type: (int) -> None
2276        """Resize the dynamic table. If the new size (ns) must be between 0 and
2277        the cap size. If the new size is lower than the current size of the
2278        dynamic table, entries are evicted.
2279        @param int ns: the new size of the dynamic table
2280        @raise AssertionError
2281        """
2282        assert 0 <= ns <= self._dynamic_table_cap_size, \
2283            'EINVAL: ns: out-of-range value; expected value is in the range [0;{}['.format(self._dynamic_table_cap_size)
2284
2285        old_size = self._dynamic_table_max_size
2286        self._dynamic_table_max_size = ns
2287        if old_size > self._dynamic_table_max_size:
2288            self._reduce_dynamic_table()
2289
2290    def recap(self, nc):
2291        # type: (int) -> None
2292        """recap changes the maximum size limit of the dynamic table. It also
2293        proceeds to a resize(), if the new size is lower than the previous one.
2294        @param int nc: the new cap of the dynamic table (that is the maximum-maximum size)
2295        @raise AssertionError
2296        """
2297        assert(nc >= 0)
2298        t = self._dynamic_table_cap_size > nc
2299        self._dynamic_table_cap_size = nc
2300
2301        if t:
2302            # The RFC is not clear about whether this resize should happen;
2303            # we do it anyway
2304            self.resize(nc)
2305
2306    def _reduce_dynamic_table(self, new_entry_size=0):
2307        # type: (int) -> None
2308        """_reduce_dynamic_table evicts entries from the dynamic table until it
2309        fits in less than the current size limit. The optional parameter,
2310        new_entry_size, allows the resize to happen so that a new entry of this
2311        size fits in.
2312        @param int new_entry_size: if called before adding a new entry, the size of the new entry in bytes (following
2313        the RFC7541 definition of the size of an entry)
2314        @raise AssertionError
2315        """
2316        assert(new_entry_size >= 0)
2317        cur_sz = len(self)
2318        dyn_tbl_sz = len(self._dynamic_table)
2319        while dyn_tbl_sz > 0 and cur_sz + new_entry_size > self._dynamic_table_max_size:
2320            last_elmt_sz = len(self._dynamic_table[-1])
2321            self._dynamic_table.pop()
2322            dyn_tbl_sz -= 1
2323            cur_sz -= last_elmt_sz
2324
2325    def register(self, hdrs):
2326        # type: (Union[HPackLitHdrFldWithIncrIndexing, H2Frame, List[HPackHeaders]]) -> None
2327        """register adds to this table the instances of
2328        HPackLitHdrFldWithIncrIndexing provided as parameters.
2329
2330        A H2Frame with a H2HeadersFrame payload can be provided, as much as a
2331        python list of HPackHeaders or a single HPackLitHdrFldWithIncrIndexing
2332        instance.
2333        @param HPackLitHdrFldWithIncrIndexing|H2Frame|list of HPackHeaders hdrs: the header(s) to register
2334        @raise AssertionError
2335        """
2336        if isinstance(hdrs, H2Frame):
2337            hdrs = [hdr for hdr in hdrs.payload.hdrs if isinstance(hdr, HPackLitHdrFldWithIncrIndexing)]
2338        elif isinstance(hdrs, HPackLitHdrFldWithIncrIndexing):
2339            hdrs = [hdrs]
2340        else:
2341            hdrs = [hdr for hdr in hdrs if isinstance(hdr, HPackLitHdrFldWithIncrIndexing)]
2342
2343        for hdr in hdrs:
2344            if hdr.index == 0:
2345                hdr_name = hdr.hdr_name.getfieldval('data').origin()
2346            else:
2347                idx = int(hdr.index)
2348                hdr_name = self[idx].name()
2349            hdr_value = hdr.hdr_value.getfieldval('data').origin()
2350
2351            # Note: we do not delete any existing hdrentry with the same names
2352            # and values, as dictated by RFC 7541 par2.3.2
2353
2354            entry = HPackHdrEntry(hdr_name, hdr_value)
2355            # According to RFC7541 par4.4, "Before a new entry is added to
2356            # the dynamic table, entries are evicted
2357            # from the end of the dynamic table until the size of the dynamic
2358            # table is less than or equal to (maximum size - new entry size)
2359            # or until the table is empty"
2360            # Also, "It is not an error to attempt to add an entry that is
2361            # larger than the maximum size; an attempt to add an entry larger
2362            # than the maximum size causes the table to be emptied of all
2363            # existing entries and results in an empty table"
2364            # For this reason, we first call the _reduce_dynamic_table and
2365            # then throw an assertion error if the new entry does not fit in
2366            new_entry_len = len(entry)
2367            self._reduce_dynamic_table(new_entry_len)
2368            assert(new_entry_len <= self._dynamic_table_max_size)
2369            self._dynamic_table.insert(0, entry)
2370
2371    def get_idx_by_name(self, name):
2372        # type: (str) -> Optional[int]
2373        """ get_idx_by_name returns the index of a matching registered header
2374
2375        This implementation will prefer returning a static entry index whenever
2376        possible. If multiple matching header name are found in the static
2377        table, there is insurance that the first entry (lowest index number)
2378        will be returned.
2379        If no matching header is found, this method returns None.
2380        """
2381        name = name.lower()
2382        for key, val in six.iteritems(type(self)._static_entries):
2383            if val.name() == name:
2384                return key
2385        for idx, val in enumerate(self._dynamic_table):
2386            if val.name() == name:
2387                return type(self)._static_entries_last_idx + idx + 1
2388        return None
2389
2390    def get_idx_by_name_and_value(self, name, value):
2391        # type: (str, str) -> Optional[int]
2392        """ get_idx_by_name_and_value returns the index of a matching registered
2393        header
2394
2395        This implementation will prefer returning a static entry index whenever
2396        possible. If multiple matching headers are found in the dynamic table,
2397        the lowest index is returned
2398        If no matching header is found, this method returns None.
2399        """
2400        name = name.lower()
2401        for key, val in six.iteritems(type(self)._static_entries):
2402            if val.name() == name and val.value() == value:
2403                return key
2404        for idx, val in enumerate(self._dynamic_table):
2405            if val.name() == name and val.value() == value:
2406                return type(self)._static_entries_last_idx + idx + 1
2407        return None
2408
2409    def __len__(self):
2410        # type: () -> int
2411        """ __len__ returns the summed length of all dynamic entries
2412        """
2413        return sum(len(x) for x in self._dynamic_table)
2414
2415    def gen_txt_repr(self, hdrs, register=True):
2416        # type: (Union[H2Frame, List[HPackHeaders]], Optional[bool]) -> str
2417        """ gen_txt_repr returns a "textual" representation of the provided
2418        headers.
2419
2420        The output of this function is compatible with the input of
2421        parse_txt_hdrs.
2422        @param H2Frame|list of HPackHeaders hdrs: the list of headers to convert to textual representation
2423        @param bool: whether incremental headers should be added to the dynamic table as we generate the text
2424            representation
2425        @return str: the textual representation of the provided headers
2426        @raise AssertionError
2427        """
2428        l = []
2429        if isinstance(hdrs, H2Frame):
2430            hdrs = hdrs.payload.hdrs
2431
2432        for hdr in hdrs:
2433            try:
2434                if isinstance(hdr, HPackIndexedHdr):
2435                    l.append('{}'.format(self[hdr.index]))
2436                elif isinstance(hdr, (
2437                    HPackLitHdrFldWithIncrIndexing,
2438                    HPackLitHdrFldWithoutIndexing
2439                )):
2440                    if hdr.index != 0:
2441                        name = self[hdr.index].name()
2442                    else:
2443                        name = hdr.hdr_name.getfieldval('data').origin()
2444                    if name.startswith(':'):
2445                        l.append(
2446                            '{} {}'.format(
2447                                name,
2448                                hdr.hdr_value.getfieldval('data').origin()
2449                            )
2450                        )
2451                    else:
2452                        l.append(
2453                            '{}: {}'.format(
2454                                name,
2455                                hdr.hdr_value.getfieldval('data').origin()
2456                            )
2457                        )
2458                if register and isinstance(hdr, HPackLitHdrFldWithIncrIndexing):
2459                    self.register(hdr)
2460            except KeyError as e:  # raised when an index is out-of-bound
2461                print(e)
2462                continue
2463        return '\n'.join(l)
2464
2465    @staticmethod
2466    def _optimize_header_length_and_packetify(s):
2467        # type: (str) -> HPackHdrString
2468        # type: (str) -> HPackHdrString
2469        zs = HPackZString(s)
2470        if len(zs) >= len(s):
2471            return HPackHdrString(data=HPackLiteralString(s))
2472        return HPackHdrString(data=zs)
2473
2474    def _convert_a_header_to_a_h2_header(self, hdr_name, hdr_value, is_sensitive, should_index):
2475        # type: (str, str, Callable[[str, str], bool], Callable[[str], bool]) -> Tuple[HPackHeaders, int]
2476        """ _convert_a_header_to_a_h2_header builds a HPackHeaders from a header
2477        name and a value. It returns a HPackIndexedHdr whenever possible. If not,
2478        it returns a HPackLitHdrFldWithoutIndexing or a
2479        HPackLitHdrFldWithIncrIndexing, based on the should_index callback.
2480        HPackLitHdrFldWithoutIndexing is forced if the is_sensitive callback
2481        returns True and its never_index bit is set.
2482        """
2483
2484        # If both name and value are already indexed
2485        idx = self.get_idx_by_name_and_value(hdr_name, hdr_value)
2486        if idx is not None:
2487            return HPackIndexedHdr(index=idx), len(self[idx])
2488
2489        # The value is not indexed for this headers
2490
2491        hdr_value = self._optimize_header_length_and_packetify(hdr_value)
2492
2493        # Searching if the header name is indexed
2494        idx = self.get_idx_by_name(hdr_name)
2495        if idx is not None:
2496            if is_sensitive(
2497                hdr_name,
2498                hdr_value.getfieldval('data').origin()
2499            ):
2500                return HPackLitHdrFldWithoutIndexing(
2501                    never_index=1,
2502                    index=idx,
2503                    hdr_value=hdr_value
2504                ), len(
2505                    HPackHdrEntry(
2506                        self[idx].name(),
2507                        hdr_value.getfieldval('data').origin()
2508                    )
2509                )
2510            if should_index(hdr_name):
2511                return HPackLitHdrFldWithIncrIndexing(
2512                    index=idx,
2513                    hdr_value=hdr_value
2514                ), len(
2515                    HPackHdrEntry(
2516                        self[idx].name(),
2517                        hdr_value.getfieldval('data').origin()
2518                    )
2519                )
2520            return HPackLitHdrFldWithoutIndexing(
2521                index=idx,
2522                hdr_value=hdr_value
2523            ), len(
2524                HPackHdrEntry(
2525                    self[idx].name(),
2526                    hdr_value.getfieldval('data').origin()
2527                )
2528            )
2529
2530        hdr_name = self._optimize_header_length_and_packetify(hdr_name)
2531
2532        if is_sensitive(
2533            hdr_name.getfieldval('data').origin(),
2534            hdr_value.getfieldval('data').origin()
2535        ):
2536            return HPackLitHdrFldWithoutIndexing(
2537                never_index=1,
2538                index=0,
2539                hdr_name=hdr_name,
2540                hdr_value=hdr_value
2541            ), len(
2542                HPackHdrEntry(
2543                    hdr_name.getfieldval('data').origin(),
2544                    hdr_value.getfieldval('data').origin()
2545                )
2546            )
2547        if should_index(hdr_name.getfieldval('data').origin()):
2548            return HPackLitHdrFldWithIncrIndexing(
2549                index=0,
2550                hdr_name=hdr_name,
2551                hdr_value=hdr_value
2552            ), len(
2553                HPackHdrEntry(
2554                    hdr_name.getfieldval('data').origin(),
2555                    hdr_value.getfieldval('data').origin()
2556                )
2557            )
2558        return HPackLitHdrFldWithoutIndexing(
2559            index=0,
2560            hdr_name=hdr_name,
2561            hdr_value=hdr_value
2562        ), len(
2563            HPackHdrEntry(
2564                hdr_name.getfieldval('data').origin(),
2565                hdr_value.getfieldval('data').origin()
2566            )
2567        )
2568
2569    def _parse_header_line(self, l):
2570        # type: (str) -> Union[Tuple[None, None], Tuple[str, str]]
2571
2572        if type(self)._regexp is None:
2573            type(self)._regexp = re.compile(r'^(?::([a-z\-0-9]+)|([a-z\-0-9]+):)\s+(.+)$')
2574
2575        hdr_line = l.rstrip()
2576        grp = type(self)._regexp.match(hdr_line)
2577
2578        if grp is None or len(grp.groups()) != 3:
2579            return None, None
2580
2581        if grp.group(1) is not None:
2582            hdr_name = ':'+grp.group(1)
2583        else:
2584            hdr_name = grp.group(2)
2585        return hdr_name.lower(), grp.group(3)
2586
2587    def parse_txt_hdrs(self,
2588                       s,  # type: str
2589                       stream_id=1,  # type: int
2590                       body=None,  # type: Optional[str]
2591                       max_frm_sz=4096,  # type: int
2592                       max_hdr_lst_sz=0,  # type: int
2593                       is_sensitive=lambda n, v: False,  # type: Callable[[str, str], bool]
2594                       should_index=lambda x: False,  # type: Callable[[str], bool]
2595                       register=True,  # type: bool
2596    ):
2597        # type: (...) -> H2Seq
2598        """ parse_txt_hdrs parses headers expressed in text and converts them
2599        into a series of H2Frames with the "correct" flags. A body can be provided
2600        in which case, the data frames are added, bearing the End Stream flag,
2601        instead of the H2HeadersFrame/H2ContinuationFrame. The generated frames
2602        may respect max_frm_sz (SETTINGS_MAX_FRAME_SIZE) and
2603        max_hdr_lst_sz (SETTINGS_MAX_HEADER_LIST_SIZE) if provided. The headers
2604        are split into multiple headers fragment (and H2Frames) to respect these
2605        limits. Also, a callback can be provided to tell if a header should be
2606        never indexed (sensitive headers, such as cookies), and another callback
2607        say if the header should be registered into the index table at all.
2608        For an header to be registered, the is_sensitive callback must return
2609        False AND the should_index callback should return True. This is the
2610        default behavior.
2611
2612        @param str s: the string to parse for headers
2613        @param int stream_id: the stream id to use in the generated H2Frames
2614        @param str|None body: the eventual body of the request, that is added to the generated frames
2615        @param int max_frm_sz: the maximum frame size. This is used to split the headers and data frames according to
2616        the maximum frame size negociated for this connection
2617        @param int max_hdr_lst_sz: the maximum size of a "header fragment" as defined in RFC7540
2618        @param callable is_sensitive: callback that returns True if the provided header is sensible and must be stored
2619        in a header packet requesting this header never to be indexed
2620        @param callable should_index: callback that returns True if the provided header should be stored in a header
2621        packet requesting indexation in the dynamic header table.
2622        @param bool register: whether to register new headers with incremental indexing as we parse them
2623        @raise Exception
2624        """
2625
2626        sio = BytesIO(s)
2627
2628        base_frm_len = len(str(H2Frame()))
2629
2630        ret = H2Seq()
2631        cur_frm = H2HeadersFrame()  # type: Union[H2HeadersFrame, H2ContinuationFrame]
2632        cur_hdr_sz = 0
2633
2634        # For each line in the headers str to parse
2635        for hdr_line in sio:
2636            hdr_name, hdr_value = self._parse_header_line(hdr_line)
2637            if hdr_name is None:
2638                continue
2639
2640            new_hdr, new_hdr_len = self._convert_a_header_to_a_h2_header(
2641                hdr_name, hdr_value, is_sensitive, should_index
2642            )
2643            new_hdr_bin_len = len(str(new_hdr))
2644
2645            if register and isinstance(new_hdr, HPackLitHdrFldWithIncrIndexing):
2646                self.register(new_hdr)
2647
2648            # The new header binary length (+ base frame size) must not exceed
2649            # the maximum frame size or it will just never fit. Also, the
2650            # header entry length (as specified in RFC7540 par6.5.2) must not
2651            # exceed the maximum length of a header fragment or it will just
2652            # never fit
2653            if (new_hdr_bin_len + base_frm_len > max_frm_sz
2654                or (max_hdr_lst_sz != 0 and new_hdr_len > max_hdr_lst_sz)
2655            ):
2656                raise Exception('Header too long: {}'.format(hdr_name))
2657
2658            if (max_frm_sz < len(str(cur_frm)) + base_frm_len + new_hdr_len
2659                or (
2660                    max_hdr_lst_sz != 0
2661                    and max_hdr_lst_sz < cur_hdr_sz + new_hdr_len
2662                )
2663            ):
2664                flags = set()
2665                if isinstance(cur_frm, H2HeadersFrame) and not body:
2666                    flags.add('ES')
2667                ret.frames.append(H2Frame(stream_id=stream_id, flags=flags)/cur_frm)
2668                cur_frm = H2ContinuationFrame()
2669                cur_hdr_sz = 0
2670
2671            hdr_list = cur_frm.hdrs
2672            hdr_list += new_hdr
2673            cur_hdr_sz += new_hdr_len
2674
2675        flags = {'EH'}
2676        if isinstance(cur_frm, H2HeadersFrame) and not body:
2677            flags.add('ES')
2678        ret.frames.append(H2Frame(stream_id=stream_id, flags=flags)/cur_frm)
2679
2680        if body:
2681            base_data_frm_len = len(str(H2DataFrame()))
2682            sio = BytesIO(body)
2683            frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len)
2684            while frgmt:
2685                nxt_frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len)
2686                flags = set()
2687                if len(nxt_frgmt) == 0:
2688                    flags.add('ES')
2689                ret.frames.append(
2690                    H2Frame(stream_id=stream_id, flags=flags)/H2DataFrame(data=frgmt)
2691                )
2692                frgmt = nxt_frgmt
2693        return ret
2694