/* Prototype implementation for HTTP2. Do not use in production.
 * There may be memory leaks, security vulnerabilities, ...
 */


/***********************************************************************/
/***  HPACK                                                          ***/
/***********************************************************************/

/* hpack predefined table. See:
 * https://tools.ietf.org/html/rfc7541#appendix-A
 */

static struct mg_header hpack_predefined[62] = {{NULL, NULL},
                                                {":authority", NULL},
                                                {":method", "GET"},
                                                {":method", "POST"},
                                                {":path", "/"},
                                                {":path", "/index.html"},
                                                {":scheme", "http"},
                                                {":scheme", "https"},
                                                {":status", "200"},
                                                {":status", "204"},
                                                {":status", "206"},
                                                {":status", "304"},
                                                {":status", "400"},
                                                {":status", "404"},
                                                {":status", "500"},
                                                {"accept-charset", NULL},
                                                {"accept-encoding", NULL},
                                                {"accept-language", NULL},
                                                {"accept-ranges", NULL},
                                                {"accept", NULL},
                                                {"access-control-allow-origin",
                                                 NULL},
                                                {"age", NULL},
                                                {"allow", NULL},
                                                {"authorization", NULL},
                                                {"cache-control", NULL},
                                                {"content-encoding", NULL},
                                                {"content-disposition", NULL},
                                                {"content-language", NULL},
                                                {"content-length", NULL},
                                                {"content-location", NULL},
                                                {"content-range", NULL},
                                                {"content-type", NULL},
                                                {"cookie", NULL},
                                                {"date", NULL},
                                                {"etag", NULL},
                                                {"expect", NULL},
                                                {"expires", NULL},
                                                {"from", NULL},
                                                {"host", NULL},
                                                {"if-match", NULL},
                                                {"if-modified-since", NULL},
                                                {"if-none-match", NULL},
                                                {"if-range", NULL},
                                                {"if-unmodified-since", NULL},
                                                {"last-modified", NULL},
                                                {"link", NULL},
                                                {"location", NULL},
                                                {"max-forwards", NULL},
                                                {"proxy-authenticate", NULL},
                                                {"proxy-authorization", NULL},
                                                {"range", NULL},
                                                {"referer", NULL},
                                                {"refresh", NULL},
                                                {"retry-after", NULL},
                                                {"server", NULL},
                                                {"set-cookie", NULL},
                                                {"strict-transport-security",
                                                 NULL},
                                                {"transfer-encoding", NULL},
                                                {"user-agent", NULL},
                                                {"vary", NULL},
                                                {"via", NULL},
                                                {"www-authenticate", NULL}};

/* Huffman decoding: https://tools.ietf.org/html/rfc7541#appendix-B

'0' ( 48)  |00000                                         0  [ 5]
'1' ( 49)  |00001                                         1  [ 5]
'2' ( 50)  |00010                                         2  [ 5]
'a' ( 97)  |00011                                         3  [ 5]
'c' ( 99)  |00100                                         4  [ 5]
'e' (101)  |00101                                         5  [ 5]
'i' (105)  |00110                                         6  [ 5]
'o' (111)  |00111                                         7  [ 5]
's' (115)  |01000                                         8  [ 5]
't' (116)  |01001                                         9  [ 5]
' ' ( 32)  |010100                                       14  [ 6]
'%' ( 37)  |010101                                       15  [ 6]
'-' ( 45)  |010110                                       16  [ 6]
'.' ( 46)  |010111                                       17  [ 6]
'/' ( 47)  |011000                                       18  [ 6]
'3' ( 51)  |011001                                       19  [ 6]
'4' ( 52)  |011010                                       1a  [ 6]
'5' ( 53)  |011011                                       1b  [ 6]
'6' ( 54)  |011100                                       1c  [ 6]
'7' ( 55)  |011101                                       1d  [ 6]
'8' ( 56)  |011110                                       1e  [ 6]
'9' ( 57)  |011111                                       1f  [ 6]
'=' ( 61)  |100000                                       20  [ 6]
'A' ( 65)  |100001                                       21  [ 6]
'_' ( 95)  |100010                                       22  [ 6]
'b' ( 98)  |100011                                       23  [ 6]
'd' (100)  |100100                                       24  [ 6]
'f' (102)  |100101                                       25  [ 6]
'g' (103)  |100110                                       26  [ 6]
'h' (104)  |100111                                       27  [ 6]
'l' (108)  |101000                                       28  [ 6]
'm' (109)  |101001                                       29  [ 6]
'n' (110)  |101010                                       2a  [ 6]
'p' (112)  |101011                                       2b  [ 6]
'r' (114)  |101100                                       2c  [ 6]
'u' (117)  |101101                                       2d  [ 6]
':' ( 58)  |1011100                                      5c  [ 7]
'B' ( 66)  |1011101                                      5d  [ 7]
'C' ( 67)  |1011110                                      5e  [ 7]
'D' ( 68)  |1011111                                      5f  [ 7]
'E' ( 69)  |1100000                                      60  [ 7]
'F' ( 70)  |1100001                                      61  [ 7]
'G' ( 71)  |1100010                                      62  [ 7]
'H' ( 72)  |1100011                                      63  [ 7]
'I' ( 73)  |1100100                                      64  [ 7]
'J' ( 74)  |1100101                                      65  [ 7]
'K' ( 75)  |1100110                                      66  [ 7]
'L' ( 76)  |1100111                                      67  [ 7]
'M' ( 77)  |1101000                                      68  [ 7]
'N' ( 78)  |1101001                                      69  [ 7]
'O' ( 79)  |1101010                                      6a  [ 7]
'P' ( 80)  |1101011                                      6b  [ 7]
'Q' ( 81)  |1101100                                      6c  [ 7]
'R' ( 82)  |1101101                                      6d  [ 7]
'S' ( 83)  |1101110                                      6e  [ 7]
'T' ( 84)  |1101111                                      6f  [ 7]
'U' ( 85)  |1110000                                      70  [ 7]
'V' ( 86)  |1110001                                      71  [ 7]
'W' ( 87)  |1110010                                      72  [ 7]
'Y' ( 89)  |1110011                                      73  [ 7]
'j' (106)  |1110100                                      74  [ 7]
'k' (107)  |1110101                                      75  [ 7]
'q' (113)  |1110110                                      76  [ 7]
'v' (118)  |1110111                                      77  [ 7]
'w' (119)  |1111000                                      78  [ 7]
'x' (120)  |1111001                                      79  [ 7]
'y' (121)  |1111010                                      7a  [ 7]
'z' (122)  |1111011                                      7b  [ 7]
'&' ( 38)  |11111000                                     f8  [ 8]
'*' ( 42)  |11111001                                     f9  [ 8]
',' ( 44)  |11111010                                     fa  [ 8]
';' ( 59)  |11111011                                     fb  [ 8]
'X' ( 88)  |11111100                                     fc  [ 8]
'Z' ( 90)  |11111101                                     fd  [ 8]
'!' ( 33)  |11111110|00                                 3f8  [10]
'"' ( 34)  |11111110|01                                 3f9  [10]
'(' ( 40)  |11111110|10                                 3fa  [10]
')' ( 41)  |11111110|11                                 3fb  [10]
'?' ( 63)  |11111111|00                                 3fc  [10]
''' ( 39)  |11111111|010                                7fa  [11]
'+' ( 43)  |11111111|011                                7fb  [11]
'|' (124)  |11111111|100                                7fc  [11]
'#' ( 35)  |11111111|1010                               ffa  [12]
'>' ( 62)  |11111111|1011                               ffb  [12]
    (  0)  |11111111|11000                             1ff8  [13]
'$' ( 36)  |11111111|11001                             1ff9  [13]
'@' ( 64)  |11111111|11010                             1ffa  [13]
'[' ( 91)  |11111111|11011                             1ffb  [13]
']' ( 93)  |11111111|11100                             1ffc  [13]
'~' (126)  |11111111|11101                             1ffd  [13]
'^' ( 94)  |11111111|111100                            3ffc  [14]
'}' (125)  |11111111|111101                            3ffd  [14]
'<' ( 60)  |11111111|1111100                           7ffc  [15]
'`' ( 96)  |11111111|1111101                           7ffd  [15]
'{' (123)  |11111111|1111110                           7ffe  [15]
'\' ( 92)  |11111111|11111110|000                     7fff0  [19]
    (195)  |11111111|11111110|001                     7fff1  [19]
    (208)  |11111111|11111110|010                     7fff2  [19]
    (128)  |11111111|11111110|0110                    fffe6  [20]
    (130)  |11111111|11111110|0111                    fffe7  [20]
    (131)  |11111111|11111110|1000                    fffe8  [20]
    (162)  |11111111|11111110|1001                    fffe9  [20]
    (184)  |11111111|11111110|1010                    fffea  [20]
    (194)  |11111111|11111110|1011                    fffeb  [20]
    (224)  |11111111|11111110|1100                    fffec  [20]
    (226)  |11111111|11111110|1101                    fffed  [20]
    (153)  |11111111|11111110|11100                  1fffdc  [21]
    (161)  |11111111|11111110|11101                  1fffdd  [21]
    (167)  |11111111|11111110|11110                  1fffde  [21]
    (172)  |11111111|11111110|11111                  1fffdf  [21]
    (176)  |11111111|11111111|00000                  1fffe0  [21]
    (177)  |11111111|11111111|00001                  1fffe1  [21]
    (179)  |11111111|11111111|00010                  1fffe2  [21]
    (209)  |11111111|11111111|00011                  1fffe3  [21]
    (216)  |11111111|11111111|00100                  1fffe4  [21]
    (217)  |11111111|11111111|00101                  1fffe5  [21]
    (227)  |11111111|11111111|00110                  1fffe6  [21]
    (229)  |11111111|11111111|00111                  1fffe7  [21]
    (230)  |11111111|11111111|01000                  1fffe8  [21]
    (129)  |11111111|11111111|010010                 3fffd2  [22]
    (132)  |11111111|11111111|010011                 3fffd3  [22]
    (133)  |11111111|11111111|010100                 3fffd4  [22]
    (134)  |11111111|11111111|010101                 3fffd5  [22]
    (136)  |11111111|11111111|010110                 3fffd6  [22]
    (146)  |11111111|11111111|010111                 3fffd7  [22]
    (154)  |11111111|11111111|011000                 3fffd8  [22]
    (156)  |11111111|11111111|011001                 3fffd9  [22]
    (160)  |11111111|11111111|011010                 3fffda  [22]
    (163)  |11111111|11111111|011011                 3fffdb  [22]
    (164)  |11111111|11111111|011100                 3fffdc  [22]
    (169)  |11111111|11111111|011101                 3fffdd  [22]
    (170)  |11111111|11111111|011110                 3fffde  [22]
    (173)  |11111111|11111111|011111                 3fffdf  [22]
    (178)  |11111111|11111111|100000                 3fffe0  [22]
    (181)  |11111111|11111111|100001                 3fffe1  [22]
    (185)  |11111111|11111111|100010                 3fffe2  [22]
    (186)  |11111111|11111111|100011                 3fffe3  [22]
    (187)  |11111111|11111111|100100                 3fffe4  [22]
    (189)  |11111111|11111111|100101                 3fffe5  [22]
    (190)  |11111111|11111111|100110                 3fffe6  [22]
    (196)  |11111111|11111111|100111                 3fffe7  [22]
    (198)  |11111111|11111111|101000                 3fffe8  [22]
    (228)  |11111111|11111111|101001                 3fffe9  [22]
    (232)  |11111111|11111111|101010                 3fffea  [22]
    (233)  |11111111|11111111|101011                 3fffeb  [22]
    (  1)  |11111111|11111111|1011000                7fffd8  [23]
    (135)  |11111111|11111111|1011001                7fffd9  [23]
    (137)  |11111111|11111111|1011010                7fffda  [23]
    (138)  |11111111|11111111|1011011                7fffdb  [23]
    (139)  |11111111|11111111|1011100                7fffdc  [23]
    (140)  |11111111|11111111|1011101                7fffdd  [23]
    (141)  |11111111|11111111|1011110                7fffde  [23]
    (143)  |11111111|11111111|1011111                7fffdf  [23]
    (147)  |11111111|11111111|1100000                7fffe0  [23]
    (149)  |11111111|11111111|1100001                7fffe1  [23]
    (150)  |11111111|11111111|1100010                7fffe2  [23]
    (151)  |11111111|11111111|1100011                7fffe3  [23]
    (152)  |11111111|11111111|1100100                7fffe4  [23]
    (155)  |11111111|11111111|1100101                7fffe5  [23]
    (157)  |11111111|11111111|1100110                7fffe6  [23]
    (158)  |11111111|11111111|1100111                7fffe7  [23]
    (165)  |11111111|11111111|1101000                7fffe8  [23]
    (166)  |11111111|11111111|1101001                7fffe9  [23]
    (168)  |11111111|11111111|1101010                7fffea  [23]
    (174)  |11111111|11111111|1101011                7fffeb  [23]
    (175)  |11111111|11111111|1101100                7fffec  [23]
    (180)  |11111111|11111111|1101101                7fffed  [23]
    (182)  |11111111|11111111|1101110                7fffee  [23]
    (183)  |11111111|11111111|1101111                7fffef  [23]
    (188)  |11111111|11111111|1110000                7ffff0  [23]
    (191)  |11111111|11111111|1110001                7ffff1  [23]
    (197)  |11111111|11111111|1110010                7ffff2  [23]
    (231)  |11111111|11111111|1110011                7ffff3  [23]
    (239)  |11111111|11111111|1110100                7ffff4  [23]
    (  9)  |11111111|11111111|11101010               ffffea  [24]
    (142)  |11111111|11111111|11101011               ffffeb  [24]
    (144)  |11111111|11111111|11101100               ffffec  [24]
    (145)  |11111111|11111111|11101101               ffffed  [24]
    (148)  |11111111|11111111|11101110               ffffee  [24]
    (159)  |11111111|11111111|11101111               ffffef  [24]
    (171)  |11111111|11111111|11110000               fffff0  [24]
    (206)  |11111111|11111111|11110001               fffff1  [24]
    (215)  |11111111|11111111|11110010               fffff2  [24]
    (225)  |11111111|11111111|11110011               fffff3  [24]
    (236)  |11111111|11111111|11110100               fffff4  [24]
    (237)  |11111111|11111111|11110101               fffff5  [24]
    (199)  |11111111|11111111|11110110|0            1ffffec  [25]
    (207)  |11111111|11111111|11110110|1            1ffffed  [25]
    (234)  |11111111|11111111|11110111|0            1ffffee  [25]
    (235)  |11111111|11111111|11110111|1            1ffffef  [25]
    (192)  |11111111|11111111|11111000|00           3ffffe0  [26]
    (193)  |11111111|11111111|11111000|01           3ffffe1  [26]
    (200)  |11111111|11111111|11111000|10           3ffffe2  [26]
    (201)  |11111111|11111111|11111000|11           3ffffe3  [26]
    (202)  |11111111|11111111|11111001|00           3ffffe4  [26]
    (205)  |11111111|11111111|11111001|01           3ffffe5  [26]
    (210)  |11111111|11111111|11111001|10           3ffffe6  [26]
    (213)  |11111111|11111111|11111001|11           3ffffe7  [26]
    (218)  |11111111|11111111|11111010|00           3ffffe8  [26]
    (219)  |11111111|11111111|11111010|01           3ffffe9  [26]
    (238)  |11111111|11111111|11111010|10           3ffffea  [26]
    (240)  |11111111|11111111|11111010|11           3ffffeb  [26]
    (242)  |11111111|11111111|11111011|00           3ffffec  [26]
    (243)  |11111111|11111111|11111011|01           3ffffed  [26]
    (255)  |11111111|11111111|11111011|10           3ffffee  [26]
    (203)  |11111111|11111111|11111011|110          7ffffde  [27]
    (204)  |11111111|11111111|11111011|111          7ffffdf  [27]
    (211)  |11111111|11111111|11111100|000          7ffffe0  [27]
    (212)  |11111111|11111111|11111100|001          7ffffe1  [27]
    (214)  |11111111|11111111|11111100|010          7ffffe2  [27]
    (221)  |11111111|11111111|11111100|011          7ffffe3  [27]
    (222)  |11111111|11111111|11111100|100          7ffffe4  [27]
    (223)  |11111111|11111111|11111100|101          7ffffe5  [27]
    (241)  |11111111|11111111|11111100|110          7ffffe6  [27]
    (244)  |11111111|11111111|11111100|111          7ffffe7  [27]
    (245)  |11111111|11111111|11111101|000          7ffffe8  [27]
    (246)  |11111111|11111111|11111101|001          7ffffe9  [27]
    (247)  |11111111|11111111|11111101|010          7ffffea  [27]
    (248)  |11111111|11111111|11111101|011          7ffffeb  [27]
    (250)  |11111111|11111111|11111101|100          7ffffec  [27]
    (251)  |11111111|11111111|11111101|101          7ffffed  [27]
    (252)  |11111111|11111111|11111101|110          7ffffee  [27]
    (253)  |11111111|11111111|11111101|111          7ffffef  [27]
    (254)  |11111111|11111111|11111110|000          7fffff0  [27]
    (  2)  |11111111|11111111|11111110|0010         fffffe2  [28]
    (  3)  |11111111|11111111|11111110|0011         fffffe3  [28]
    (  4)  |11111111|11111111|11111110|0100         fffffe4  [28]
    (  5)  |11111111|11111111|11111110|0101         fffffe5  [28]
    (  6)  |11111111|11111111|11111110|0110         fffffe6  [28]
    (  7)  |11111111|11111111|11111110|0111         fffffe7  [28]
    (  8)  |11111111|11111111|11111110|1000         fffffe8  [28]
    ( 11)  |11111111|11111111|11111110|1001         fffffe9  [28]
    ( 12)  |11111111|11111111|11111110|1010         fffffea  [28]
    ( 14)  |11111111|11111111|11111110|1011         fffffeb  [28]
    ( 15)  |11111111|11111111|11111110|1100         fffffec  [28]
    ( 16)  |11111111|11111111|11111110|1101         fffffed  [28]
    ( 17)  |11111111|11111111|11111110|1110         fffffee  [28]
    ( 18)  |11111111|11111111|11111110|1111         fffffef  [28]
    ( 19)  |11111111|11111111|11111111|0000         ffffff0  [28]
    ( 20)  |11111111|11111111|11111111|0001         ffffff1  [28]
    ( 21)  |11111111|11111111|11111111|0010         ffffff2  [28]
    ( 23)  |11111111|11111111|11111111|0011         ffffff3  [28]
    ( 24)  |11111111|11111111|11111111|0100         ffffff4  [28]
    ( 25)  |11111111|11111111|11111111|0101         ffffff5  [28]
    ( 26)  |11111111|11111111|11111111|0110         ffffff6  [28]
    ( 27)  |11111111|11111111|11111111|0111         ffffff7  [28]
    ( 28)  |11111111|11111111|11111111|1000         ffffff8  [28]
    ( 29)  |11111111|11111111|11111111|1001         ffffff9  [28]
    ( 30)  |11111111|11111111|11111111|1010         ffffffa  [28]
    ( 31)  |11111111|11111111|11111111|1011         ffffffb  [28]
    (127)  |11111111|11111111|11111111|1100         ffffffc  [28]
    (220)  |11111111|11111111|11111111|1101         ffffffd  [28]
    (249)  |11111111|11111111|11111111|1110         ffffffe  [28]
    ( 10)  |11111111|11111111|11111111|111100      3ffffffc  [30]
    ( 13)  |11111111|11111111|11111111|111101      3ffffffd  [30]
    ( 22)  |11111111|11111111|11111111|111110      3ffffffe  [30]
    (256)  |11111111|11111111|11111111|111111      3fffffff  [30]
*/

struct {
	uint8_t decoded;
	uint8_t bitcount;
	uint32_t encoded;
} hpack_huff_dec[] = {
    {48, 5, 0x0},
    {49, 5, 0x1},
    {50, 5, 0x2},
    {97, 5, 0x3},
    {99, 5, 0x4},
    {101, 5, 0x5},
    {105, 5, 0x6},
    {111, 5, 0x7},
    {115, 5, 0x8},
    {116, 5, 0x9},
    {32, 6, 0x14},
    {37, 6, 0x15},
    {45, 6, 0x16},
    {46, 6, 0x17},
    {47, 6, 0x18},
    {51, 6, 0x19},
    {52, 6, 0x1a},
    {53, 6, 0x1b},
    {54, 6, 0x1c},
    {55, 6, 0x1d},
    {56, 6, 0x1e},
    {57, 6, 0x1f},
    {61, 6, 0x20},
    {65, 6, 0x21},
    {95, 6, 0x22},
    {98, 6, 0x23},
    {100, 6, 0x24},
    {102, 6, 0x25},
    {103, 6, 0x26},
    {104, 6, 0x27},
    {108, 6, 0x28},
    {109, 6, 0x29},
    {110, 6, 0x2a},
    {112, 6, 0x2b},
    {114, 6, 0x2c},
    {117, 6, 0x2d},
    {58, 7, 0x5c},
    {66, 7, 0x5d},
    {67, 7, 0x5e},
    {68, 7, 0x5f},
    {69, 7, 0x60},
    {70, 7, 0x61},
    {71, 7, 0x62},
    {72, 7, 0x63},
    {73, 7, 0x64},
    {74, 7, 0x65},
    {75, 7, 0x66},
    {76, 7, 0x67},
    {77, 7, 0x68},
    {78, 7, 0x69},
    {79, 7, 0x6a},
    {80, 7, 0x6b},
    {81, 7, 0x6c},
    {82, 7, 0x6d},
    {83, 7, 0x6e},
    {84, 7, 0x6f},
    {85, 7, 0x70},
    {86, 7, 0x71},
    {87, 7, 0x72},
    {89, 7, 0x73},
    {106, 7, 0x74},
    {107, 7, 0x75},
    {113, 7, 0x76},
    {118, 7, 0x77},
    {119, 7, 0x78},
    {120, 7, 0x79},
    {121, 7, 0x7a},
    {122, 7, 0x7b},
    {38, 8, 0xf8},
    {42, 8, 0xf9},
    {44, 8, 0xfa},
    {59, 8, 0xfb},
    {88, 8, 0xfc},
    {90, 8, 0xfd},
    {33, 10, 0x3f8},
    {34, 10, 0x3f9},
    {40, 10, 0x3fa},
    {41, 10, 0x3fb},
    {63, 10, 0x3fc},
    {39, 11, 0x7fa},
    {43, 11, 0x7fb},
    {124, 11, 0x7fc},
    {35, 12, 0xffa},
    {62, 12, 0xffb},
    {0, 13, 0x1ff8},
    {36, 13, 0x1ff9},
    {64, 13, 0x1ffa},
    {91, 13, 0x1ffb},
    {93, 13, 0x1ffc},
    {126, 13, 0x1ffd},
    {94, 14, 0x3ffc},
    {125, 14, 0x3ffd},
    {60, 15, 0x7ffc},
    {96, 15, 0x7ffd},
    {123, 15, 0x7ffe},
    {92, 19, 0x7fff0},
    {195, 19, 0x7fff1},
    {208, 19, 0x7fff2},
    {128, 20, 0xfffe6},
    {130, 20, 0xfffe7},
    {131, 20, 0xfffe8},
    {162, 20, 0xfffe9},
    {184, 20, 0xfffea},
    {194, 20, 0xfffeb},
    {224, 20, 0xfffec},
    {226, 20, 0xfffed},
    {153, 21, 0x1fffdc},
    {161, 21, 0x1fffdd},
    {167, 21, 0x1fffde},
    {172, 21, 0x1fffdf},
    {176, 21, 0x1fffe0},
    {177, 21, 0x1fffe1},
    {179, 21, 0x1fffe2},
    {209, 21, 0x1fffe3},
    {216, 21, 0x1fffe4},
    {217, 21, 0x1fffe5},
    {227, 21, 0x1fffe6},
    {229, 21, 0x1fffe7},
    {230, 21, 0x1fffe8},
    {129, 22, 0x3fffd2},
    {132, 22, 0x3fffd3},
    {133, 22, 0x3fffd4},
    {134, 22, 0x3fffd5},
    {136, 22, 0x3fffd6},
    {146, 22, 0x3fffd7},
    {154, 22, 0x3fffd8},
    {156, 22, 0x3fffd9},
    {160, 22, 0x3fffda},
    {163, 22, 0x3fffdb},
    {164, 22, 0x3fffdc},
    {169, 22, 0x3fffdd},
    {170, 22, 0x3fffde},
    {173, 22, 0x3fffdf},
    {178, 22, 0x3fffe0},
    {181, 22, 0x3fffe1},
    {185, 22, 0x3fffe2},
    {186, 22, 0x3fffe3},
    {187, 22, 0x3fffe4},
    {189, 22, 0x3fffe5},
    {190, 22, 0x3fffe6},
    {196, 22, 0x3fffe7},
    {198, 22, 0x3fffe8},
    {228, 22, 0x3fffe9},
    {232, 22, 0x3fffea},
    {233, 22, 0x3fffeb},
    {1, 23, 0x7fffd8},
    {135, 23, 0x7fffd9},
    {137, 23, 0x7fffda},
    {138, 23, 0x7fffdb},
    {139, 23, 0x7fffdc},
    {140, 23, 0x7fffdd},
    {141, 23, 0x7fffde},
    {143, 23, 0x7fffdf},
    {147, 23, 0x7fffe0},
    {149, 23, 0x7fffe1},
    {150, 23, 0x7fffe2},
    {151, 23, 0x7fffe3},
    {152, 23, 0x7fffe4},
    {155, 23, 0x7fffe5},
    {157, 23, 0x7fffe6},
    {158, 23, 0x7fffe7},
    {165, 23, 0x7fffe8},
    {166, 23, 0x7fffe9},
    {168, 23, 0x7fffea},
    {174, 23, 0x7fffeb},
    {175, 23, 0x7fffec},
    {180, 23, 0x7fffed},
    {182, 23, 0x7fffee},
    {183, 23, 0x7fffef},
    {188, 23, 0x7ffff0},
    {191, 23, 0x7ffff1},
    {197, 23, 0x7ffff2},
    {231, 23, 0x7ffff3},
    {239, 23, 0x7ffff4},
    {9, 24, 0xffffea},
    {142, 24, 0xffffeb},
    {144, 24, 0xffffec},
    {145, 24, 0xffffed},
    {148, 24, 0xffffee},
    {159, 24, 0xffffef},
    {171, 24, 0xfffff0},
    {206, 24, 0xfffff1},
    {215, 24, 0xfffff2},
    {225, 24, 0xfffff3},
    {236, 24, 0xfffff4},
    {237, 24, 0xfffff5},
    {199, 25, 0x1ffffec},
    {207, 25, 0x1ffffed},
    {234, 25, 0x1ffffee},
    {235, 25, 0x1ffffef},
    {192, 26, 0x3ffffe0},
    {193, 26, 0x3ffffe1},
    {200, 26, 0x3ffffe2},
    {201, 26, 0x3ffffe3},
    {202, 26, 0x3ffffe4},
    {205, 26, 0x3ffffe5},
    {210, 26, 0x3ffffe6},
    {213, 26, 0x3ffffe7},
    {218, 26, 0x3ffffe8},
    {219, 26, 0x3ffffe9},
    {238, 26, 0x3ffffea},
    {240, 26, 0x3ffffeb},
    {242, 26, 0x3ffffec},
    {243, 26, 0x3ffffed},
    {255, 26, 0x3ffffee},
    {203, 27, 0x7ffffde},
    {204, 27, 0x7ffffdf},
    {211, 27, 0x7ffffe0},
    {212, 27, 0x7ffffe1},
    {214, 27, 0x7ffffe2},
    {221, 27, 0x7ffffe3},
    {222, 27, 0x7ffffe4},
    {223, 27, 0x7ffffe5},
    {241, 27, 0x7ffffe6},
    {244, 27, 0x7ffffe7},
    {245, 27, 0x7ffffe8},
    {246, 27, 0x7ffffe9},
    {247, 27, 0x7ffffea},
    {248, 27, 0x7ffffeb},
    {250, 27, 0x7ffffec},
    {251, 27, 0x7ffffed},
    {252, 27, 0x7ffffee},
    {253, 27, 0x7ffffef},
    {254, 27, 0x7fffff0},
    {2, 28, 0xfffffe2},
    {3, 28, 0xfffffe3},
    {4, 28, 0xfffffe4},
    {5, 28, 0xfffffe5},
    {6, 28, 0xfffffe6},
    {7, 28, 0xfffffe7},
    {8, 28, 0xfffffe8},
    {11, 28, 0xfffffe9},
    {12, 28, 0xfffffea},
    {14, 28, 0xfffffeb},
    {15, 28, 0xfffffec},
    {16, 28, 0xfffffed},
    {17, 28, 0xfffffee},
    {18, 28, 0xfffffef},
    {19, 28, 0xffffff0},
    {20, 28, 0xffffff1},
    {21, 28, 0xffffff2},
    {23, 28, 0xffffff3},
    {24, 28, 0xffffff4},
    {25, 28, 0xffffff5},
    {26, 28, 0xffffff6},
    {27, 28, 0xffffff7},
    {28, 28, 0xffffff8},
    {29, 28, 0xffffff9},
    {30, 28, 0xffffffa},
    {31, 28, 0xffffffb},
    {127, 28, 0xffffffc},
    {220, 28, 0xffffffd},
    {249, 28, 0xffffffe},
    {10, 30, 0x3ffffffc},
    {13, 30, 0x3ffffffd},
    {22, 30, 0x3ffffffe},
    {(uint8_t)256, 30, 0x3fffffff} /* filling/termination */
};

/* highest value with 5, 6, 7, ... 28, 29, 30 and all (32) bits */
uint32_t hpack_huff_end_code[] = {0x9,       0x2d,       0x7b,       0xfd,
                                  0,         0x3fc,      0x7fc,      0xffb,
                                  0x1ffd,    0x3ffd,     0x7ffe,     0,
                                  0,         0,          0x7fff2,    0xfffed,
                                  0x1fffe8,  0x3fffeb,   0x7ffff4,   0xfffff5,
                                  0x1ffffef, 0x3ffffee,  0x7fffff0,  0xffffffe,
                                  0,         0x3ffffffe, 0xFFFFFFFFu};

/* lowest index with 5, 6, 7, ... 28, 29, 30 and all (32) bits */
uint8_t hpack_huff_start_index[] = {0,   10,  36,  68,  0,   74,  79, 82,  84,
                                    90,  92,  0,   0,   0,   95,  98, 106, 119,
                                    145, 174, 186, 190, 205, 224, 0,  253, 0};


/* Function to decode an integer from a HPACK encoded block */
/* Integers have a variable size encoding, according to the RFC.
 * The integer starts at index *i, idx_mask masks the available bits in
 * the first byte. The index *i is advanced until the end of the
 * encoded integer.
 */
static uint64_t
hpack_getnum(const uint8_t *buf,
             int *i,
             uint8_t idx_mask,
             struct mg_context *ctx)
{
	uint64_t num = (buf[*i] & idx_mask);

	(void)ctx;

	if (num == idx_mask) {
		/* Algorithm from https://tools.ietf.org/html/rfc7541#section-5.1 */
		uint32_t M = 0;
		do {
			(*i)++;
			num = num + ((buf[*i] & 0x7F) << M);
			M += 7;
		} while ((buf[*i] & 0x80) == 0x80);
	}

	(*i)++;
	return num;
}


/* Function to decode a string from a HPACK encoded block */
/* Strings have a variable size and can be either encoded directly (8 bits
 * per char), or using huffman encoding (variable bits per char).
 * The string starts at index *i. This index is advanced until the end of
 * the encoded string.
 */
static char *
hpack_decode(const uint8_t *buf, int *i, int max_i, struct mg_context *ctx)
{
	uint64_t byte_len64;
	int byte_len;
	int bit_len;
	uint8_t is_huff = ((buf[*i] & 0x80) == 0x80);

	/* Get length of string in bytes */
	byte_len64 = hpack_getnum(buf, i, 0x7f, ctx);
	if (byte_len64 > 1024) {
		/* TODO */
		return NULL;
	}
	byte_len = (int)byte_len64;
	bit_len = byte_len * 8;

	/* check size */
	if ((*i) + byte_len > max_i) {
		return NULL;
	}

	/* Now read the string */
	if (!is_huff) {
		/* Not huffman encoded: Copy directly */
		char *result = (char *)mg_malloc_ctx(byte_len + 1, ctx);
		if (result) {
			memcpy(result, buf + (*i), byte_len);
			result[byte_len] = 0;
		}
		(*i) += byte_len;
		return result;

	} else {
		/* Huffman encoded: need to decode bitwise */
		const uint8_t *pData =
		    buf + (*i);           /* begin pointer of bit input string */
		int bitRead = 0;          /* number of encoded bits read */
		uint32_t bytesStored = 0; /* number of decoded bytes stored */
		uint8_t str[2048];        /* storage buffer for decoded string */

		for (;;) {
			uint32_t accu = 0; /* accu register: collect bits */
			uint8_t bc = 0;    /* number of bits collected */
			int n;

			/* Collect bits in this loop, until we have a valid huff code in
			 * accu */
			do {
				accu <<= 1;
				accu |= (pData[bitRead / 8] >> (7 - (bitRead & 7))) & 1;
				bitRead++;
				bc++;
				if (bitRead > bit_len) {
					/* We used all bits. Return the decoded string. */
					str[bytesStored] = 0; /* Terminate string */
					(*i) += byte_len;     /* Advance parsing index */
					return mg_strdup_ctx((char *)str,
					                     ctx); /* Return a string copy */
				}
			} while ((bc < 5) || (accu > hpack_huff_end_code[bc - 5]));

			/* Find matching code in huffman encoding table */
			for (n = hpack_huff_start_index[bc - 5]; n < 256; n++) {
				if (accu == hpack_huff_dec[n].encoded) {
					str[bytesStored] = hpack_huff_dec[n].decoded;
					bytesStored++;
					break;
				}
			}
			if (bytesStored == sizeof(str)) {
				/* too long */
				return 0;
			}
		}
	}
}


static void
append_bits(uint8_t *target,
            uint32_t offset,
            uint32_t value,
            uint8_t value_bits)
{
	uint32_t offset_bytes = offset / 8;
	uint32_t offset_bits = offset % 8;
	uint32_t remaining_bits, ac;

	value &= ~(0xFFFFFFFF << value_bits);

	remaining_bits = 8 - offset_bits;

	if (value_bits <= remaining_bits) {
		ac = value << (remaining_bits - value_bits);
		target[offset_bytes] |= ac;
		return;
	}

	ac = value >> (value_bits - remaining_bits);
	target[offset_bytes] |= ac;
	append_bits(target,
	            offset + remaining_bits,
	            value,
	            value_bits - remaining_bits);
}


static int
hpack_encode(uint8_t *store, const char *load, int lower)
{
	uint32_t nohuff_len = strlen(load);

	uint32_t len_bits = 0;
	uint32_t len_bytes;
	uint32_t spare_bits;
	uint32_t i;

	memset(store, 0, nohuff_len + 1);

	for (i = 0; i < nohuff_len; i++) {
		uint8_t b = (uint8_t)((char)(lower ? tolower(load[i]) : load[i]));
		int idx;

		for (idx = 0; idx <= 255; idx++) {
			if (hpack_huff_dec[idx].decoded == b) {
				append_bits((uint8_t *)store + 1,
				            len_bits,
				            hpack_huff_dec[idx].encoded,
				            hpack_huff_dec[idx].bitcount);
				len_bits += hpack_huff_dec[idx].bitcount;
				break;
			}
		}
	}

	len_bytes = (len_bits + 7) / 8;
	spare_bits = len_bytes * 8 - len_bits;
	if (spare_bits) {
		append_bits((uint8_t *)store + 1, len_bits, 0xFFFFFFFF, spare_bits);
	}

	if (len_bytes >= 127) {
		// TODO: Shift string and encode len in more bytes
		return 0;
	}
	*store = 0x80 + (uint8_t)len_bytes;

	if ((len_bytes >= nohuff_len) && (0)) {
		*store = (uint8_t)nohuff_len;
		if (lower) {
			for (i = 1; i <= nohuff_len; i++) {
				store[i] = tolower(load[i]);
			}
		} else {
			memcpy(store + 1, load, nohuff_len);
		}
		return nohuff_len + 1;
	} else {
		/*
		int i = 0;
		char *test = hpack_decode(store, &i, NULL);
		i = i; // breakpoint for debugging / testing
		*/
	}

	return len_bytes + 1;
}


/***********************************************************************/
/***  HTTP 2                                                         ***/
/***********************************************************************/


static const char http2_pri[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
static const unsigned char http2_pri_len = 24; /* = strlen(http2_pri) */


/* Read and check the HTTP/2 primer/preface:
 * See https://tools.ietf.org/html/rfc7540#section-3.5 */
static int
is_valid_http2_primer(struct mg_connection *conn)
{
	size_t pri_len = http2_pri_len;
	char buf[32]; /* Buffer must hold 24 bytes primer */

	int read_pri_len = mg_read(conn, buf, pri_len);
	if (read_pri_len != (int)pri_len) {
		/* Size does not match.
		 * This includes cases where mg_read returns error codes */
		return 0;
	}
	if (0 != memcmp(buf, http2_pri, pri_len)) {
		/* Primer does not match */
		return 0;
	}
	/* Primer does match */
	return 1;
}


#define mg_xwrite(conn, data, len)                                             \
	push_all((conn)->phys_ctx,                                                 \
	         NULL,                                                             \
	         (conn)->client.sock,                                              \
	         (conn)->ssl,                                                      \
	         (const char *)(data),                                             \
	         (int)(len))


static void
http2_settings_acknowledge(struct mg_connection *conn)
{
	unsigned char http2_set_ackn_frame[9] = {0, 0, 0, 4, 1, 0, 0, 0, 0};

	DEBUG_TRACE("%s", "Sending settings frame");
	mg_xwrite(conn, http2_set_ackn_frame, 9);
}


struct http2_settings {
	uint32_t settings_header_table_size;
	uint32_t settings_enable_push;
	uint32_t settings_max_concurrent_streams;
	uint32_t settings_initial_window_size;
	uint32_t settings_max_frame_size;
	uint32_t settings_max_header_list_size;
};


const struct http2_settings http2_default_settings =
    {4096, 1, UINT32_MAX, 65535, 16384, UINT32_MAX};

const struct http2_settings http2_civetweb_server_settings =
    {4096, 0, 100, 65535, 16384, 65535};


enum {
	HTTP2_ERR_NO_ERROR = 0,
	HTTP2_ERR_PROTOCOL_ERROR,
	HTTP2_ERR_INTERNAL_ERROR,
	HTTP2_ERR_FLOW_CONTROL_ERROR,
	HTTP2_ERR_SETTINGS_TIMEOUT,
	HTTP2_ERR_STREAM_CLOSED,
	HTTP2_ERR_FRAME_SIZE_ERROR,
	HTTP2_ERR_REFUSED_STREAM,
	HTTP2_ERR_CANCEL,
	HTTP2_ERR_COMPRESSION_ERROR,
	HTTP2_ERR_CONNECT_ERROR,
	HTTP2_ERR_ENHANCE_YOUR_CALM,
	HTTP2_ERR_INADEQUATE_SECURITY,
	HTTP2_ERR_HTTP_1_1_REQUIRED
};


static void
http2_send_settings(struct mg_connection *conn,
                    const struct http2_settings *set)
{
	uint16_t id;
	uint32_t data;
	uint8_t http2_settings_frame[9] = {0, 0, 36, 4, 0, 0, 0, 0, 0};
	mg_xwrite(conn, http2_settings_frame, 9);

	id = htons(1);
	data = htonl(set->settings_header_table_size);
	mg_xwrite(conn, &id, 2);
	mg_xwrite(conn, &data, 4);

	id = htons(1);
	data = htonl(set->settings_enable_push);
	mg_xwrite(conn, &id, 2);
	mg_xwrite(conn, &data, 4);

	id = htons(1);
	data = htonl(set->settings_max_concurrent_streams);
	mg_xwrite(conn, &id, 2);
	mg_xwrite(conn, &data, 4);

	id = htons(1);
	data = htonl(set->settings_initial_window_size);
	mg_xwrite(conn, &id, 2);
	mg_xwrite(conn, &data, 4);

	id = htons(1);
	data = htonl(set->settings_max_frame_size);
	mg_xwrite(conn, &id, 2);
	mg_xwrite(conn, &data, 4);

	id = htons(1);
	data = htonl(set->settings_max_header_list_size);
	mg_xwrite(conn, &id, 2);
	mg_xwrite(conn, &data, 4);

	DEBUG_TRACE("%s", "HTTP2 settings sent");
}


static int
http2_send_response_headers(struct mg_connection *conn)
{
	unsigned char http2_header_frame[9] = {0, 0, 0, 1, 4, 0, 0, 0, 0};
	uint8_t header_bin[1024];
	uint16_t header_len = 0;
	int has_date = 0;
	int has_connection_header = 0;
	int i, ok;

	if ((conn->status_code < 100) || (conn->status_code > 999)) {
		/* Invalid status: Set status to "Internal Server Error" */
		conn->status_code = 500;
	}

	switch (conn->status_code) {
	case 200:
		header_bin[header_len++] = 0x88;
		break;
	case 204:
		header_bin[header_len++] = 0x89;
		break;
	case 206:
		header_bin[header_len++] = 0x8A;
		break;
	case 304:
		header_bin[header_len++] = 0x8B;
		break;
	case 400:
		header_bin[header_len++] = 0x8C;
		break;
	case 404:
		header_bin[header_len++] = 0x8D;
		break;
	case 500:
		header_bin[header_len++] = 0x8E;
		break;
	default:
		header_bin[header_len++] = 0x48;
		header_bin[header_len++] = 0x03;
		header_bin[header_len++] = 0x30 + (conn->status_code / 100);
		header_bin[header_len++] = 0x30 + ((conn->status_code / 10) % 10);
		header_bin[header_len++] = 0x30 + (conn->status_code % 10);
		break;
	}

	/* Add all headers */
	for (i = 0; i < conn->response_info.num_headers; i++) {
		uint16_t predef = 0;
		uint16_t j;

		/* Filter headers not valid in HTTP/2 */
		if (!mg_strcasecmp("Connection",
		                   conn->response_info.http_headers[i].name)) {
			has_connection_header = 1;
			continue; /* do not send */
		}

		/* Check if this header is known in HPACK (static table index 15 to 61)
		 * see https://tools.ietf.org/html/rfc7541#appendix-A */
		for (j = 15; j <= 61; j++) {
			if (!mg_strcasecmp(hpack_predefined[j].name,
			                   conn->response_info.http_headers[i].name)) {
				predef = j;
				break;
			}
		}

		if (predef) {
			/* Predefined header found */
			header_bin[header_len++] = 0x40 + predef;
		} else {
			/* Rare header, do not index */
			header_bin[header_len++] = 0x10;
			j = hpack_encode(header_bin + header_len,
			                 conn->response_info.http_headers[i].name,
			                 1);
			header_len += j;
		}

		j = hpack_encode(header_bin + header_len,
		                 conn->response_info.http_headers[i].value,
		                 0);
		header_len += j;

		/* Mark required headers as sent */
		if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) {
			has_date = 1;
		}
	}

	/* Add required headers, if they have not been sent yet */
	if (!has_date) {
		/* Create header frame */
		char date[64];
		uint8_t date_len;
		time_t curtime = time(NULL);

		gmt_time_string(date, sizeof(date), &curtime);
		date_len = (uint8_t)strlen(date);

		header_bin[header_len++] =
		    0x61; /* "Date" predefined HPACK index 33 (0x21) + 0x40 */
		header_bin[header_len++] = date_len;
		memcpy(header_bin + header_len, date, date_len);
		header_len += date_len;
	}

	http2_header_frame[1] = (header_len & 0xFF00) >> 8;
	http2_header_frame[2] = (header_len & 0xFF);

	http2_header_frame[5] = (conn->http2.stream_id & 0xFF000000u) >> 24;
	http2_header_frame[6] = (conn->http2.stream_id & 0xFF0000u) >> 16;
	http2_header_frame[7] = (conn->http2.stream_id & 0xFF00u) >> 8;
	http2_header_frame[8] = (conn->http2.stream_id & 0xFFu);

	/* Send header frame */
	ok = 1;
	if (mg_xwrite(conn, http2_header_frame, 9) != 9) {
		ok = 0;
	} else if (mg_xwrite(conn, header_bin, header_len) != header_len) {
		ok = 0;
	}
	if (ok) {
		DEBUG_TRACE("HTTP2 response header sent: stream %u",
		            conn->http2.stream_id);
	} else {
		DEBUG_TRACE("HTTP2 response header sending error: stream %u",
		            conn->http2.stream_id);
	}

	(void)has_connection_header; /* ignore for the moment */

	return ok;
}


static void
http2_data_frame_head(struct mg_connection *conn,
                      uint32_t frame_size,
                      int is_final)
{
	unsigned char http2_data_frame[9];
	uint32_t stream_id = conn->http2.stream_id;

	http2_data_frame[0] = (frame_size & 0xFF0000) >> 16;
	http2_data_frame[1] = (frame_size & 0xFF00) >> 8;
	http2_data_frame[2] = (frame_size & 0xFF);

	http2_data_frame[3] = 0; /* frame type "DATA" */
	http2_data_frame[4] = (is_final ? 1 : 0);

	http2_data_frame[5] = (stream_id & 0xFF000000u) >> 24;
	http2_data_frame[6] = (stream_id & 0xFF0000u) >> 16;
	http2_data_frame[7] = (stream_id & 0xFF00u) >> 8;
	http2_data_frame[8] = (stream_id & 0xFFu);

	DEBUG_TRACE("HTTP2 begin data frame: stream %u, frame_size %u (final: %i)",
	            stream_id,
	            frame_size,
	            is_final);

	mg_xwrite(conn, http2_data_frame, 9);
}


static void
http2_send_window(struct mg_connection *conn,
                  uint32_t stream_id,
                  uint32_t window_size)
{
	unsigned char http2_window_frame[9] = {0, 0, 4, 8, 0, 0, 0, 0, 0};
	uint32_t data = htonl(window_size);

	DEBUG_TRACE("HTTP2 send window_size: stream %u, error %u",
	            stream_id,
	            window_size);

	http2_window_frame[5] = (stream_id & 0xFF000000u) >> 24;
	http2_window_frame[6] = (stream_id & 0xFF0000u) >> 16;
	http2_window_frame[7] = (stream_id & 0xFF00u) >> 8;
	http2_window_frame[8] = (stream_id & 0xFFu);
	mg_xwrite(conn, http2_window_frame, 9);
	mg_xwrite(conn, &data, 4);
}


static void
http2_reset_stream(struct mg_connection *conn,
                   uint32_t stream_id,
                   uint32_t error_id)
{
	unsigned char http2_reset_frame[9] = {0, 0, 4, 3, 0, 0, 0, 0, 0};
	uint32_t val = htonl(error_id);

	DEBUG_TRACE("HTTP2 send reset: stream %u, error %u", stream_id, error_id);

	http2_reset_frame[5] = (stream_id & 0xFF000000u) >> 24;
	http2_reset_frame[6] = (stream_id & 0xFF0000u) >> 16;
	http2_reset_frame[7] = (stream_id & 0xFF00u) >> 8;
	http2_reset_frame[8] = (stream_id & 0xFFu);
	mg_xwrite(conn, http2_reset_frame, 9);
	mg_xwrite(conn, &val, 4);
}


static void
http2_must_use_http1(struct mg_connection *conn)
{
	DEBUG_TRACE("HTTP2 not available for this URL (%s)", conn->path_info);
	http2_reset_stream(conn, conn->http2.stream_id, 0xd);
}


/* The HTTP2 implementation collects request headers as array of dynamically
 * allocated string values. This array must be freed once the request is
 * handled.
 * This is different to the HTTP/1.x implementation: For HTTP/1.x, the header
 * list is implemented as pointers into an existing buffer, so free must not
 * be called for HTTP/1.x.
 * Thus free_buffered_request_header_list is in mod_http2.inl.
 */
#if defined(DEBUG)
static int mem_h_count = 0;
static int mem_d_count = 0;
#define CHECK_LEAK_HDR_ALLOC(ptr)                                              \
	DEBUG_TRACE("H NEW %p (%i): %s", ptr, ++mem_h_count, (const char *)ptr)
#define CHECK_LEAK_HDR_FREE(ptr)                                               \
	DEBUG_TRACE("H DEL %p (%i): %s", ptr, --mem_h_count, (const char *)ptr)
#define CHECK_LEAK_DYN_ALLOC(ptr)                                              \
	DEBUG_TRACE("D NEW %p (%i): %s", ptr, ++mem_d_count, (const char *)ptr)
#define CHECK_LEAK_DYN_FREE(ptr)                                               \
	DEBUG_TRACE("D DEL %p (%i): %s", ptr, --mem_d_count, (const char *)ptr)
#else
#define CHECK_LEAK_HDR_ALLOC(ptr)
#define CHECK_LEAK_HDR_FREE(ptr)
#define CHECK_LEAK_DYN_ALLOC(ptr)
#define CHECK_LEAK_DYN_FREE(ptr)
#endif


/* The dynamic header table may be resized on a HTTP2 client request.
 * A tablesize=0 will free all memory.
 */
static void
purge_dynamic_header_table(struct mg_connection *conn, uint32_t tableSize)
{
	DEBUG_TRACE("HTTP2 dynamic header table set to %u", tableSize);
	while (conn->http2.dyn_table_size > tableSize) {
		conn->http2.dyn_table_size--;

		CHECK_LEAK_DYN_FREE(
		    conn->http2.dyn_table[conn->http2.dyn_table_size].name);
		CHECK_LEAK_DYN_FREE(
		    conn->http2.dyn_table[conn->http2.dyn_table_size].value);

		mg_free((void *)conn->http2.dyn_table[conn->http2.dyn_table_size].name);
		conn->http2.dyn_table[conn->http2.dyn_table_size].name = 0;
		mg_free(
		    (void *)conn->http2.dyn_table[conn->http2.dyn_table_size].value);
		conn->http2.dyn_table[conn->http2.dyn_table_size].value = 0;
	}
}


/* Internal function to free request header list.
 * Not to be confused with the response header list.
 */
static void
free_buffered_request_header_list(struct mg_connection *conn)
{
	while (conn->request_info.num_headers > 0) {
		conn->request_info.num_headers--;

		CHECK_LEAK_HDR_FREE(
		    conn->request_info.http_headers[conn->request_info.num_headers]
		        .name);
		CHECK_LEAK_HDR_FREE(
		    conn->request_info.http_headers[conn->request_info.num_headers]
		        .value);

		mg_free((void *)conn->request_info
		            .http_headers[conn->request_info.num_headers]
		            .name);
		conn->request_info.http_headers[conn->request_info.num_headers].name =
		    0;
		mg_free((void *)conn->request_info
		            .http_headers[conn->request_info.num_headers]
		            .value);
		conn->request_info.http_headers[conn->request_info.num_headers].value =
		    0;
	}
}


/* HTTP2 requires a different handling loop */
static void
handle_http2(struct mg_connection *conn)
{
	unsigned char http2_frame_head[9];
	uint32_t http2_frame_size;
	uint8_t http2_frame_type;
	uint8_t http2_frame_flags;
	uint32_t http2_frame_stream_id;
	uint32_t http_window_length = 0;
	int bytes_read;
	uint8_t *buf;
	int my_settings_accepted = 0;
	const char *my_hpack_headers[128];

	struct http2_settings client_settings = http2_default_settings;
	struct http2_settings server_settings = http2_default_settings;

	/* Send own settings */
	http2_send_settings(conn, &http2_civetweb_server_settings);
	// http2_send_window(conn, 0, /* 0x3fff0001 */ 1024*1024);

	/* initialize hpack header table with predefined header fields */
	memset((void *)my_hpack_headers, 0, sizeof(my_hpack_headers));
	memcpy((void *)my_hpack_headers,
	       hpack_predefined,
	       sizeof(hpack_predefined));

	buf = (uint8_t *)mg_malloc_ctx(server_settings.settings_max_frame_size,
	                               conn->phys_ctx);
	if (!buf) {
		/* Out of memory */
		DEBUG_TRACE("%s", "Out of memory for HTTP2 frame");
		return;
	}

	for (;;) {
		/* HTTP/2 is handled frame by frame */
		int frame_is_end_stream = 0;
		int frame_is_end_headers = 0;
		int frame_is_padded = 0;
		int frame_is_priority = 0;

#if defined(USE_SERVER_STATS)
		conn->conn_state = 3; /* HTTP/2 ready */
#endif

		bytes_read = mg_read(conn, http2_frame_head, sizeof(http2_frame_head));
		if (bytes_read != sizeof(http2_frame_head)) {
			/* TODO: errormsg */
			goto clean_http2;
		}

		/* Extract data from frame header */
		http2_frame_size = ((uint32_t)http2_frame_head[0] * 0x10000u)
		                   + ((uint32_t)http2_frame_head[1] * 0x100u)
		                   + ((uint32_t)http2_frame_head[2]);
		http2_frame_type = http2_frame_head[3];
		http2_frame_flags = http2_frame_head[4];
		http2_frame_stream_id = ((uint32_t)http2_frame_head[5] * 0x1000000u)
		                        + ((uint32_t)http2_frame_head[6] * 0x10000u)
		                        + ((uint32_t)http2_frame_head[7] * 0x100u)
		                        + ((uint32_t)http2_frame_head[8]);

		frame_is_end_stream = (0 != (http2_frame_flags & 0x01));
		frame_is_end_headers = (0 != (http2_frame_flags & 0x04));
		frame_is_padded = (0 != (http2_frame_flags & 0x08));
		frame_is_priority = (0 != (http2_frame_flags & 0x20));

		if (http2_frame_size > server_settings.settings_max_frame_size) {
			/* TODO: Error Message */
			DEBUG_TRACE("HTTP2 frame too large (%lu)",
			            (unsigned long)http2_frame_size);
			goto clean_http2;
		}
		bytes_read = mg_read(conn, buf, http2_frame_size);
		if (bytes_read != (int)http2_frame_size) {
			/* TODO: Error Message - or read again? */
			DEBUG_TRACE("HTTP2 read error (%li != %li)",
			            (signed long int)bytes_read,
			            (signed long int)http2_frame_size);
			goto clean_http2;
		}

		DEBUG_TRACE("HTTP2 frame type %u, size %u, stream %u, flags %02x",
		            http2_frame_type,
		            http2_frame_size,
		            http2_frame_stream_id,
		            http2_frame_flags);

		/* Further processing according to frame type. See definition: */
		/* https://tools.ietf.org/html/rfc7540#section-6 */
		switch (http2_frame_type) {

		case 0: /* DATA */
		{
			/* TODO */
			DEBUG_TRACE("%s", "HTTP2 DATA frame?");
		} break;

		case 1: /* HEADERS */
		{
			int i = 0;
			uint8_t padding = 0;
			uint32_t dependency = 0;
			uint8_t weight = 0;
			uint8_t exclusive = 0;

			/* Request start time */
			clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));

			if (frame_is_padded) {
				padding = buf[i];
				i++;
				DEBUG_TRACE("HTTP2 frame padded by %u bytes", padding);
			}
			if (frame_is_priority) {
				uint32_t val = ((uint32_t)buf[0 + i] * 0x1000000u)
				               + ((uint32_t)buf[1 + i] * 0x10000u)
				               + ((uint32_t)buf[2 + i] * 0x100u)
				               + ((uint32_t)buf[3 + i]);
				dependency = (val & 0x7FFFFFFFu);
				exclusive = ((val & 0x80000000u) != 0);
				weight = buf[4 + i];
				i += 5;
				DEBUG_TRACE(
				    "HTTP2 frame weight %u, dependency %u (exclusive: %i)",
				    weight,
				    dependency,
				    exclusive);
			}

			conn->request_info.num_headers = 0;

			while (i < (int)http2_frame_size - (int)padding) {
				const char *key = 0;
				const char *val = 0;
				uint8_t idx_mask = 0;
				uint8_t value_known = 0;
				uint8_t indexing = 0;
				uint64_t idx = 0;

				/* Classify next entry by checking the bit mask */
				if ((buf[i] & 0x80u) == 0x80u) {
					/* Indexed Header Field Representation:
					 * https://tools.ietf.org/html/rfc7541#section-6.1 */
					idx_mask = 0x7fu;
					value_known = 1;

				} else if ((buf[i] & 0xC0u) == 0x40u) {
					/* Literal Header Field with Incremental Indexing:
					 * https://tools.ietf.org/html/rfc7541#section-6.2.1 */
					idx_mask = 0x3fu;
					indexing = 1;

				} else if ((buf[i] & 0xF0u) == 0x00u) {
					/* Literal Header Field without Indexing:
					 * https://tools.ietf.org/html/rfc7541#section-6.2.2 */
					idx_mask = 0x0fu;

				} else if ((buf[i] & 0xF0u) == 0x10u) {
					/* Literal Header Field Never Indexed:
					 * https://tools.ietf.org/html/rfc7541#section-6.2.3 */
					idx_mask = 0x0fu;

				} else if ((buf[i] & 0xE0u) == 0x20u) {
					uint64_t tableSize;
					/* Dynamic Table Size Update:
					 * https://tools.ietf.org/html/rfc7541#section-6.3 */
					idx_mask = 0x1fu;
					tableSize = hpack_getnum(buf, &i, idx_mask, conn->phys_ctx);

					/* TODO: check if tablesize > allowed table size */

					/* Purge additional table entries */
					purge_dynamic_header_table(conn, (uint32_t)tableSize);

					/* Process next frame */
					continue;

				} else {
					DEBUG_TRACE("HTTP2 unknown start pattern %02x", buf[i]);
					goto clean_http2;
				}

				/* Get the header name table index */
				idx = hpack_getnum(buf, &i, idx_mask, conn->phys_ctx);

				/* Get Header name "key" */
				if (idx == 0) {
					/* Index 0: Header name encoded in following bytes */
					key =
					    hpack_decode(buf, &i, (int)bytes_read, conn->phys_ctx);
					CHECK_LEAK_HDR_ALLOC(key);
					if (!key) {
						DEBUG_TRACE("%s", "HTTP2 key decoding error");
						goto clean_http2;
					}
				} else if (/*(idx >= 15) &&*/ (idx <= 61)) {
					/* Take key name from predefined header table */
					key = mg_strdup_ctx(hpack_predefined[idx].name,
					                    conn->phys_ctx); /* leak? */
					CHECK_LEAK_HDR_ALLOC(key);
				} else if ((idx >= 62)
				           && ((idx - 61) <= conn->http2.dyn_table_size)) {
					/* Take from dynamic header table */
					uint32_t local_table_idx = (uint32_t)idx - 62;
					key = mg_strdup_ctx(
					    conn->http2.dyn_table[local_table_idx].name,
					    conn->phys_ctx);
					CHECK_LEAK_HDR_ALLOC(key);
				} else {
					/* protocol violation */
					DEBUG_TRACE("HTTP2 invalid index %lu", (unsigned long)idx);
					goto clean_http2;
				}
				/* key is allocated now and must be freed later */

				/* Get header value */
				if (value_known) {
					/* Server must already know the value */
					if (idx <= 61) {
						if (hpack_predefined[idx].value) {
							val = mg_strdup_ctx(hpack_predefined[idx].value,
							                    conn->phys_ctx); /* leak? */
							CHECK_LEAK_HDR_ALLOC(val);
						} else {
							/* protocol violation */
							DEBUG_TRACE("HTTP2 indexed header %lu has no value "
							            "(key: %s)",
							            (unsigned long)idx,
							            key);
							CHECK_LEAK_HDR_FREE(key);
							mg_free((void *)key);
							goto clean_http2;
						}
					} else if ((idx >= 62)
					           && ((idx - 61) <= conn->http2.dyn_table_size)) {
						uint32_t local_table_idx = (uint32_t)idx - 62;
						val = mg_strdup_ctx(
						    conn->http2.dyn_table[local_table_idx].value,
						    conn->phys_ctx);
						CHECK_LEAK_HDR_ALLOC(val);
					} else {
						/* protocol violation */
						DEBUG_TRACE(
						    "HTTP2 indexed header %lu out of range (key: %s)",
						    (unsigned long)idx,
						    key);
						CHECK_LEAK_HDR_FREE(key);
						mg_free((void *)key);
						goto clean_http2;
					}

				} else {
					/* Read value from HTTP2 stream */
					val = hpack_decode(buf,
					                   &i,
					                   (int)bytes_read,
					                   conn->phys_ctx); /* leak? */
					CHECK_LEAK_HDR_ALLOC(val);
					if (!val) {
						DEBUG_TRACE("%s", "HTTP2 value decoding error");
						mg_free((void *)key);
						goto clean_http2;
					}

					if (indexing) {
						/* Add to index */
						if (conn->http2.dyn_table_size
						    >= HTTP2_DYN_TABLE_SIZE) {
							/* Too many elements */
							DEBUG_TRACE("HTTP2 index table is full (key: %s, "
							            "value: %s)",
							            key,
							            val);

							CHECK_LEAK_HDR_FREE(key);
							CHECK_LEAK_HDR_FREE(val);

							mg_free((void *)key);
							mg_free((void *)val);
							goto clean_http2;
						}

						/* Add to table of dynamic headers */
						conn->http2.dyn_table[conn->http2.dyn_table_size].name =
						    mg_strdup_ctx(key, conn->phys_ctx); /* leak */
						conn->http2.dyn_table[conn->http2.dyn_table_size]
						    .value =
						    mg_strdup_ctx(val, conn->phys_ctx); /* leak */

						CHECK_LEAK_DYN_ALLOC(
						    conn->http2.dyn_table[conn->http2.dyn_table_size]
						        .name);
						CHECK_LEAK_DYN_ALLOC(
						    conn->http2.dyn_table[conn->http2.dyn_table_size]
						        .value);

						conn->http2.dyn_table_size++;

						DEBUG_TRACE("HTTP2 new dynamic header table entry %i "
						            "(key: %s, value: %s)",
						            (int)conn->http2.dyn_table_size,
						            key,
						            val);
					}
				}
				/* val and key are allocated now and must be freed later */
				/* Store these pointers in conn->request_info[].http_headers,
				 * free_buffered_header_list(conn) will clean up later. */

				/* Add header for this request */
				if ((key != NULL) && (val != NULL)
				    && (conn->request_info.num_headers < MG_MAX_HEADERS)) {
					conn->request_info
					    .http_headers[conn->request_info.num_headers]
					    .name = key;
					conn->request_info
					    .http_headers[conn->request_info.num_headers]
					    .value = val;
					conn->request_info.num_headers++;

					/* Some headers need to be stored in the request structure
					 */
					if (!strcmp(":method", key)) {
						conn->request_info.request_method = val;
					} else if (!strcmp(":path", key)) {
						conn->request_info.local_uri = val;
						conn->request_info.request_uri = val;
						conn->request_info.local_uri_raw = val;
					} else if (!strcmp(":status", key)) {
						conn->status_code = atoi(val);
					}

					DEBUG_TRACE("HTTP2 request header (key: %s, value: %s)",
					            key,
					            val);

				} else {
					/* - either key or value are NULL (out of memory)
					 * - or the max. number of headers is reached
					 * in both cases free all memory
					 */
					DEBUG_TRACE("%s", "HTTP2 cannot add header");
					CHECK_LEAK_HDR_FREE(key);
					CHECK_LEAK_HDR_FREE(val);

					mg_free((void *)key);
					key = NULL;
					mg_free((void *)val);
					val = NULL;
				}
			}

			/* stream id */
			conn->http2.stream_id = http2_frame_stream_id;

			/* header parsed */
			DEBUG_TRACE("HTTP2 handle_request (stream %u)",
			            http2_frame_stream_id);
			handle_request_stat_log(conn);

			/* Send "final" frame */
			DEBUG_TRACE("HTTP2 handle_request done (stream %u)",
			            http2_frame_stream_id);
			http2_data_frame_head(conn, 0, 1);
			free_buffered_response_header_list(conn);
			free_buffered_request_header_list(conn);
		} break;

		case 2: /* PRIORITY */
		{
			uint32_t dependStream =
			    ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u)
			    + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]);
			uint8_t weight = buf[4];
			DEBUG_TRACE("HTTP2 priority %u dependent stream %u",
			            weight,
			            dependStream);
		} break;

		case 3: /* RST_STREAM */
		{
			uint32_t errorId =
			    ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u)
			    + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]);
			DEBUG_TRACE("HTTP2 reset with error %u", errorId);
		} break;

		case 4: /* SETTINGS */
			if (http2_frame_stream_id != 0) {
				/* Send protocol error */
				http2_reset_stream(conn,
				                   http2_frame_stream_id,
				                   HTTP2_ERR_PROTOCOL_ERROR);
				DEBUG_TRACE("%s", "HTTP2 received invalid settings frame");
			} else if (http2_frame_flags) {
				/* ACK frame. Do not reply. */
				my_settings_accepted++;
				DEBUG_TRACE("%s", "CivetWeb settings confirmed by peer");
			} else {
				int i;
				for (i = 0; i < (int)http2_frame_size; i += 6) {
					uint16_t id =
					    ((uint16_t)buf[i] * 0x100u) + ((uint16_t)buf[i + 1]);
					uint32_t val = ((uint32_t)buf[i + 2] * 0x1000000u)
					               + ((uint32_t)buf[i + 3] * 0x10000u)
					               + ((uint32_t)buf[i + 4] * 0x100u)
					               + ((uint32_t)buf[i + 5]);
					switch (id) {
					case 1:
						client_settings.settings_header_table_size = val;
						DEBUG_TRACE("Received settings header_table_size: %u",
						            val);
						break;
					case 2:
						client_settings.settings_enable_push = (val != 0);
						DEBUG_TRACE("Received settings enable_push: %u", val);
						break;
					case 3:
						client_settings.settings_max_concurrent_streams = val;
						DEBUG_TRACE(
						    "Received settings max_concurrent_streams: %u",
						    val);
						break;
					case 4:
						client_settings.settings_initial_window_size = val;
						DEBUG_TRACE("Received settings initial_window_size: %u",
						            val);
						break;
					case 5:
						client_settings.settings_max_frame_size = val;
						DEBUG_TRACE("Received settings max_frame_size: %u",
						            val);
						break;
					case 6:
						client_settings.settings_max_header_list_size = val;
						DEBUG_TRACE(
						    "Received settings max_header_list_size: %u", val);
						break;
					default:
						/* Unknown setting. Ignore it. */
						DEBUG_TRACE("Received unknown settings id=%u: %u",
						            id,
						            val);
						break;
					}
				}

				/* Every settings frame must be acknowledged */
				http2_settings_acknowledge(conn);
			}
			break;

		case 5: /* PUSH_PROMISE */
			DEBUG_TRACE("%s", "Push promise not supported");
			break;

		case 6: /* PING */
			if (http2_frame_flags == 0) {
				/* Set "reply" flag, and send same data back */
				DEBUG_TRACE("%s", "Replying to ping");
				http2_frame_head[4] = 1;
				mg_xwrite(conn, http2_frame_head, sizeof(http2_frame_head));
				mg_xwrite(conn, buf, http2_frame_size);
			}
			break;

		case 7: /* GOAWAY */
		{
			uint32_t lastStream =
			    ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u)
			    + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]);
			uint32_t errorId =
			    ((uint32_t)buf[4] * 0x1000000u) + ((uint32_t)buf[5] * 0x10000u)
			    + ((uint32_t)buf[6] * 0x100u) + ((uint32_t)buf[7]);
			; /* followed by debug data */
			uint32_t debugDataLen = http2_frame_size - 8;
			char *debugData = (char *)buf + 8;

			DEBUG_TRACE("HTTP2 goaway stream %u, error %u (%.*s)",
			            lastStream,
			            errorId,
			            debugDataLen,
			            debugData);

		} break;

		case 8: /* WINDOW_UPDATE */
		{
			uint32_t val = ((uint32_t)buf[0] * 0x1000000u)
			               + ((uint32_t)buf[1] * 0x10000u)
			               + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]);
			http_window_length = (val & 0x7FFFFFFFu);

			DEBUG_TRACE("HTTP2 window update stream %u, length %u",
			            http2_frame_stream_id,
			            http_window_length);
		} break;

		case 9: /* CONTINUATION */
			DEBUG_TRACE("%s", "HTTP2 Continue");
			break;

		default:
			/* TODO: Error Message */
			DEBUG_TRACE("%s", "Unknown frame type");
			goto clean_http2;
		}

		/* not used in the moment */
		(void)frame_is_end_stream;
		(void)frame_is_end_headers;
		(void)client_settings;
	}

clean_http2:
	DEBUG_TRACE("%s", "HTTP2 free buffer, connection handler finished");
	mg_free(buf);
}


#if 0
static void
HPACK_TEST()
{
	uint64_t test;

	for (test = 0;; test++) {
		char in[32] = {0};
		uint8_t out[32] = {0};
		char *check;
		int i;
		int l;

		memcpy(in, &test, sizeof(test));
		l = hpack_encode(out, in, 0);
		i = 0;
		check = hpack_decode(out, &i, NULL);

		if (strcmp(in, check)) {
			printf("Error\n");
		}
		mg_free(check);
	}
}

static void
HPACK_TABLE_TEST()
{
	int i;

	uint32_t hpack_huff_end_code_expected[32] = { 0 };
	uint8_t hpack_huff_start_index_expected[32] = { 0 };
	int reverse_map[256] = { 0 };

	for (i = 0; i < 256; i++) {
		reverse_map[i] = -1;
	}

	for (i = 0; i < 256; i++) {
		uint8_t bits = hpack_huff_dec[i].bitcount;
		uint8_t dec = hpack_huff_dec[i].decoded;
		if (bits > hpack_huff_dec[i + 1].bitcount) {
			ck_abort_msg("hpack_huff_dec disorder at index %i", i);
		}
		if (hpack_huff_dec[i].encoded & (0xFFFFFFFFul << bits)) {
			ck_abort_msg("hpack_huff_dec bits inconsistent at index %i", i);
		}
		if ((bits < 5) || (bits > 30)) {
			ck_abort_msg("hpack_huff_dec bits out of range at index %i", i);
		}
		if (reverse_map[dec] != -1) {
			ck_abort_msg("hpack_huff_dec duplicate: %i", hpack_huff_dec[i].decoded);
		}
		reverse_map[dec] = i;

		hpack_huff_end_code_expected[bits - 5] = hpack_huff_dec[i].encoded;
	}

	for (i = 255; i >= 0; i--) {
		uint8_t bits = hpack_huff_dec[i].bitcount;
		hpack_huff_start_index_expected[bits - 5] = i;
	}

	for (i = 0; i < 256; i++) {
		if (reverse_map[i] == -1) {
			ck_abort_msg("reverse map at %i missing", i);
		}
	}

	i = sizeof(hpack_huff_start_index) / sizeof(hpack_huff_start_index[0]);
	if (i != 27) {
		ck_abort_msg("hpack_huff_start_index size error: ", i);
	}

	i = sizeof(hpack_huff_end_code) / sizeof(hpack_huff_end_code[0]);
	if (i != 27) {
		ck_abort_msg("hpack_huff_end_code size error: ", i);
	}

	for (i = 0; i < 27; i++) {
		if (hpack_huff_start_index_expected[i] != hpack_huff_start_index[i]) {
			ck_abort_msg("hpack_huff_start_index error at %i", i);
		}
		if (hpack_huff_end_code_expected[i] != hpack_huff_end_code[i]) {
			ck_abort_msg("hpack_huff_end_code error at %i", i);
		}
	}

}
#endif


static void
process_new_http2_connection(struct mg_connection *conn)
{
	if (!is_valid_http2_primer(conn)) {
		/* Primer does not match expectation from RFC.
		 * See https://tools.ietf.org/html/rfc7540#section-3.5 */
		DEBUG_TRACE("%s", "No valid HTTP2 primer");
		mg_send_http_error(conn, 400, "%s", "Invalid HTTP/2 primer");

	} else {
		/* Valid HTTP/2 primer received */
		DEBUG_TRACE("%s", "Start handling HTTP2");
		handle_http2(conn);

		/* Free memory allocated for headers, if not done yet */
		DEBUG_TRACE("%s", "Free remaining HTTP2 header memory");
		free_buffered_response_header_list(conn);
		free_buffered_request_header_list(conn);
		purge_dynamic_header_table(conn, 0);
	}
}
