├── .gitmodules ├── Makefile ├── Makefile.inc ├── README.md ├── hpack.3 ├── hpack.c ├── hpack.h ├── hpack.md ├── lib ├── Makefile └── shlib_version └── regress ├── Makefile ├── extern.h ├── hpack-test-samples ├── headers │ ├── headers_00.txt │ └── headers_01.txt ├── hex │ ├── go-hpack_00.hpacktest │ ├── go-hpack_01.hpacktest │ ├── go-hpack_02.hpacktest │ ├── go-hpack_03.hpacktest │ ├── go-hpack_07.hpacktest │ ├── go-hpack_10.hpacktest │ ├── go-hpack_11.hpacktest │ ├── go-hpack_12.hpacktest │ ├── go-hpack_16.hpacktest │ ├── go-hpack_18.hpacktest │ └── go-hpack_19.hpacktest └── raw │ ├── go-hpack_00.hpackraw │ ├── go-hpack_01.hpackraw │ ├── go-hpack_02.hpackraw │ ├── go-hpack_05.hpackraw │ ├── go-hpack_16.hpackraw │ └── go-hpack_22.hpackraw ├── jsmn.c ├── jsmn.h ├── json.c └── main.c /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hpacktest/hpack-test-case"] 2 | path = regress/hpack-test-case 3 | url = https://github.com/http2jp/hpack-test-case.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SUBDIR= lib regress 2 | 3 | .include 4 | -------------------------------------------------------------------------------- /Makefile.inc: -------------------------------------------------------------------------------- 1 | SRCS+= hpack.c 2 | 3 | CFLAGS+= -Wall -I. -I${.CURDIR}/.. 4 | CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes 5 | CFLAGS+= -Wmissing-declarations 6 | CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual 7 | CFLAGS+= -Wsign-compare 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | hpack 2 | ===== 3 | 4 | The [hpack(3)](hpack.md) header compression API for HTTP/2, written in C. 5 | 6 | 1. Why another HPACK implementation? 7 | 8 | I either didn't like the license or the style of the existing C code. 9 | And I wanted to have a small [HPACK][4] implementation that fits into a 10 | single `.c` and `.h` file. As a design decision, I decided to be 11 | extra careful with input and output buffers: avoiding to use 12 | dangerous pointer arithmetics, using allocated (heap) data instead 13 | of stack buffers, depending on extra features of OpenBSD's "otto" malloc(3). 14 | 15 | 2. What is the purpose of this HPACK code? 16 | 17 | I want to include it, one day, into [relayd or httpd][1]. 18 | 19 | 3. Why is this an OpenBSD library? 20 | 21 | This is just for testing and development. The final code will 22 | eventually be included into the software under [OpenBSD][2]. 23 | 24 | TODO 25 | ---- 26 | 27 | - optimizations (heuristics to decide on huffman encoding, header indexing, ...) 28 | - more tests and fuzzing (I already did some hours of [afl][3] fuzzing). 29 | 30 | TESTS 31 | ----- 32 | 33 | Make sure to checkout all git submodules. 34 | 35 | ``` 36 | $ git submodule update --init 37 | ``` 38 | 39 | The tests use OpenBSD's regress framework. 40 | 41 | ``` 42 | $ make regress 43 | ===> regress 44 | cc -O2 -pipe -DJSMN_PARENT_LINKS -Wall -I. -Iregress/.. -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare -MD -MP -c regress/main.c 45 | cc -O2 -pipe -DJSMN_PARENT_LINKS -Wall -I. -Iregress/.. -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare -MD -MP -c regress/jsmn.c 46 | cc -O2 -pipe -DJSMN_PARENT_LINKS -Wall -I. -Iregress/.. -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare -MD -MP -c regress/json.c 47 | cc -O2 -pipe -DJSMN_PARENT_LINKS -Wall -I. -Iregress/.. -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare -MD -MP -c regress/../hpack.c 48 | cc -o hpacktest main.o jsmn.o json.o hpack.o 49 | ./hpacktest -v regress/hpack-test-samples regress/hpack-test-case 50 | SUCCESS: regress/hpack-test-samples/raw/go-hpack_00.hpackraw: 1 tests 51 | SUCCESS: regress/hpack-test-samples/raw/go-hpack_01.hpackraw: 1 tests 52 | SUCCESS: regress/hpack-test-samples/raw/go-hpack_02.hpackraw: 1 tests 53 | SUCCESS: regress/hpack-test-samples/raw/go-hpack_05.hpackraw: 1 tests 54 | SUCCESS: regress/hpack-test-samples/raw/go-hpack_16.hpackraw: 1 tests 55 | SUCCESS: regress/hpack-test-samples/raw/go-hpack_22.hpackraw: 1 tests 56 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_00.hpacktest: 3 tests 57 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_01.hpacktest: 2 tests 58 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_02.hpacktest: 10 tests 59 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_03.hpacktest: 10 tests 60 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_07.hpacktest: 10 tests 61 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_10.hpacktest: 10 tests 62 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_11.hpacktest: 10 tests 63 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_12.hpacktest: 10 tests 64 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_16.hpacktest: 10 tests 65 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_18.hpacktest: 10 tests 66 | SUCCESS: regress/hpack-test-samples/hex/go-hpack_19.hpacktest: 10 tests 67 | SUCCESS: regress/hpack-test-samples/headers/headers_00.txt: 1 tests 68 | SUCCESS: regress/hpack-test-samples/headers/headers_01.txt: 1 tests 69 | SUCCESS: regress/hpack-test-case/go-hpack/story_00.json: 3 tests 70 | SUCCESS: regress/hpack-test-case/go-hpack/story_01.json: 2 tests 71 | SUCCESS: regress/hpack-test-case/go-hpack/story_02.json: 10 tests 72 | SUCCESS: regress/hpack-test-case/go-hpack/story_03.json: 10 tests 73 | SUCCESS: regress/hpack-test-case/go-hpack/story_04.json: 10 tests 74 | SUCCESS: regress/hpack-test-case/go-hpack/story_05.json: 10 tests 75 | SUCCESS: regress/hpack-test-case/go-hpack/story_06.json: 10 tests 76 | SUCCESS: regress/hpack-test-case/go-hpack/story_07.json: 10 tests 77 | SUCCESS: regress/hpack-test-case/go-hpack/story_08.json: 10 tests 78 | SUCCESS: regress/hpack-test-case/go-hpack/story_09.json: 10 tests 79 | SUCCESS: regress/hpack-test-case/go-hpack/story_10.json: 10 tests 80 | SUCCESS: regress/hpack-test-case/go-hpack/story_11.json: 10 tests 81 | SUCCESS: regress/hpack-test-case/go-hpack/story_12.json: 10 tests 82 | SUCCESS: regress/hpack-test-case/go-hpack/story_13.json: 10 tests 83 | SUCCESS: regress/hpack-test-case/go-hpack/story_14.json: 10 tests 84 | SUCCESS: regress/hpack-test-case/go-hpack/story_15.json: 10 tests 85 | SUCCESS: regress/hpack-test-case/go-hpack/story_16.json: 10 tests 86 | SUCCESS: regress/hpack-test-case/go-hpack/story_17.json: 10 tests 87 | SUCCESS: regress/hpack-test-case/go-hpack/story_18.json: 10 tests 88 | SUCCESS: regress/hpack-test-case/go-hpack/story_19.json: 10 tests 89 | SUCCESS: regress/hpack-test-case/go-hpack/story_20.json: 164 tests 90 | SUCCESS: regress/hpack-test-case/go-hpack/story_21.json: 366 tests 91 | SUCCESS: regress/hpack-test-case/go-hpack/story_22.json: 455 tests 92 | SUCCESS: regress/hpack-test-case/go-hpack/story_23.json: 363 tests 93 | SUCCESS: regress/hpack-test-case/go-hpack/story_24.json: 33 tests 94 | SUCCESS: regress/hpack-test-case/go-hpack/story_25.json: 256 tests 95 | SUCCESS: regress/hpack-test-case/go-hpack/story_26.json: 117 tests 96 | SUCCESS: regress/hpack-test-case/go-hpack/story_27.json: 219 tests 97 | SUCCESS: regress/hpack-test-case/go-hpack/story_28.json: 128 tests 98 | SUCCESS: regress/hpack-test-case/go-hpack/story_29.json: 335 tests 99 | SUCCESS: regress/hpack-test-case/go-hpack/story_30.json: 646 tests 100 | SUCCESS: regress/hpack-test-case/go-hpack/story_31.json: 117 tests 101 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_00.json: 3 tests 102 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_01.json: 2 tests 103 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_02.json: 10 tests 104 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_03.json: 10 tests 105 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_04.json: 10 tests 106 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_05.json: 10 tests 107 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_06.json: 10 tests 108 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_07.json: 10 tests 109 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_08.json: 10 tests 110 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_09.json: 10 tests 111 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_10.json: 10 tests 112 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_11.json: 10 tests 113 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_12.json: 10 tests 114 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_13.json: 10 tests 115 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_14.json: 10 tests 116 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_15.json: 10 tests 117 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_16.json: 10 tests 118 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_17.json: 10 tests 119 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_18.json: 10 tests 120 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_19.json: 10 tests 121 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_20.json: 164 tests 122 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_21.json: 366 tests 123 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_22.json: 455 tests 124 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_23.json: 363 tests 125 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_24.json: 33 tests 126 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_25.json: 256 tests 127 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_26.json: 117 tests 128 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_27.json: 219 tests 129 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_28.json: 128 tests 130 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_29.json: 335 tests 131 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_30.json: 646 tests 132 | SUCCESS: regress/hpack-test-case/haskell-http2-linear-huffman/story_31.json: 117 tests 133 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_00.json: 3 tests 134 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_01.json: 2 tests 135 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_02.json: 10 tests 136 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_03.json: 10 tests 137 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_04.json: 10 tests 138 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_05.json: 10 tests 139 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_06.json: 10 tests 140 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_07.json: 10 tests 141 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_08.json: 10 tests 142 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_09.json: 10 tests 143 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_10.json: 10 tests 144 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_11.json: 10 tests 145 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_12.json: 10 tests 146 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_13.json: 10 tests 147 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_14.json: 10 tests 148 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_15.json: 10 tests 149 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_16.json: 10 tests 150 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_17.json: 10 tests 151 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_18.json: 10 tests 152 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_19.json: 10 tests 153 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_20.json: 164 tests 154 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_21.json: 366 tests 155 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_22.json: 455 tests 156 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_23.json: 363 tests 157 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_24.json: 33 tests 158 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_25.json: 256 tests 159 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_26.json: 117 tests 160 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_27.json: 219 tests 161 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_28.json: 128 tests 162 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_29.json: 335 tests 163 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_30.json: 646 tests 164 | SUCCESS: regress/hpack-test-case/haskell-http2-linear/story_31.json: 117 tests 165 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_00.json: 3 tests 166 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_01.json: 2 tests 167 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_02.json: 10 tests 168 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_03.json: 10 tests 169 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_04.json: 10 tests 170 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_05.json: 10 tests 171 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_06.json: 10 tests 172 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_07.json: 10 tests 173 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_08.json: 10 tests 174 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_09.json: 10 tests 175 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_10.json: 10 tests 176 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_11.json: 10 tests 177 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_12.json: 10 tests 178 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_13.json: 10 tests 179 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_14.json: 10 tests 180 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_15.json: 10 tests 181 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_16.json: 10 tests 182 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_17.json: 10 tests 183 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_18.json: 10 tests 184 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_19.json: 10 tests 185 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_20.json: 164 tests 186 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_21.json: 366 tests 187 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_22.json: 455 tests 188 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_23.json: 363 tests 189 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_24.json: 33 tests 190 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_25.json: 256 tests 191 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_26.json: 117 tests 192 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_27.json: 219 tests 193 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_28.json: 128 tests 194 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_29.json: 335 tests 195 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_30.json: 646 tests 196 | SUCCESS: regress/hpack-test-case/haskell-http2-naive-huffman/story_31.json: 117 tests 197 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_00.json: 3 tests 198 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_01.json: 2 tests 199 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_02.json: 10 tests 200 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_03.json: 10 tests 201 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_04.json: 10 tests 202 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_05.json: 10 tests 203 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_06.json: 10 tests 204 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_07.json: 10 tests 205 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_08.json: 10 tests 206 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_09.json: 10 tests 207 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_10.json: 10 tests 208 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_11.json: 10 tests 209 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_12.json: 10 tests 210 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_13.json: 10 tests 211 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_14.json: 10 tests 212 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_15.json: 10 tests 213 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_16.json: 10 tests 214 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_17.json: 10 tests 215 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_18.json: 10 tests 216 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_19.json: 10 tests 217 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_20.json: 164 tests 218 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_21.json: 366 tests 219 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_22.json: 455 tests 220 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_23.json: 363 tests 221 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_24.json: 33 tests 222 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_25.json: 256 tests 223 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_26.json: 117 tests 224 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_27.json: 219 tests 225 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_28.json: 128 tests 226 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_29.json: 335 tests 227 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_30.json: 646 tests 228 | SUCCESS: regress/hpack-test-case/haskell-http2-naive/story_31.json: 117 tests 229 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_00.json: 3 tests 230 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_01.json: 2 tests 231 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_02.json: 10 tests 232 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_03.json: 10 tests 233 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_04.json: 10 tests 234 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_05.json: 10 tests 235 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_06.json: 10 tests 236 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_07.json: 10 tests 237 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_08.json: 10 tests 238 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_09.json: 10 tests 239 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_10.json: 10 tests 240 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_11.json: 10 tests 241 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_12.json: 10 tests 242 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_13.json: 10 tests 243 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_14.json: 10 tests 244 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_15.json: 10 tests 245 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_16.json: 10 tests 246 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_17.json: 10 tests 247 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_18.json: 10 tests 248 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_19.json: 10 tests 249 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_20.json: 164 tests 250 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_21.json: 366 tests 251 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_22.json: 455 tests 252 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_23.json: 363 tests 253 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_24.json: 33 tests 254 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_25.json: 256 tests 255 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_26.json: 117 tests 256 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_27.json: 219 tests 257 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_28.json: 128 tests 258 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_29.json: 335 tests 259 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_30.json: 646 tests 260 | SUCCESS: regress/hpack-test-case/haskell-http2-static-huffman/story_31.json: 117 tests 261 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_00.json: 3 tests 262 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_01.json: 2 tests 263 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_02.json: 10 tests 264 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_03.json: 10 tests 265 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_04.json: 10 tests 266 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_05.json: 10 tests 267 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_06.json: 10 tests 268 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_07.json: 10 tests 269 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_08.json: 10 tests 270 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_09.json: 10 tests 271 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_10.json: 10 tests 272 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_11.json: 10 tests 273 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_12.json: 10 tests 274 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_13.json: 10 tests 275 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_14.json: 10 tests 276 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_15.json: 10 tests 277 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_16.json: 10 tests 278 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_17.json: 10 tests 279 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_18.json: 10 tests 280 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_19.json: 10 tests 281 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_20.json: 164 tests 282 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_21.json: 366 tests 283 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_22.json: 455 tests 284 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_23.json: 363 tests 285 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_24.json: 33 tests 286 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_25.json: 256 tests 287 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_26.json: 117 tests 288 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_27.json: 219 tests 289 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_28.json: 128 tests 290 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_29.json: 335 tests 291 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_30.json: 646 tests 292 | SUCCESS: regress/hpack-test-case/haskell-http2-static/story_31.json: 117 tests 293 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_00.json: 3 tests 294 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_01.json: 2 tests 295 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_02.json: 10 tests 296 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_03.json: 10 tests 297 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_04.json: 10 tests 298 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_05.json: 10 tests 299 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_06.json: 10 tests 300 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_07.json: 10 tests 301 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_08.json: 10 tests 302 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_09.json: 10 tests 303 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_10.json: 10 tests 304 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_11.json: 10 tests 305 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_12.json: 10 tests 306 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_13.json: 10 tests 307 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_14.json: 10 tests 308 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_15.json: 10 tests 309 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_16.json: 10 tests 310 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_17.json: 10 tests 311 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_18.json: 10 tests 312 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_19.json: 10 tests 313 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_20.json: 164 tests 314 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_21.json: 366 tests 315 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_22.json: 455 tests 316 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_23.json: 363 tests 317 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_24.json: 33 tests 318 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_25.json: 256 tests 319 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_26.json: 117 tests 320 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_27.json: 219 tests 321 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_28.json: 128 tests 322 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_29.json: 335 tests 323 | SUCCESS: regress/hpack-test-case/nghttp2-16384-4096/story_30.json: 646 tests 324 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_00.json: 3 tests 325 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_01.json: 2 tests 326 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_02.json: 10 tests 327 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_03.json: 10 tests 328 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_04.json: 10 tests 329 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_05.json: 10 tests 330 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_06.json: 10 tests 331 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_07.json: 10 tests 332 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_08.json: 10 tests 333 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_09.json: 10 tests 334 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_10.json: 10 tests 335 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_11.json: 10 tests 336 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_12.json: 10 tests 337 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_13.json: 10 tests 338 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_14.json: 10 tests 339 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_15.json: 10 tests 340 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_16.json: 10 tests 341 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_17.json: 10 tests 342 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_18.json: 10 tests 343 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_19.json: 10 tests 344 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_20.json: 164 tests 345 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_21.json: 366 tests 346 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_22.json: 455 tests 347 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_23.json: 363 tests 348 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_24.json: 33 tests 349 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_25.json: 256 tests 350 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_26.json: 117 tests 351 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_27.json: 219 tests 352 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_28.json: 128 tests 353 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_29.json: 335 tests 354 | SUCCESS: regress/hpack-test-case/nghttp2-change-table-size/story_30.json: 646 tests 355 | SUCCESS: regress/hpack-test-case/nghttp2/story_00.json: 3 tests 356 | SUCCESS: regress/hpack-test-case/nghttp2/story_01.json: 2 tests 357 | SUCCESS: regress/hpack-test-case/nghttp2/story_02.json: 10 tests 358 | SUCCESS: regress/hpack-test-case/nghttp2/story_03.json: 10 tests 359 | SUCCESS: regress/hpack-test-case/nghttp2/story_04.json: 10 tests 360 | SUCCESS: regress/hpack-test-case/nghttp2/story_05.json: 10 tests 361 | SUCCESS: regress/hpack-test-case/nghttp2/story_06.json: 10 tests 362 | SUCCESS: regress/hpack-test-case/nghttp2/story_07.json: 10 tests 363 | SUCCESS: regress/hpack-test-case/nghttp2/story_08.json: 10 tests 364 | SUCCESS: regress/hpack-test-case/nghttp2/story_09.json: 10 tests 365 | SUCCESS: regress/hpack-test-case/nghttp2/story_10.json: 10 tests 366 | SUCCESS: regress/hpack-test-case/nghttp2/story_11.json: 10 tests 367 | SUCCESS: regress/hpack-test-case/nghttp2/story_12.json: 10 tests 368 | SUCCESS: regress/hpack-test-case/nghttp2/story_13.json: 10 tests 369 | SUCCESS: regress/hpack-test-case/nghttp2/story_14.json: 10 tests 370 | SUCCESS: regress/hpack-test-case/nghttp2/story_15.json: 10 tests 371 | SUCCESS: regress/hpack-test-case/nghttp2/story_16.json: 10 tests 372 | SUCCESS: regress/hpack-test-case/nghttp2/story_17.json: 10 tests 373 | SUCCESS: regress/hpack-test-case/nghttp2/story_18.json: 10 tests 374 | SUCCESS: regress/hpack-test-case/nghttp2/story_19.json: 10 tests 375 | SUCCESS: regress/hpack-test-case/nghttp2/story_20.json: 164 tests 376 | SUCCESS: regress/hpack-test-case/nghttp2/story_21.json: 366 tests 377 | SUCCESS: regress/hpack-test-case/nghttp2/story_22.json: 455 tests 378 | SUCCESS: regress/hpack-test-case/nghttp2/story_23.json: 363 tests 379 | SUCCESS: regress/hpack-test-case/nghttp2/story_24.json: 33 tests 380 | SUCCESS: regress/hpack-test-case/nghttp2/story_25.json: 256 tests 381 | SUCCESS: regress/hpack-test-case/nghttp2/story_26.json: 117 tests 382 | SUCCESS: regress/hpack-test-case/nghttp2/story_27.json: 219 tests 383 | SUCCESS: regress/hpack-test-case/nghttp2/story_28.json: 128 tests 384 | SUCCESS: regress/hpack-test-case/nghttp2/story_29.json: 335 tests 385 | SUCCESS: regress/hpack-test-case/nghttp2/story_30.json: 646 tests 386 | SUCCESS: regress/hpack-test-case/nghttp2/story_31.json: 117 tests 387 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_00.json: 3 tests 388 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_01.json: 2 tests 389 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_02.json: 10 tests 390 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_03.json: 10 tests 391 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_04.json: 10 tests 392 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_05.json: 10 tests 393 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_06.json: 10 tests 394 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_07.json: 10 tests 395 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_08.json: 10 tests 396 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_09.json: 10 tests 397 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_10.json: 10 tests 398 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_11.json: 10 tests 399 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_12.json: 10 tests 400 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_13.json: 10 tests 401 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_14.json: 10 tests 402 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_15.json: 10 tests 403 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_16.json: 10 tests 404 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_17.json: 10 tests 405 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_18.json: 10 tests 406 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_19.json: 10 tests 407 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_20.json: 164 tests 408 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_21.json: 366 tests 409 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_22.json: 455 tests 410 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_23.json: 363 tests 411 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_24.json: 33 tests 412 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_25.json: 256 tests 413 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_26.json: 117 tests 414 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_27.json: 219 tests 415 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_28.json: 128 tests 416 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_29.json: 335 tests 417 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_30.json: 646 tests 418 | SUCCESS: regress/hpack-test-case/node-http2-hpack/story_31.json: 117 tests 419 | SUCCESS: regress/hpack-test-case/python-hpack/story_00.json: 3 tests 420 | SUCCESS: regress/hpack-test-case/python-hpack/story_01.json: 2 tests 421 | SUCCESS: regress/hpack-test-case/python-hpack/story_02.json: 10 tests 422 | SUCCESS: regress/hpack-test-case/python-hpack/story_03.json: 10 tests 423 | SUCCESS: regress/hpack-test-case/python-hpack/story_04.json: 10 tests 424 | SUCCESS: regress/hpack-test-case/python-hpack/story_05.json: 10 tests 425 | SUCCESS: regress/hpack-test-case/python-hpack/story_06.json: 10 tests 426 | SUCCESS: regress/hpack-test-case/python-hpack/story_07.json: 10 tests 427 | SUCCESS: regress/hpack-test-case/python-hpack/story_08.json: 10 tests 428 | SUCCESS: regress/hpack-test-case/python-hpack/story_09.json: 10 tests 429 | SUCCESS: regress/hpack-test-case/python-hpack/story_10.json: 10 tests 430 | SUCCESS: regress/hpack-test-case/python-hpack/story_11.json: 10 tests 431 | SUCCESS: regress/hpack-test-case/python-hpack/story_12.json: 10 tests 432 | SUCCESS: regress/hpack-test-case/python-hpack/story_13.json: 10 tests 433 | SUCCESS: regress/hpack-test-case/python-hpack/story_14.json: 10 tests 434 | SUCCESS: regress/hpack-test-case/python-hpack/story_15.json: 10 tests 435 | SUCCESS: regress/hpack-test-case/python-hpack/story_16.json: 10 tests 436 | SUCCESS: regress/hpack-test-case/python-hpack/story_17.json: 10 tests 437 | SUCCESS: regress/hpack-test-case/python-hpack/story_18.json: 10 tests 438 | SUCCESS: regress/hpack-test-case/python-hpack/story_19.json: 10 tests 439 | SUCCESS: regress/hpack-test-case/python-hpack/story_20.json: 164 tests 440 | SUCCESS: regress/hpack-test-case/python-hpack/story_21.json: 366 tests 441 | SUCCESS: regress/hpack-test-case/python-hpack/story_22.json: 455 tests 442 | SUCCESS: regress/hpack-test-case/python-hpack/story_23.json: 363 tests 443 | SUCCESS: regress/hpack-test-case/python-hpack/story_24.json: 33 tests 444 | SUCCESS: regress/hpack-test-case/python-hpack/story_25.json: 256 tests 445 | SUCCESS: regress/hpack-test-case/python-hpack/story_26.json: 117 tests 446 | SUCCESS: regress/hpack-test-case/python-hpack/story_27.json: 219 tests 447 | SUCCESS: regress/hpack-test-case/python-hpack/story_28.json: 128 tests 448 | SUCCESS: regress/hpack-test-case/python-hpack/story_29.json: 335 tests 449 | SUCCESS: regress/hpack-test-case/python-hpack/story_30.json: 646 tests 450 | SUCCESS: regress/hpack-test-case/python-hpack/story_31.json: 117 tests 451 | 452 | ``` 453 | 454 | [1]: https://bsd.plumbing/ 455 | [2]: https://www.openbsd.org/ 456 | [3]: http://lcamtuf.coredump.cx/afl/ 457 | [4]: https://tools.ietf.org/html/rfc7541 458 | -------------------------------------------------------------------------------- /hpack.3: -------------------------------------------------------------------------------- 1 | .\" $OpenBSD$ 2 | .\" 3 | .\" Copyright (c) 2019 Reyk Floeter 4 | .\" 5 | .\" Permission to use, copy, modify, and distribute this software for any 6 | .\" purpose with or without fee is hereby granted, provided that the above 7 | .\" copyright notice and this permission notice appear in all copies. 8 | .\" 9 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | .\" 17 | .Dd $Mdocdate: May 23 2019 $ 18 | .Dt HPACK 3 19 | .Os 20 | .Sh NAME 21 | .Nm hpack_init , 22 | .Nm hpack_table_new , 23 | .Nm hpack_table_free , 24 | .Nm hpack_table_size , 25 | .Nm hpack_decode , 26 | .Nm hpack_encode , 27 | .Nm hpack_header_new , 28 | .Nm hpack_header_add , 29 | .Nm hpack_header_free , 30 | .Nm hpack_headerblock_new , 31 | .Nm hpack_headerblock_free , 32 | .Nm hpack_huffman_decode , 33 | .Nm hpack_huffman_decode_str , 34 | .Nm hpack_huffman_encode 35 | .Nd HPACK header compression for HTTP/2 36 | .Sh SYNOPSIS 37 | .In sys/queue.h 38 | .In hpack.h 39 | .Ft int 40 | .Fn hpack_init void 41 | .Ft struct hpack_table * 42 | .Fn hpack_table_new "size_t max_table_size" 43 | .Ft void 44 | .Fn hpack_table_free "struct hpack_table *hpack" 45 | .Ft size_t 46 | .Fn hpack_table_size "struct hpack_table *hpack" 47 | .Ft struct hpack_headerblock * 48 | .Fn hpack_decode "unsigned char *data" "size_t len" "struct hpack_table *hpack" 49 | .Ft unsigned char * 50 | .Fn hpack_encode "struct hpack_headerblock *hdrs" "size_t *encoded_len" "struct hpack_table *hpack" 51 | .Ft struct hpack_header * 52 | .Fn hpack_header_new void 53 | .Ft struct hpack_header * 54 | .Fn hpack_header_add "struct hpack_headerblock *hdrs" "const char *key" "const char *value" "enum hpack_header_index index" 55 | .Ft void 56 | .Fn hpack_header_free "struct hpack_header *hdr" 57 | .Ft struct hpack_headerblock * 58 | .Fn hpack_headerblock_new void 59 | .Ft void 60 | .Fn hpack_headerblock_free "struct hpack_headerblock *hdrs" 61 | .Ft unsigned char * 62 | .Fn hpack_huffman_decode "unsigned char *data" "size_t len" "size_t *decoded_len" 63 | .Ft char * 64 | .Fn hpack_huffman_decode_str "unsigned char *data" "size_t len" 65 | .Ft unsigned char * 66 | .Fn hpack_huffman_encode "unsigned char *data" "size_t len" "size_t *encoded_len" 67 | .Sh DESCRIPTION 68 | The 69 | .Nm hpack 70 | family of functions provides an API to decode and encode HPACK header 71 | compression for HTTP/2. 72 | .Pp 73 | The 74 | .Vt hpack_header 75 | and 76 | .Vt hpack_headerblock 77 | structures are defined as 78 | .In sys/queue.h 79 | tail queue element and head of the following types: 80 | .Bd -literal 81 | struct hpack_header { 82 | char *hdr_name; 83 | char *hdr_value; 84 | enum hpack_header_index hdr_index; 85 | TAILQ_ENTRY(hpack_header) hdr_entry; 86 | }; 87 | TAILQ_HEAD(hpack_headerblock, hpack_header); 88 | .Ed 89 | .Pp 90 | The 91 | .Fa index 92 | argument can be specified as one of the following values: 93 | .Dv HPACK_INDEX , 94 | .Dv HPACK_NO_INDEX , 95 | or 96 | .Dv HPACK_NEVER_INDEX 97 | to add the header to the index of the dynamic HPACK table, 98 | to exclude the header from the index, 99 | or to exclude the header from the index and to mark it as sensitive to 100 | never include it in the index. 101 | .Sh RETURN VALUES 102 | .Fn hpack_init 103 | returns 0 on success or -1 on error. 104 | .Pp 105 | .Fn hpack_table_size 106 | returns the current size of the dynamic HPACK table or 0 if it is empty. 107 | .Pp 108 | .Fn hpack_table_new , 109 | .Fn hpack_decode , 110 | .Fn hpack_encode , 111 | .Fn hpack_header_new , 112 | .Fn hpack_header_add , 113 | .Fn hpack_headerblock_new , 114 | .Fn hpack_huffman_decode , 115 | .Fn hpack_huffman_decode_str , 116 | and 117 | .Fn hpack_huffman_encode 118 | return 119 | .Dv NULL 120 | on error or an out-of-memory condition. 121 | .Sh SEE ALSO 122 | .Xr queue 3 , 123 | .Xr relayd 8 124 | .Sh STANDARDS 125 | .Rs 126 | .%A R. Peon 127 | .%A H. Ruellan 128 | .%D May 2015 129 | .%R RFC 7541 130 | .%T HPACK: Header Compression for HTTP/2 131 | .Re 132 | .Sh HISTORY 133 | The 134 | .Nm hpack 135 | API first appeared on 136 | .Lk https://github.com/reyk/hpack . 137 | .Sh AUTHORS 138 | .An Reyk Floeter Aq Mt reyk@openbsd.org 139 | -------------------------------------------------------------------------------- /hpack.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD$ */ 2 | 3 | /* 4 | * Copyright (c) 2019 Reyk Floeter 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define HPACK_INTERNAL 29 | #include "hpack.h" 30 | 31 | static const struct hpack_index * 32 | hpack_table_getbyid(long, struct hpack_index *, 33 | struct hpack_table *); 34 | static const struct hpack_index * 35 | hpack_table_getbyheader(struct hpack_header *, 36 | struct hpack_index *, struct hpack_table *); 37 | static int hpack_table_add(struct hpack_header *, 38 | struct hpack_table *); 39 | static int hpack_table_evict(long, long, struct hpack_table *); 40 | static int hpack_table_setsize(long, struct hpack_table *); 41 | 42 | static long hpack_decode_int(struct hbuf *, unsigned char); 43 | static char *hpack_decode_str(struct hbuf *, unsigned char); 44 | static int hpack_decode_buf(struct hbuf *, struct hpack_table *); 45 | static long hpack_decode_index(struct hbuf *, unsigned char, 46 | const struct hpack_index **, struct hpack_table *); 47 | static int hpack_decode_literal(struct hbuf *, unsigned char, 48 | struct hpack_table *); 49 | static int hpack_encode_int(struct hbuf *, long, unsigned char, 50 | unsigned char); 51 | static int hpack_encode_str(struct hbuf *, char *); 52 | 53 | static int hpack_huffman_init(void); 54 | static struct hpack_huffman_node * 55 | hpack_huffman_new(void); 56 | static void hpack_huffman_free(struct hpack_huffman_node *); 57 | 58 | static struct hbuf * 59 | hbuf_new(unsigned char *, size_t); 60 | static void hbuf_free(struct hbuf *); 61 | static int hbuf_writechar(struct hbuf *, unsigned char); 62 | static int hbuf_writebuf(struct hbuf *, unsigned char *, size_t); 63 | static unsigned char * 64 | hbuf_release(struct hbuf *, size_t *); 65 | static int hbuf_readchar(struct hbuf *, unsigned char *); 66 | static int hbuf_readbuf(struct hbuf *, unsigned char **, size_t); 67 | static int hbuf_advance(struct hbuf *, size_t); 68 | static size_t hbuf_left(struct hbuf *); 69 | 70 | static struct hpack hpack_global; 71 | 72 | int 73 | hpack_init(void) 74 | { 75 | /* Initialize the huffman tree */ 76 | if (hpack_huffman_init() == -1) 77 | return (-1); 78 | 79 | return (0); 80 | } 81 | 82 | struct hpack_header * 83 | hpack_header_new(void) 84 | { 85 | return (calloc(1, sizeof(struct hpack_header))); 86 | } 87 | 88 | struct hpack_header * 89 | hpack_header_add(struct hpack_headerblock *hdrs, const char *name, 90 | const char *value, enum hpack_header_index index) 91 | { 92 | struct hpack_header *hdr; 93 | 94 | if ((hdr = hpack_header_new()) == NULL) 95 | return (NULL); 96 | hdr->hdr_name = strdup(name); 97 | hdr->hdr_value = strdup(value); 98 | hdr->hdr_index = index; 99 | if (hdr->hdr_name == NULL || hdr->hdr_value == NULL) { 100 | hpack_header_free(hdr); 101 | return (NULL); 102 | } 103 | TAILQ_INSERT_TAIL(hdrs, hdr, hdr_entry); 104 | 105 | return (hdr); 106 | } 107 | 108 | void 109 | hpack_header_free(struct hpack_header *hdr) 110 | { 111 | if (hdr == NULL) 112 | return; 113 | free(hdr->hdr_name); 114 | free(hdr->hdr_value); 115 | free(hdr); 116 | } 117 | 118 | struct hpack_headerblock * 119 | hpack_headerblock_new(void) 120 | { 121 | struct hpack_headerblock *hdrs; 122 | if ((hdrs = calloc(1, sizeof(*hdrs))) == NULL) 123 | return (NULL); 124 | TAILQ_INIT(hdrs); 125 | return (hdrs); 126 | } 127 | 128 | void 129 | hpack_headerblock_free(struct hpack_headerblock *hdrs) 130 | { 131 | struct hpack_header *hdr; 132 | 133 | if (hdrs == NULL) 134 | return; 135 | while ((hdr = TAILQ_FIRST(hdrs)) != NULL) { 136 | TAILQ_REMOVE(hdrs, hdr, hdr_entry); 137 | hpack_header_free(hdr); 138 | } 139 | } 140 | 141 | struct hpack_table * 142 | hpack_table_new(size_t max_table_size) 143 | { 144 | struct hpack_table *hpack; 145 | 146 | if ((hpack = calloc(1, sizeof(*hpack))) == NULL) 147 | return (NULL); 148 | if ((hpack->htb_dynamic = hpack_headerblock_new()) == NULL) { 149 | free(hpack); 150 | return (NULL); 151 | } 152 | hpack->htb_max_table_size = hpack->htb_table_size = 153 | max_table_size == 0 ? HPACK_MAX_TABLE_SIZE : max_table_size; 154 | 155 | return (hpack); 156 | } 157 | 158 | void 159 | hpack_table_free(struct hpack_table *hpack) 160 | { 161 | if (hpack == NULL) 162 | return; 163 | hpack_headerblock_free(hpack->htb_dynamic); 164 | free(hpack); 165 | } 166 | 167 | static const struct hpack_index * 168 | hpack_table_getbyid(long index, struct hpack_index *idbuf, 169 | struct hpack_table *hpack) 170 | { 171 | struct hpack_index *id = NULL; 172 | struct hpack_header *hdr; 173 | long dynidx = HPACK_STATIC_SIZE; 174 | 175 | if (index < 1 || index > dynidx + (long)hpack->htb_dynamic_size) 176 | return (NULL); 177 | 178 | if (index <= dynidx) { 179 | /* Static table */ 180 | id = &static_table[index - 1]; 181 | if (id->hpi_id != index) 182 | errx(1, "corrupted HPACK static table %ld != %ld", 183 | id->hpi_id, index); 184 | } else { 185 | /* Dynamic table */ 186 | TAILQ_FOREACH_REVERSE(hdr, hpack->htb_dynamic, 187 | hpack_headerblock, hdr_entry) { 188 | dynidx++; 189 | if (dynidx == index) { 190 | idbuf->hpi_id = index; 191 | idbuf->hpi_name = hdr->hdr_name; 192 | idbuf->hpi_value = hdr->hdr_value; 193 | id = idbuf; 194 | break; 195 | } 196 | } 197 | } 198 | 199 | return (id); 200 | } 201 | 202 | static const struct hpack_index * 203 | hpack_table_getbyheader(struct hpack_header *key, struct hpack_index *idbuf, 204 | struct hpack_table *hpack) 205 | { 206 | struct hpack_index *id = NULL, *firstid = NULL; 207 | struct hpack_header *hdr; 208 | size_t i, dynidx = HPACK_STATIC_SIZE; 209 | 210 | if (key->hdr_name == NULL) 211 | return (NULL); 212 | 213 | /* 214 | * Search the static and dynamic tables for a perfect match 215 | * or the first match that only matches the name. 216 | */ 217 | 218 | /* Static table */ 219 | for (i = 0; i < dynidx; i++) { 220 | id = &static_table[i]; 221 | if (strcasecmp(id->hpi_name, key->hdr_name) != 0) 222 | continue; 223 | if (firstid == NULL) { 224 | memcpy(idbuf, id, sizeof(*id)); 225 | idbuf->hpi_value = NULL; 226 | firstid = idbuf; 227 | } 228 | if ((id->hpi_value != NULL && key->hdr_value != NULL) && 229 | strcasecmp(id->hpi_value, key->hdr_value) == 0) 230 | return (id); 231 | } 232 | 233 | /* Dynamic table */ 234 | TAILQ_FOREACH_REVERSE(hdr, hpack->htb_dynamic, 235 | hpack_headerblock, hdr_entry) { 236 | dynidx++; 237 | if (strcasecmp(hdr->hdr_name, key->hdr_name) != 0) 238 | continue; 239 | if (firstid == NULL) { 240 | idbuf->hpi_id = dynidx; 241 | idbuf->hpi_name = hdr->hdr_name; 242 | idbuf->hpi_value = NULL; 243 | firstid = idbuf; 244 | } 245 | if ((hdr->hdr_value != NULL && key->hdr_value != NULL) && 246 | strcasecmp(hdr->hdr_value, key->hdr_value) == 0) { 247 | idbuf->hpi_id = dynidx; 248 | idbuf->hpi_name = hdr->hdr_name; 249 | idbuf->hpi_value = hdr->hdr_value; 250 | id = idbuf; 251 | return (id); 252 | } 253 | } 254 | 255 | return (firstid); 256 | } 257 | 258 | static int 259 | hpack_table_add(struct hpack_header *hdr, struct hpack_table *hpack) 260 | { 261 | long newsize; 262 | 263 | if (hdr->hdr_index != HPACK_INDEX) 264 | return (0); 265 | 266 | /* 267 | * Following RFC 7451 section 4.1, 268 | * the additional 32 octets account for an estimated overhead 269 | * associated with an entry. 270 | */ 271 | newsize = strlen(hdr->hdr_name) + strlen(hdr->hdr_value) + 32; 272 | 273 | if (newsize > hpack->htb_table_size) { 274 | /* 275 | * An entry larger than the maximum size causes 276 | * the table to be emptied of all existing entries. 277 | */ 278 | hpack_table_evict(0, newsize, hpack); 279 | return (0); 280 | } else 281 | hpack_table_evict(hpack->htb_table_size, 282 | newsize, hpack); 283 | 284 | if (hpack_header_add(hpack->htb_dynamic, 285 | hdr->hdr_name, hdr->hdr_value, hdr->hdr_index) == NULL) 286 | return (-1); 287 | hpack->htb_dynamic_entries++; 288 | hpack->htb_dynamic_size += newsize; 289 | 290 | return (0); 291 | } 292 | 293 | static int 294 | hpack_table_evict(long size, long newsize, struct hpack_table *hpack) 295 | { 296 | struct hpack_header *hdr; 297 | 298 | while (size < (hpack->htb_dynamic_size + newsize) && 299 | (hdr = TAILQ_FIRST(hpack->htb_dynamic)) != NULL) { 300 | TAILQ_REMOVE(hpack->htb_dynamic, hdr, hdr_entry); 301 | hpack->htb_dynamic_entries--; 302 | hpack->htb_dynamic_size -= 303 | strlen(hdr->hdr_name) + 304 | strlen(hdr->hdr_value) + 305 | 32; 306 | hpack_header_free(hdr); 307 | } 308 | 309 | if (TAILQ_EMPTY(hpack->htb_dynamic) && 310 | hpack->htb_dynamic_entries != 0 && 311 | hpack->htb_dynamic_size != 0) 312 | errx(1, "corrupted HPACK dynamic table"); 313 | 314 | return (0); 315 | } 316 | 317 | static int 318 | hpack_table_setsize(long size, struct hpack_table *hpack) 319 | { 320 | if (size > hpack->htb_max_table_size) 321 | return (-1); 322 | 323 | if (hpack_table_evict(size, 0, hpack) == -1) 324 | return (-1); 325 | hpack->htb_table_size = size; 326 | 327 | return (0); 328 | } 329 | 330 | size_t 331 | hpack_table_size(struct hpack_table *hpack) 332 | { 333 | return ((size_t)hpack->htb_dynamic_size); 334 | } 335 | 336 | struct hpack_headerblock * 337 | hpack_decode(unsigned char *data, size_t len, struct hpack_table *hpack) 338 | { 339 | struct hpack_headerblock *hdrs = NULL; 340 | struct hbuf *hbuf = NULL; 341 | struct hpack_table *ctx = NULL; 342 | int ret = -1; 343 | 344 | if (len == 0 || len > LONG_MAX) 345 | goto fail; 346 | 347 | if (hpack == NULL && (hpack = ctx = hpack_table_new(0)) == NULL) 348 | goto fail; 349 | if ((hdrs = hpack_headerblock_new()) == NULL) 350 | goto fail; 351 | 352 | hpack->htb_headers = hdrs; 353 | hpack->htb_next = NULL; 354 | 355 | if ((hbuf = hbuf_new(data, len)) == NULL) 356 | goto fail; 357 | 358 | do { 359 | if (hpack_decode_buf(hbuf, hpack) == -1) 360 | goto fail; 361 | } while (hbuf_left(hbuf) > 0); 362 | 363 | ret = 0; 364 | fail: 365 | hbuf_free(hbuf); 366 | if (ret != 0) { 367 | hpack_headerblock_free(hdrs); 368 | hdrs = NULL; 369 | } else 370 | hdrs = hpack->htb_headers; 371 | hpack->htb_headers = NULL; 372 | hpack->htb_next = NULL; 373 | 374 | /* Free the local table (for single invocations) */ 375 | hpack_table_free(ctx); 376 | 377 | return (hdrs); 378 | } 379 | 380 | static long 381 | hpack_decode_int(struct hbuf *buf, unsigned char prefix) 382 | { 383 | unsigned long i = 0; 384 | unsigned char b = 0, m; 385 | 386 | if (hbuf_left(buf) == 0) 387 | return (-1); 388 | 389 | if (hbuf_readchar(buf, &b) == -1 || 390 | hbuf_advance(buf, 1) == -1) 391 | return (-1); 392 | 393 | /* Mask and remainder after the prefix of the first octet */ 394 | m = ~prefix; 395 | i = b & m; 396 | 397 | if (i >= m) { 398 | m = 0; 399 | 400 | /* Read varint bits while the 0x80 bit is set */ 401 | do { 402 | if (i > LONG_MAX) 403 | return (-1); 404 | if (hbuf_readchar(buf, &b) == -1 || 405 | hbuf_advance(buf, 1) == -1) 406 | return (-1); 407 | i += (b & ~0x80) << m; 408 | m += 7; 409 | } while (b & 0x80); 410 | } 411 | 412 | return ((long)i); 413 | } 414 | 415 | static long 416 | hpack_decode_index(struct hbuf *buf, unsigned char prefix, 417 | const struct hpack_index **idptr, struct hpack_table *hpack) 418 | { 419 | struct hpack_index idbuf; 420 | struct hpack_header *hdr = hpack->htb_next; 421 | const struct hpack_index *id; 422 | long i; 423 | int hasvalue; 424 | 425 | if (idptr != NULL) 426 | *idptr = NULL; 427 | 428 | if ((i = hpack_decode_int(buf, prefix)) == -1) 429 | return (-1); 430 | DPRINTF("%s: index %ld", __func__, i); 431 | 432 | if (i == 0) 433 | return (0); 434 | if ((id = hpack_table_getbyid(i, &idbuf, hpack)) == NULL) { 435 | DPRINTF("index not found: %ld\n", i); 436 | return (-1); 437 | } 438 | 439 | if (hdr == NULL || hdr->hdr_name != NULL || hdr->hdr_value != NULL) 440 | errx(1, "invalid header"); 441 | 442 | if ((hdr->hdr_name = strdup(id->hpi_name)) == NULL) 443 | return (-1); 444 | hasvalue = id->hpi_value == NULL ? 0 : 1; 445 | if (hasvalue && 446 | (hdr->hdr_value = strdup(id->hpi_value)) == NULL) { 447 | free(hdr->hdr_name); 448 | hdr->hdr_name = NULL; 449 | return (-1); 450 | } 451 | 452 | DPRINTF("%s: index: %ld (%s%s%s)", __func__, 453 | i, id->hpi_name, 454 | hasvalue ? ": " : "", 455 | hasvalue ? id->hpi_value : ""); 456 | 457 | if (idptr != NULL) 458 | *idptr = id; 459 | 460 | return (i); 461 | } 462 | 463 | static char * 464 | hpack_decode_str(struct hbuf *buf, unsigned char prefix) 465 | { 466 | long i; 467 | unsigned char *ptr, c; 468 | char *str; 469 | 470 | if (hbuf_readchar(buf, &c) == -1) 471 | return (NULL); 472 | if ((i = hpack_decode_int(buf, prefix)) == -1) 473 | return (NULL); 474 | if (hbuf_readbuf(buf, &ptr, (size_t)i) == -1 || 475 | hbuf_advance(buf, (size_t)i) == -1) 476 | return (NULL); 477 | if ((c & HPACK_M_LITERAL) == HPACK_F_LITERAL_HUFFMAN) { 478 | DPRINTF("%s: decoding huffman code (size %ld)", __func__, i); 479 | if ((str = hpack_huffman_decode_str(ptr, (size_t)i)) == NULL) 480 | return (NULL); 481 | } else { 482 | if ((str = calloc(1, (size_t)i + 1)) == NULL) 483 | return (NULL); 484 | memcpy(str, ptr, (size_t)i); 485 | } 486 | return (str); 487 | } 488 | 489 | static int 490 | hpack_decode_literal(struct hbuf *buf, unsigned char prefix, 491 | struct hpack_table *hpack) 492 | { 493 | struct hpack_header *hdr = hpack->htb_next; 494 | const struct hpack_index *id; 495 | long i; 496 | char *str; 497 | 498 | if ((i = hpack_decode_index(buf, prefix, &id, hpack)) == -1) 499 | return (-1); 500 | 501 | if (i == 0) { 502 | if (hdr == NULL || 503 | hdr->hdr_name != NULL || hdr->hdr_value != NULL) 504 | errx(1, "invalid header"); 505 | 506 | if ((str = hpack_decode_str(buf, 507 | HPACK_M_LITERAL)) == NULL) 508 | return (-1); 509 | DPRINTF("%s: name: %s", __func__, str); 510 | hdr->hdr_name = str; 511 | } 512 | 513 | /* The index might have set a default value */ 514 | if (hdr->hdr_value != NULL) { 515 | free(hdr->hdr_value); 516 | hdr->hdr_value = NULL; 517 | } 518 | 519 | if ((str = hpack_decode_str(buf, HPACK_M_LITERAL)) == NULL) 520 | return (-1); 521 | DPRINTF("%s: value: %s", __func__, str); 522 | hdr->hdr_value = str; 523 | 524 | return (0); 525 | } 526 | 527 | static int 528 | hpack_decode_buf(struct hbuf *buf, struct hpack_table *hpack) 529 | { 530 | struct hpack_header *hdr = NULL; 531 | unsigned char c; 532 | long i; 533 | 534 | if (hbuf_readchar(buf, &c) == -1) 535 | goto fail; 536 | 537 | if ((hdr = hpack_header_new()) == NULL) 538 | goto fail; 539 | hdr->hdr_index = HPACK_NO_INDEX; 540 | hpack->htb_next = hdr; 541 | 542 | /* 6.1 Indexed Header Field Representation */ 543 | if ((c & HPACK_M_INDEX) == HPACK_F_INDEX) { 544 | DPRINTF("%s: 0x%02x: 6.1 index", __func__, c); 545 | 546 | /* 7 bit index */ 547 | if ((i = hpack_decode_index(buf, 548 | HPACK_M_INDEX, NULL, hpack)) == -1) 549 | goto fail; 550 | 551 | /* No value means header with empty value */ 552 | if ((hdr->hdr_value == NULL) && 553 | (hdr->hdr_value = strdup("")) == NULL) 554 | goto fail; 555 | } 556 | 557 | /* 6.2.1. Literal Header Field with Incremental Indexing */ 558 | else if ((c & HPACK_M_LITERAL_INDEX) == HPACK_F_LITERAL_INDEX) { 559 | DPRINTF("%s: 0x%02x: 6.2.1 literal indexed", __func__, c); 560 | 561 | /* 6 bit index */ 562 | if (hpack_decode_literal(buf, 563 | HPACK_M_LITERAL_INDEX, hpack) == -1) 564 | goto fail; 565 | hdr->hdr_index = HPACK_INDEX; 566 | } 567 | 568 | /* 6.2.2. Literal Header Field without Indexing */ 569 | else if ((c & HPACK_M_LITERAL_NO_INDEX) == HPACK_F_LITERAL_NO_INDEX) { 570 | DPRINTF("%s: 0x%02x: 6.2.2 literal", __func__, c); 571 | 572 | /* 4 bit index */ 573 | if (hpack_decode_literal(buf, 574 | HPACK_M_LITERAL_NO_INDEX, hpack) == -1) 575 | goto fail; 576 | } 577 | 578 | /* 6.2.3. Literal Header Field Never Indexed */ 579 | else if ((c & HPACK_M_LITERAL_NO_INDEX) == HPACK_F_LITERAL_NO_INDEX) { 580 | DPRINTF("%s: 0x%02x: 6.2.3 literal never indexed", __func__, c); 581 | 582 | /* 4 bit index */ 583 | if (hpack_decode_literal(buf, 584 | HPACK_M_LITERAL_NO_INDEX, hpack) == -1) 585 | goto fail; 586 | hdr->hdr_index = HPACK_NEVER_INDEX; 587 | } 588 | 589 | /* 6.3. Dynamic Table Size Update */ 590 | else if ((c & HPACK_M_TABLE_SIZE_UPDATE) == HPACK_F_TABLE_SIZE_UPDATE) { 591 | DPRINTF("%s: 0x%02x: 6.3 dynamic table update", __func__, c); 592 | 593 | /* 5 bit index */ 594 | if ((i = hpack_decode_int(buf, 595 | HPACK_M_TABLE_SIZE_UPDATE)) == -1) 596 | goto fail; 597 | 598 | if (hpack_table_setsize(i, hpack) == -1) 599 | goto fail; 600 | 601 | return (0); 602 | } 603 | 604 | /* unknown index */ 605 | else { 606 | DPRINTF("%s: 0x%02x: unknown index", __func__, c); 607 | goto fail; 608 | } 609 | 610 | if (hdr->hdr_name == NULL || hdr->hdr_value == NULL) 611 | goto fail; 612 | 613 | /* Optionally add to index */ 614 | if (hpack_table_add(hdr, hpack) == -1) 615 | goto fail; 616 | 617 | /* Add header to the list */ 618 | TAILQ_INSERT_TAIL(hpack->htb_headers, hdr, hdr_entry); 619 | hpack->htb_next = NULL; 620 | 621 | return (0); 622 | fail: 623 | DPRINTF("%s: failed", __func__); 624 | hpack_header_free(hdr); 625 | hpack->htb_next = NULL; 626 | 627 | return (-1); 628 | } 629 | 630 | unsigned char * 631 | hpack_encode(struct hpack_headerblock *hdrs, size_t *encoded_len, 632 | struct hpack_table *hpack) 633 | { 634 | const struct hpack_index *id; 635 | struct hpack_index idbuf; 636 | struct hpack_table *ctx = NULL; 637 | struct hpack_header *hdr; 638 | struct hbuf *hbuf = NULL; 639 | unsigned char mask, flag; 640 | 641 | if (hpack == NULL && (hpack = ctx = hpack_table_new(0)) == NULL) 642 | goto fail; 643 | 644 | if ((hbuf = hbuf_new(NULL, BUFSIZ)) == NULL) 645 | goto fail; 646 | 647 | TAILQ_FOREACH(hdr, hdrs, hdr_entry) { 648 | DPRINTF("%s: header %s: %s (index %d)", __func__, 649 | hdr->hdr_name, 650 | hdr->hdr_value == NULL ? "(null)" : hdr->hdr_value, 651 | hdr->hdr_index); 652 | 653 | switch (hdr->hdr_index) { 654 | case HPACK_INDEX: 655 | mask = HPACK_M_LITERAL_INDEX; 656 | flag = HPACK_F_LITERAL_INDEX; 657 | break; 658 | case HPACK_NO_INDEX: 659 | mask = HPACK_M_LITERAL_NO_INDEX; 660 | flag = HPACK_F_LITERAL_NO_INDEX; 661 | break; 662 | case HPACK_NEVER_INDEX: 663 | mask = HPACK_M_LITERAL_NEVER_INDEX; 664 | flag = HPACK_F_LITERAL_NEVER_INDEX; 665 | break; 666 | } 667 | 668 | id = hpack_table_getbyheader(hdr, &idbuf, hpack); 669 | 670 | /* 6.1 Indexed Header Field Representation */ 671 | if (id != NULL && id->hpi_value != NULL) { 672 | DPRINTF("%s: index %zu (%s: %s)", __func__, 673 | id->hpi_id, 674 | id->hpi_name, 675 | id->hpi_value == NULL ? "(null)" : id->hpi_value); 676 | if (hpack_encode_int(hbuf, id->hpi_id, 677 | HPACK_M_INDEX, HPACK_F_INDEX) == -1) 678 | goto fail; 679 | continue; 680 | } 681 | 682 | /* 6.2 Literal Header Field Representation */ 683 | else if (id != NULL) { 684 | DPRINTF("%s: index+name %zu, %s", __func__, 685 | id->hpi_id, 686 | hdr->hdr_value); 687 | 688 | if (hpack_encode_int(hbuf, id->hpi_id, 689 | mask, flag) == -1) 690 | goto fail; 691 | } else { 692 | DPRINTF("%s: literal %s: %s", __func__, 693 | hdr->hdr_name, 694 | hdr->hdr_value); 695 | 696 | if (hpack_encode_int(hbuf, 0, mask, flag) == -1) 697 | goto fail; 698 | 699 | /* name */ 700 | if (hpack_encode_str(hbuf, hdr->hdr_name) == -1) 701 | goto fail; 702 | } 703 | 704 | /* value */ 705 | if (hpack_encode_str(hbuf, hdr->hdr_value) == -1) 706 | goto fail; 707 | 708 | /* Optionally add to index */ 709 | if (hpack_table_add(hdr, hpack) == -1) 710 | goto fail; 711 | } 712 | 713 | return (hbuf_release(hbuf, encoded_len)); 714 | fail: 715 | hpack_table_free(ctx); 716 | hbuf_free(hbuf); 717 | return (NULL); 718 | } 719 | 720 | static int 721 | hpack_encode_int(struct hbuf *buf, long i, unsigned char prefix, 722 | unsigned char type) 723 | { 724 | unsigned char b, m; 725 | 726 | if (i < 0) 727 | return (-1); 728 | 729 | /* The first octet encodes up to prefix length bits */ 730 | m = ~prefix; 731 | if (i <= m) 732 | b = (i & m) | type; 733 | else 734 | b = m | type; 735 | if (hbuf_writechar(buf, b) == -1) 736 | return (-1); 737 | i -= m; 738 | 739 | /* Encode the remainder as a varint */ 740 | for (m = 0x80; i >= m; i /= m) { 741 | b = i % m + m; 742 | /* Set the continuation bit if there are steps left */ 743 | if (i >= m) 744 | b |= m; 745 | if (hbuf_writechar(buf, b) == -1) 746 | return (-1); 747 | } 748 | if (i > 0 && 749 | hbuf_writechar(buf, (unsigned char)i) == -1) 750 | return (-1); 751 | 752 | return (0); 753 | } 754 | 755 | static int 756 | hpack_encode_str(struct hbuf *buf, char *str) 757 | { 758 | unsigned char *data = NULL; 759 | size_t len, slen; 760 | int ret = -1; 761 | 762 | /* 763 | * We have to decide if the string should be encoded with huffman 764 | * encoding or as literal string. There could be better heuristics 765 | * to do this... 766 | */ 767 | slen = strlen(str); 768 | if ((data = hpack_huffman_encode(str, slen, &len)) == NULL) 769 | goto done; 770 | if (len > 0 && len < slen) { 771 | DPRINTF("%s: encoded huffman code (size %ld, from %ld)", 772 | __func__, len, slen); 773 | if (hpack_encode_int(buf, len, HPACK_M_LITERAL, 774 | HPACK_F_LITERAL_HUFFMAN) == -1) 775 | goto done; 776 | if (hbuf_writebuf(buf, data, len) == -1) 777 | goto done; 778 | } else { 779 | if (hpack_encode_int(buf, slen, HPACK_M_LITERAL, 780 | HPACK_F_LITERAL) == -1) 781 | goto done; 782 | if (hbuf_writebuf(buf, str, slen) == -1) 783 | goto done; 784 | } 785 | 786 | ret = 0; 787 | done: 788 | free(data); 789 | return (ret); 790 | } 791 | 792 | static int 793 | hpack_huffman_init(void) 794 | { 795 | struct hpack_huffman *hph; 796 | struct hpack_huffman_node *root, *cur, *node; 797 | unsigned int i, j; 798 | 799 | /* Create new Huffman tree */ 800 | if ((root = hpack_huffman_new()) == NULL) 801 | return (-1); 802 | 803 | for (i = 0; i < HPACK_HUFFMAN_SIZE; i++) { 804 | hph = &huffman_table[i]; 805 | cur = root; 806 | 807 | /* Create branch for each symbol */ 808 | for (j = hph->hph_length; j > 0; j--) { 809 | if ((hph->hph_code >> (j - 1)) & 1) { 810 | if (cur->hpn_one == NULL) { 811 | if ((node = 812 | hpack_huffman_new()) == NULL) 813 | goto fail; 814 | cur->hpn_one = node; 815 | } 816 | cur = cur->hpn_one; 817 | } else { 818 | if (cur->hpn_zero == NULL) { 819 | if ((node = 820 | hpack_huffman_new()) == NULL) 821 | goto fail; 822 | cur->hpn_zero = node; 823 | } 824 | cur = cur->hpn_zero; 825 | } 826 | } 827 | 828 | /* The leaf node contains the (8-bit ASCII) symbol */ 829 | cur->hpn_sym = i; 830 | } 831 | 832 | hpack_global.hpack_huffman = root; 833 | return (0); 834 | fail: 835 | hpack_huffman_free(root); 836 | hpack_global.hpack_huffman = NULL; 837 | return (-1); 838 | } 839 | 840 | unsigned char * 841 | hpack_huffman_decode(unsigned char *buf, size_t len, size_t *decoded_len) 842 | { 843 | struct hpack_huffman_node *node, *root; 844 | unsigned int i, j, code; 845 | struct hbuf *hbuf = NULL; 846 | 847 | if ((root = node = hpack_global.hpack_huffman) == NULL) 848 | errx(1, "hpack not initialized"); 849 | 850 | if ((hbuf = hbuf_new(NULL, len)) == NULL) 851 | return (NULL); 852 | 853 | for (i = 0; i < len; i++) { 854 | code = buf[i]; 855 | 856 | /* Walk the Huffman tree for each bit in the encoded input */ 857 | for (j = 8; j > 0; j--) { 858 | if ((code >> (j - 1)) & 1) 859 | node = node->hpn_one; 860 | else 861 | node = node->hpn_zero; 862 | if (node->hpn_sym == -1) 863 | continue; 864 | 865 | /* Leaf node of the next (8-bit ASCII) symbol */ 866 | if (hbuf_writechar(hbuf, 867 | (unsigned char)node->hpn_sym) == -1) { 868 | DPRINTF("%s: failed to add '%c'", __func__, 869 | node->hpn_sym); 870 | goto fail; 871 | } 872 | node = root; 873 | } 874 | } 875 | 876 | return (hbuf_release(hbuf, decoded_len)); 877 | fail: 878 | *decoded_len = 0; 879 | hbuf_free(hbuf); 880 | return (NULL); 881 | } 882 | 883 | char * 884 | hpack_huffman_decode_str(unsigned char *buf, size_t len) 885 | { 886 | unsigned char *data; 887 | char *str; 888 | size_t data_len; 889 | 890 | if ((data = hpack_huffman_decode(buf, len, &data_len)) == NULL) 891 | return (NULL); 892 | 893 | /* Allocate with an extra NUL character */ 894 | if ((str = recallocarray(data, data_len, data_len + 1, 1)) == NULL) { 895 | freezero(data, data_len); 896 | return (NULL); 897 | } 898 | 899 | /* Check if this is an actual string (no matter of the encoding) */ 900 | if (strlen(str) != data_len) { 901 | freezero(str, data_len + 1); 902 | str = NULL; 903 | } 904 | 905 | return (str); 906 | } 907 | 908 | unsigned char * 909 | hpack_huffman_encode(unsigned char *data, size_t len, size_t *encoded_len) 910 | { 911 | struct hbuf *hbuf; 912 | struct hpack_huffman *hph; 913 | unsigned int code, i, j; 914 | unsigned char o, obits; 915 | 916 | if ((hbuf = hbuf_new(NULL, len)) == NULL) 917 | return (NULL); 918 | 919 | for (i = 0, o = 0, obits = 8; i < len; i++) { 920 | /* Get Huffman code for each (8-bit ASCII) symbol */ 921 | hph = &huffman_table[data[i]]; 922 | 923 | for (code = hph->hph_code, j = hph->hph_length; j > 0;) { 924 | if (j > obits) { 925 | /* More bits to encode for this symbol */ 926 | j -= obits; 927 | o |= (code >> j) & 0xff; 928 | obits = 0; 929 | } else { 930 | /* 931 | * Remaining bits to encode for this input 932 | * symbol. The current output octet will 933 | * include bits from the next symbol or padding. 934 | */ 935 | obits -= j; 936 | o |= (code << obits) & 0xff; 937 | j = 0; 938 | } 939 | if (obits == 0) { 940 | if (hbuf_writechar(hbuf, o) == -1) { 941 | DPRINTF("%s: failed to add '%c'", 942 | __func__, o); 943 | goto fail; 944 | } 945 | o = 0; 946 | obits = 8; 947 | } 948 | } 949 | } 950 | 951 | if (len && obits > 0 && obits < 8) { 952 | /* Pad last octet with ones (EOS) */ 953 | o |= (1 << obits) - 1; 954 | if (hbuf_writechar(hbuf, o) == -1) { 955 | DPRINTF("%s: failed to add '%c'", __func__, o); 956 | goto fail; 957 | } 958 | } 959 | 960 | return (hbuf_release(hbuf, encoded_len)); 961 | fail: 962 | *encoded_len = 0; 963 | hbuf_free(hbuf); 964 | return (NULL); 965 | } 966 | 967 | static struct hpack_huffman_node * 968 | hpack_huffman_new(void) 969 | { 970 | struct hpack_huffman_node *node; 971 | 972 | if ((node = calloc(1, sizeof(*node))) == NULL) 973 | return (NULL); 974 | node->hpn_sym = -1; 975 | 976 | return (node); 977 | } 978 | 979 | static void 980 | hpack_huffman_free(struct hpack_huffman_node *root) 981 | { 982 | if (root == NULL) 983 | return; 984 | hpack_huffman_free(root->hpn_zero); 985 | hpack_huffman_free(root->hpn_one); 986 | free(root); 987 | } 988 | 989 | static struct hbuf * 990 | hbuf_new(unsigned char *data, size_t len) 991 | { 992 | struct hbuf *buf; 993 | size_t size = len; 994 | 995 | if ((buf = calloc(1, sizeof(*buf))) == NULL) 996 | return (NULL); 997 | size = MAX(HPACK_HUFFMAN_BUFSZ, len); 998 | if ((buf->data = calloc(1, size)) == NULL) { 999 | free(buf); 1000 | return (NULL); 1001 | } 1002 | if (data != NULL) { 1003 | memcpy(buf->data, data, len); 1004 | buf->wpos = len; 1005 | } 1006 | buf->size = buf->wbsz = size; 1007 | return (buf); 1008 | } 1009 | 1010 | static void 1011 | hbuf_free(struct hbuf *buf) 1012 | { 1013 | if (buf == NULL) 1014 | return; 1015 | freezero(buf->data, buf->size); 1016 | free(buf); 1017 | } 1018 | 1019 | static int 1020 | hbuf_realloc(struct hbuf *buf, size_t len) 1021 | { 1022 | unsigned char *ptr; 1023 | size_t newsize; 1024 | 1025 | /* Allocate a multiple of the initial write buffer size */ 1026 | newsize = (buf->size + len + (buf->wbsz - 1)) & ~(buf->wbsz - 1); 1027 | 1028 | DPRINTF("%s: size %zu -> %zu", __func__, buf->size, newsize); 1029 | 1030 | if ((ptr = recallocarray(buf->data, buf->size, newsize, 1)) == NULL) 1031 | return (-1); 1032 | buf->data = ptr; 1033 | buf->size = newsize; 1034 | 1035 | return (0); 1036 | } 1037 | 1038 | static int 1039 | hbuf_writechar(struct hbuf *buf, unsigned char c) 1040 | { 1041 | return (hbuf_writebuf(buf, &c, 1)); 1042 | } 1043 | 1044 | static int 1045 | hbuf_writebuf(struct hbuf *buf, unsigned char *data, size_t len) 1046 | { 1047 | if ((buf->wpos + len > buf->size) && 1048 | hbuf_realloc(buf, len) == -1) 1049 | return (-1); 1050 | 1051 | memcpy(buf->data + buf->wpos, data, len); 1052 | buf->wpos += len; 1053 | 1054 | return (0); 1055 | } 1056 | 1057 | static unsigned char * 1058 | hbuf_release(struct hbuf *buf, size_t *len) 1059 | { 1060 | unsigned char *data; 1061 | 1062 | /* 1063 | * Adjust (shrink) buffer to the used size. This allows to 1064 | * safely call recallocarray() or freezero() later. 1065 | */ 1066 | if (buf->wpos != buf->size) { 1067 | if ((data = recallocarray(buf->data, 1068 | buf->size, buf->wpos, 1)) == NULL) { 1069 | hbuf_free(buf); 1070 | return (NULL); 1071 | } 1072 | buf->data = data; 1073 | } 1074 | 1075 | *len = buf->wpos; 1076 | data = buf->data; 1077 | free(buf); 1078 | 1079 | return (data); 1080 | } 1081 | 1082 | static int 1083 | hbuf_readchar(struct hbuf *buf, unsigned char *c) 1084 | { 1085 | if (buf->rpos + 1 > buf->size) 1086 | return (-1); 1087 | *c = *(buf->data + buf->rpos); 1088 | return (0); 1089 | } 1090 | 1091 | static int 1092 | hbuf_readbuf(struct hbuf *buf, unsigned char **ptr, size_t len) 1093 | { 1094 | if (buf->rpos + len > buf->size) 1095 | return (-1); 1096 | *ptr = buf->data + buf->rpos; 1097 | return (0); 1098 | } 1099 | 1100 | static int 1101 | hbuf_advance(struct hbuf *buf, size_t len) 1102 | { 1103 | if (buf->rpos + len > buf->size) 1104 | return (-1); 1105 | buf->rpos += len; 1106 | return (0); 1107 | } 1108 | 1109 | static size_t 1110 | hbuf_left(struct hbuf *buf) 1111 | { 1112 | if (buf->rpos >= buf->wpos) 1113 | return (0); 1114 | return (buf->wpos - buf->rpos); 1115 | } 1116 | -------------------------------------------------------------------------------- /hpack.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD$ */ 2 | 3 | /* 4 | * Copyright (c) 2019 Reyk Floeter 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | #ifndef HPACK_H 22 | #define HPACK_H 23 | 24 | struct hpack_table; 25 | 26 | enum hpack_header_index { 27 | HPACK_NO_INDEX = 0, 28 | HPACK_NEVER_INDEX, 29 | HPACK_INDEX, 30 | }; 31 | 32 | struct hpack_header { 33 | char *hdr_name; 34 | char *hdr_value; 35 | enum hpack_header_index hdr_index; 36 | TAILQ_ENTRY(hpack_header) hdr_entry; 37 | }; 38 | TAILQ_HEAD(hpack_headerblock, hpack_header); 39 | 40 | int hpack_init(void); 41 | 42 | struct hpack_table 43 | *hpack_table_new(size_t); 44 | void hpack_table_free(struct hpack_table *); 45 | size_t hpack_table_size(struct hpack_table *); 46 | 47 | struct hpack_headerblock 48 | *hpack_decode(unsigned char *, size_t, struct hpack_table *); 49 | unsigned char 50 | *hpack_encode(struct hpack_headerblock *, size_t *, 51 | struct hpack_table *); 52 | 53 | struct hpack_header 54 | *hpack_header_new(void); 55 | struct hpack_header 56 | *hpack_header_add(struct hpack_headerblock *, 57 | const char *, const char *, enum hpack_header_index); 58 | void hpack_header_free(struct hpack_header *); 59 | struct hpack_headerblock 60 | *hpack_headerblock_new(void); 61 | void hpack_headerblock_free(struct hpack_headerblock *); 62 | 63 | unsigned char 64 | *hpack_huffman_decode(unsigned char *, size_t, size_t *); 65 | char *hpack_huffman_decode_str(unsigned char *, size_t); 66 | unsigned char 67 | *hpack_huffman_encode(unsigned char *, size_t, size_t *); 68 | 69 | #ifdef HPACK_INTERNAL 70 | 71 | #ifndef DEBUG 72 | #define DPRINTF(x...) do{} while(0) 73 | #else 74 | #define DPRINTF warnx 75 | #endif 76 | 77 | /* from sys/param.h */ 78 | #define MAX(a,b) (((a)>(b))?(a):(b)) 79 | 80 | #define HPACK_HUFFMAN_BUFSZ 256 81 | #define HPACK_MAX_TABLE_SIZE 4096 82 | 83 | struct hpack_huffman_node { 84 | struct hpack_huffman_node *hpn_zero; 85 | struct hpack_huffman_node *hpn_one; 86 | int hpn_sym; 87 | }; 88 | 89 | struct hpack { 90 | struct hpack_huffman_node *hpack_huffman; 91 | }; 92 | 93 | struct hpack_table { 94 | struct hpack_headerblock *htb_dynamic; 95 | long htb_dynamic_size; 96 | long htb_dynamic_entries; 97 | 98 | long htb_table_size; 99 | long htb_max_table_size; 100 | 101 | struct hpack_headerblock *htb_headers; 102 | struct hpack_header *htb_next; 103 | }; 104 | 105 | /* Simple internal buffer API */ 106 | struct hbuf { 107 | unsigned char *data; /* data pointer */ 108 | size_t size; /* data size */ 109 | size_t rpos; /* read position */ 110 | size_t wpos; /* write position */ 111 | size_t wbsz; /* realloc buf size */ 112 | }; 113 | 114 | /* Masks, flags, and prefixes of the field types */ 115 | #define HPACK_M_INDEX 0x80 /* 7-bit prefix */ 116 | #define HPACK_F_INDEX 0x80 /* index flag */ 117 | #define HPACK_M_LITERAL_INDEX 0xc0 /* 6-bit prefix */ 118 | #define HPACK_F_LITERAL_INDEX 0x40 /* literal index flag */ 119 | #define HPACK_M_LITERAL_NO_INDEX 0xf0 /* 4-bit prefix */ 120 | #define HPACK_F_LITERAL_NO_INDEX 0x00 /* no index flag */ 121 | #define HPACK_M_LITERAL_NEVER_INDEX 0xf0 /* 4-bit prefix */ 122 | #define HPACK_F_LITERAL_NEVER_INDEX 0x10 /* never index flag */ 123 | #define HPACK_M_TABLE_SIZE_UPDATE 0xe0 /* 5-bit prefix */ 124 | #define HPACK_F_TABLE_SIZE_UPDATE 0x20 /* dynamic table size flag */ 125 | #define HPACK_M_LITERAL 0x80 /* 7-bit index */ 126 | #define HPACK_F_LITERAL 0x00 /* literal encoding */ 127 | #define HPACK_F_LITERAL_HUFFMAN 0x80 /* huffman encoding */ 128 | 129 | /* 130 | * Appendix A. Static Table Definition 131 | */ 132 | struct hpack_index { 133 | long hpi_id; /* Index */ 134 | const char *hpi_name; /* Header Name */ 135 | const char *hpi_value; /* Value */ 136 | }; 137 | #define HPACK_STATIC_SIZE (sizeof(static_table) / sizeof(static_table[0])) 138 | static struct hpack_index static_table[] = { 139 | { 1, ":authority", NULL }, \ 140 | { 2, ":method", "GET" }, \ 141 | { 3, ":method", "POST" }, \ 142 | { 4, ":path", "/" }, \ 143 | { 5, ":path", "/index.html"}, \ 144 | { 6, ":scheme", "http" }, \ 145 | { 7, ":scheme", "https" }, \ 146 | { 8, ":status", "200" }, \ 147 | { 9, ":status", "204" }, \ 148 | { 10, ":status", "206" }, \ 149 | { 11, ":status", "304" }, \ 150 | { 12, ":status", "400" }, \ 151 | { 13, ":status", "404" }, \ 152 | { 14, ":status", "500" }, \ 153 | { 15, "accept-charset", NULL }, \ 154 | { 16, "accept-encoding", "gzip, deflate" }, \ 155 | { 17, "accept-language", NULL }, \ 156 | { 18, "accept-ranges", NULL }, \ 157 | { 19, "accept", NULL }, \ 158 | { 20, "access-control-allow-origin", NULL }, \ 159 | { 21, "age", NULL }, \ 160 | { 22, "allow", NULL }, \ 161 | { 23, "authorization", NULL }, \ 162 | { 24, "cache-control", NULL }, \ 163 | { 25, "content-disposition", NULL }, \ 164 | { 26, "content-encoding", NULL }, \ 165 | { 27, "content-language", NULL }, \ 166 | { 28, "content-length", NULL }, \ 167 | { 29, "content-location", NULL }, \ 168 | { 30, "content-range", NULL }, \ 169 | { 31, "content-type", NULL }, \ 170 | { 32, "cookie", NULL }, \ 171 | { 33, "date", NULL }, \ 172 | { 34, "etag", NULL }, \ 173 | { 35, "expect", NULL }, \ 174 | { 36, "expires", NULL }, \ 175 | { 37, "from", NULL }, \ 176 | { 38, "host", NULL }, \ 177 | { 39, "if-match", NULL }, \ 178 | { 40, "if-modified-since", NULL }, \ 179 | { 41, "if-none-match", NULL }, \ 180 | { 42, "if-range", NULL }, \ 181 | { 43, "if-unmodified-since", NULL }, \ 182 | { 44, "last-modified", NULL }, \ 183 | { 45, "link", NULL }, \ 184 | { 46, "location", NULL }, \ 185 | { 47, "max-forwards", NULL }, \ 186 | { 48, "proxy-authenticate", NULL }, \ 187 | { 49, "proxy-authorization", NULL }, \ 188 | { 50, "range", NULL }, \ 189 | { 51, "referer", NULL }, \ 190 | { 52, "refresh", NULL }, \ 191 | { 53, "retry-after", NULL }, \ 192 | { 54, "server", NULL }, \ 193 | { 55, "set-cookie", NULL }, \ 194 | { 56, "strict-transport-security", NULL }, \ 195 | { 57, "transfer-encoding", NULL }, \ 196 | { 58, "user-agent", NULL }, \ 197 | { 59, "vary", NULL }, \ 198 | { 60, "via", NULL }, \ 199 | { 61, "www-authenticate", NULL }, \ 200 | }; 201 | 202 | /* 203 | * Appendix B. Huffman Code 204 | */ 205 | struct hpack_huffman { 206 | /* (comment) */ /* ASCII symbol */ 207 | /* (comment) */ /* code as bits aligned to MSB */ 208 | unsigned int hph_code; /* code as hex aligned to LSB */ 209 | unsigned int hph_length; /* len in bits */ 210 | }; 211 | #define HPACK_HUFFMAN_SIZE (sizeof(huffman_table) / sizeof(huffman_table[0])) 212 | static struct hpack_huffman huffman_table[] = { 213 | { /* ( 0) |11111111|11000 */ 0x1ff8, 13 }, 214 | { /* ( 1) |11111111|11111111|1011000 */ 0x7fffd8, 23 }, 215 | { /* ( 2) |11111111|11111111|11111110|0010 */ 0xfffffe2, 28 }, 216 | { /* ( 3) |11111111|11111111|11111110|0011 */ 0xfffffe3, 28 }, 217 | { /* ( 4) |11111111|11111111|11111110|0100 */ 0xfffffe4, 28 }, 218 | { /* ( 5) |11111111|11111111|11111110|0101 */ 0xfffffe5, 28 }, 219 | { /* ( 6) |11111111|11111111|11111110|0110 */ 0xfffffe6, 28 }, 220 | { /* ( 7) |11111111|11111111|11111110|0111 */ 0xfffffe7, 28 }, 221 | { /* ( 8) |11111111|11111111|11111110|1000 */ 0xfffffe8, 28 }, 222 | { /* ( 9) |11111111|11111111|11101010 */ 0xffffea, 24 }, 223 | { /* ( 10) |11111111|11111111|11111111|111100 */ 0x3ffffffc, 30 }, 224 | { /* ( 11) |11111111|11111111|11111110|1001 */ 0xfffffe9, 28 }, 225 | { /* ( 12) |11111111|11111111|11111110|1010 */ 0xfffffea, 28 }, 226 | { /* ( 13) |11111111|11111111|11111111|111101 */ 0x3ffffffd, 30 }, 227 | { /* ( 14) |11111111|11111111|11111110|1011 */ 0xfffffeb, 28 }, 228 | { /* ( 15) |11111111|11111111|11111110|1100 */ 0xfffffec, 28 }, 229 | { /* ( 16) |11111111|11111111|11111110|1101 */ 0xfffffed, 28 }, 230 | { /* ( 17) |11111111|11111111|11111110|1110 */ 0xfffffee, 28 }, 231 | { /* ( 18) |11111111|11111111|11111110|1111 */ 0xfffffef, 28 }, 232 | { /* ( 19) |11111111|11111111|11111111|0000 */ 0xffffff0, 28 }, 233 | { /* ( 20) |11111111|11111111|11111111|0001 */ 0xffffff1, 28 }, 234 | { /* ( 21) |11111111|11111111|11111111|0010 */ 0xffffff2, 28 }, 235 | { /* ( 22) |11111111|11111111|11111111|111110 */ 0x3ffffffe, 30 }, 236 | { /* ( 23) |11111111|11111111|11111111|0011 */ 0xffffff3, 28 }, 237 | { /* ( 24) |11111111|11111111|11111111|0100 */ 0xffffff4, 28 }, 238 | { /* ( 25) |11111111|11111111|11111111|0101 */ 0xffffff5, 28 }, 239 | { /* ( 26) |11111111|11111111|11111111|0110 */ 0xffffff6, 28 }, 240 | { /* ( 27) |11111111|11111111|11111111|0111 */ 0xffffff7, 28 }, 241 | { /* ( 28) |11111111|11111111|11111111|1000 */ 0xffffff8, 28 }, 242 | { /* ( 29) |11111111|11111111|11111111|1001 */ 0xffffff9, 28 }, 243 | { /* ( 30) |11111111|11111111|11111111|1010 */ 0xffffffa, 28 }, 244 | { /* ( 31) |11111111|11111111|11111111|1011 */ 0xffffffb, 28 }, 245 | { /* ' ' ( 32) |010100 */ 0x14, 6 }, 246 | { /* '!' ( 33) |11111110|00 */ 0x3f8, 10 }, 247 | { /* '"' ( 34) |11111110|01 */ 0x3f9, 10 }, 248 | { /* '#' ( 35) |11111111|1010 */ 0xffa, 12 }, 249 | { /* '$' ( 36) |11111111|11001 */ 0x1ff9, 13 }, 250 | { /* '%' ( 37) |010101 */ 0x15, 6 }, 251 | { /* '&' ( 38) |11111000 */ 0xf8, 8 }, 252 | { /* ''' ( 39) |11111111|010 */ 0x7fa, 11 }, 253 | { /* '(' ( 40) |11111110|10 */ 0x3fa, 10 }, 254 | { /* ')' ( 41) |11111110|11 */ 0x3fb, 10 }, 255 | { /* '*' ( 42) |11111001 */ 0xf9, 8 }, 256 | { /* '+' ( 43) |11111111|011 */ 0x7fb, 11 }, 257 | { /* ',' ( 44) |11111010 */ 0xfa, 8 }, 258 | { /* '-' ( 45) |010110 */ 0x16, 6 }, 259 | { /* '.' ( 46) |010111 */ 0x17, 6 }, 260 | { /* '/' ( 47) |011000 */ 0x18, 6 }, 261 | { /* '0' ( 48) |00000 */ 0x0, 5 }, 262 | { /* '1' ( 49) |00001 */ 0x1, 5 }, 263 | { /* '2' ( 50) |00010 */ 0x2, 5 }, 264 | { /* '3' ( 51) |011001 */ 0x19, 6 }, 265 | { /* '4' ( 52) |011010 */ 0x1a, 6 }, 266 | { /* '5' ( 53) |011011 */ 0x1b, 6 }, 267 | { /* '6' ( 54) |011100 */ 0x1c, 6 }, 268 | { /* '7' ( 55) |011101 */ 0x1d, 6 }, 269 | { /* '8' ( 56) |011110 */ 0x1e, 6 }, 270 | { /* '9' ( 57) |011111 */ 0x1f, 6 }, 271 | { /* ':' ( 58) |1011100 */ 0x5c, 7 }, 272 | { /* ';' ( 59) |11111011 */ 0xfb, 8 }, 273 | { /* '<' ( 60) |11111111|1111100 */ 0x7ffc, 15 }, 274 | { /* '=' ( 61) |100000 */ 0x20, 6 }, 275 | { /* '>' ( 62) |11111111|1011 */ 0xffb, 12 }, 276 | { /* '?' ( 63) |11111111|00 */ 0x3fc, 10 }, 277 | { /* '@' ( 64) |11111111|11010 */ 0x1ffa, 13 }, 278 | { /* 'A' ( 65) |100001 */ 0x21, 6 }, 279 | { /* 'B' ( 66) |1011101 */ 0x5d, 7 }, 280 | { /* 'C' ( 67) |1011110 */ 0x5e, 7 }, 281 | { /* 'D' ( 68) |1011111 */ 0x5f, 7 }, 282 | { /* 'E' ( 69) |1100000 */ 0x60, 7 }, 283 | { /* 'F' ( 70) |1100001 */ 0x61, 7 }, 284 | { /* 'G' ( 71) |1100010 */ 0x62, 7 }, 285 | { /* 'H' ( 72) |1100011 */ 0x63, 7 }, 286 | { /* 'I' ( 73) |1100100 */ 0x64, 7 }, 287 | { /* 'J' ( 74) |1100101 */ 0x65, 7 }, 288 | { /* 'K' ( 75) |1100110 */ 0x66, 7 }, 289 | { /* 'L' ( 76) |1100111 */ 0x67, 7 }, 290 | { /* 'M' ( 77) |1101000 */ 0x68, 7 }, 291 | { /* 'N' ( 78) |1101001 */ 0x69, 7 }, 292 | { /* 'O' ( 79) |1101010 */ 0x6a, 7 }, 293 | { /* 'P' ( 80) |1101011 */ 0x6b, 7 }, 294 | { /* 'Q' ( 81) |1101100 */ 0x6c, 7 }, 295 | { /* 'R' ( 82) |1101101 */ 0x6d, 7 }, 296 | { /* 'S' ( 83) |1101110 */ 0x6e, 7 }, 297 | { /* 'T' ( 84) |1101111 */ 0x6f, 7 }, 298 | { /* 'U' ( 85) |1110000 */ 0x70, 7 }, 299 | { /* 'V' ( 86) |1110001 */ 0x71, 7 }, 300 | { /* 'W' ( 87) |1110010 */ 0x72, 7 }, 301 | { /* 'X' ( 88) |11111100 */ 0xfc, 8 }, 302 | { /* 'Y' ( 89) |1110011 */ 0x73, 7 }, 303 | { /* 'Z' ( 90) |11111101 */ 0xfd, 8 }, 304 | { /* '[' ( 91) |11111111|11011 */ 0x1ffb, 13 }, 305 | { /* '\' ( 92) |11111111|11111110|000 */ 0x7fff0, 19 }, 306 | { /* '}' ( 93) |11111111|11100 */ 0x1ffc, 13 }, 307 | { /* '^' ( 94) |11111111|111100 */ 0x3ffc, 14 }, 308 | { /* '_' ( 95) |100010 */ 0x22, 6 }, 309 | { /* '`' ( 96) |11111111|1111101 */ 0x7ffd, 15 }, 310 | { /* 'a' ( 97) |00011 */ 0x3, 5 }, 311 | { /* 'b' ( 98) |100011 */ 0x23, 6 }, 312 | { /* 'c' ( 99) |00100 */ 0x4, 5 }, 313 | { /* 'd' (100) |100100 */ 0x24, 6 }, 314 | { /* 'e' (101) |00101 */ 0x5, 5 }, 315 | { /* 'f' (102) |100101 */ 0x25, 6 }, 316 | { /* 'g' (103) |100110 */ 0x26, 6 }, 317 | { /* 'h' (104) |100111 */ 0x27, 6 }, 318 | { /* 'i' (105) |00110 */ 0x6, 5 }, 319 | { /* 'j' (106) |1110100 */ 0x74, 7 }, 320 | { /* 'k' (107) |1110101 */ 0x75, 7 }, 321 | { /* 'l' (108) |101000 */ 0x28, 6 }, 322 | { /* 'm' (109) |101001 */ 0x29, 6 }, 323 | { /* 'n' (110) |101010 */ 0x2a, 6 }, 324 | { /* 'o' (111) |00111 */ 0x7, 5 }, 325 | { /* 'p' (112) |101011 */ 0x2b, 6 }, 326 | { /* 'q' (113) |1110110 */ 0x76, 7 }, 327 | { /* 'r' (114) |101100 */ 0x2c, 6 }, 328 | { /* 's' (115) |01000 */ 0x8, 5 }, 329 | { /* 't' (116) |01001 */ 0x9, 5 }, 330 | { /* 'u' (117) |101101 */ 0x2d, 6 }, 331 | { /* 'v' (118) |1110111 */ 0x77, 7 }, 332 | { /* 'w' (119) |1111000 */ 0x78, 7 }, 333 | { /* 'x' (120) |1111001 */ 0x79, 7 }, 334 | { /* 'y' (121) |1111010 */ 0x7a, 7 }, 335 | { /* 'z' (122) |1111011 */ 0x7b, 7 }, 336 | { /* '{' (123) |11111111|1111110 */ 0x7ffe, 15 }, 337 | { /* '|' (124) |11111111|100 */ 0x7fc, 11 }, 338 | { /* '}' (125) |11111111|111101 */ 0x3ffd, 14 }, 339 | { /* '~' (126) |11111111|11101 */ 0x1ffd, 13 }, 340 | { /* (127) |11111111|11111111|11111111|1100 */ 0xffffffc, 28 }, 341 | { /* (128) |11111111|11111110|0110 */ 0xfffe6, 20 }, 342 | { /* (129) |11111111|11111111|010010 */ 0x3fffd2, 22 }, 343 | { /* (130) |11111111|11111110|0111 */ 0xfffe7, 20 }, 344 | { /* (131) |11111111|11111110|1000 */ 0xfffe8, 20 }, 345 | { /* (132) |11111111|11111111|010011 */ 0x3fffd3, 22 }, 346 | { /* (133) |11111111|11111111|010100 */ 0x3fffd4, 22 }, 347 | { /* (134) |11111111|11111111|010101 */ 0x3fffd5, 22 }, 348 | { /* (135) |11111111|11111111|1011001 */ 0x7fffd9, 23 }, 349 | { /* (136) |11111111|11111111|010110 */ 0x3fffd6, 22 }, 350 | { /* (137) |11111111|11111111|1011010 */ 0x7fffda, 23 }, 351 | { /* (138) |11111111|11111111|1011011 */ 0x7fffdb, 23 }, 352 | { /* (139) |11111111|11111111|1011100 */ 0x7fffdc, 23 }, 353 | { /* (140) |11111111|11111111|1011101 */ 0x7fffdd, 23 }, 354 | { /* (141) |11111111|11111111|1011110 */ 0x7fffde, 23 }, 355 | { /* (142) |11111111|11111111|11101011 */ 0xffffeb, 24 }, 356 | { /* (143) |11111111|11111111|1011111 */ 0x7fffdf, 23 }, 357 | { /* (144) |11111111|11111111|11101100 */ 0xffffec, 24 }, 358 | { /* (145) |11111111|11111111|11101101 */ 0xffffed, 24 }, 359 | { /* (146) |11111111|11111111|010111 */ 0x3fffd7, 22 }, 360 | { /* (147) |11111111|11111111|1100000 */ 0x7fffe0, 23 }, 361 | { /* (148) |11111111|11111111|11101110 */ 0xffffee, 24 }, 362 | { /* (149) |11111111|11111111|1100001 */ 0x7fffe1, 23 }, 363 | { /* (150) |11111111|11111111|1100010 */ 0x7fffe2, 23 }, 364 | { /* (151) |11111111|11111111|1100011 */ 0x7fffe3, 23 }, 365 | { /* (152) |11111111|11111111|1100100 */ 0x7fffe4, 23 }, 366 | { /* (153) |11111111|11111110|11100 */ 0x1fffdc, 21 }, 367 | { /* (154) |11111111|11111111|011000 */ 0x3fffd8, 22 }, 368 | { /* (155) |11111111|11111111|1100101 */ 0x7fffe5, 23 }, 369 | { /* (156) |11111111|11111111|011001 */ 0x3fffd9, 22 }, 370 | { /* (157) |11111111|11111111|1100110 */ 0x7fffe6, 23 }, 371 | { /* (158) |11111111|11111111|1100111 */ 0x7fffe7, 23 }, 372 | { /* (159) |11111111|11111111|11101111 */ 0xffffef, 24 }, 373 | { /* (160) |11111111|11111111|011010 */ 0x3fffda, 22 }, 374 | { /* (161) |11111111|11111110|11101 */ 0x1fffdd, 21 }, 375 | { /* (162) |11111111|11111110|1001 */ 0xfffe9, 20 }, 376 | { /* (163) |11111111|11111111|011011 */ 0x3fffdb, 22 }, 377 | { /* (164) |11111111|11111111|011100 */ 0x3fffdc, 22 }, 378 | { /* (165) |11111111|11111111|1101000 */ 0x7fffe8, 23 }, 379 | { /* (166) |11111111|11111111|1101001 */ 0x7fffe9, 23 }, 380 | { /* (167) |11111111|11111110|11110 */ 0x1fffde, 21 }, 381 | { /* (168) |11111111|11111111|1101010 */ 0x7fffea, 23 }, 382 | { /* (169) |11111111|11111111|011101 */ 0x3fffdd, 22 }, 383 | { /* (170) |11111111|11111111|011110 */ 0x3fffde, 22 }, 384 | { /* (171) |11111111|11111111|11110000 */ 0xfffff0, 24 }, 385 | { /* (172) |11111111|11111110|11111 */ 0x1fffdf, 21 }, 386 | { /* (173) |11111111|11111111|011111 */ 0x3fffdf, 22 }, 387 | { /* (174) |11111111|11111111|1101011 */ 0x7fffeb, 23 }, 388 | { /* (175) |11111111|11111111|1101100 */ 0x7fffec, 23 }, 389 | { /* (176) |11111111|11111111|00000 */ 0x1fffe0, 21 }, 390 | { /* (177) |11111111|11111111|00001 */ 0x1fffe1, 21 }, 391 | { /* (178) |11111111|11111111|100000 */ 0x3fffe0, 22 }, 392 | { /* (179) |11111111|11111111|00010 */ 0x1fffe2, 21 }, 393 | { /* (180) |11111111|11111111|1101101 */ 0x7fffed, 23 }, 394 | { /* (181) |11111111|11111111|100001 */ 0x3fffe1, 22 }, 395 | { /* (182) |11111111|11111111|1101110 */ 0x7fffee, 23 }, 396 | { /* (183) |11111111|11111111|1101111 */ 0x7fffef, 23 }, 397 | { /* (184) |11111111|11111110|1010 */ 0xfffea, 20 }, 398 | { /* (185) |11111111|11111111|100010 */ 0x3fffe2, 22 }, 399 | { /* (186) |11111111|11111111|100011 */ 0x3fffe3, 22 }, 400 | { /* (187) |11111111|11111111|100100 */ 0x3fffe4, 22 }, 401 | { /* (188) |11111111|11111111|1110000 */ 0x7ffff0, 23 }, 402 | { /* (189) |11111111|11111111|100101 */ 0x3fffe5, 22 }, 403 | { /* (190) |11111111|11111111|100110 */ 0x3fffe6, 22 }, 404 | { /* (191) |11111111|11111111|1110001 */ 0x7ffff1, 23 }, 405 | { /* (192) |11111111|11111111|11111000|00 */ 0x3ffffe0, 26 }, 406 | { /* (193) |11111111|11111111|11111000|01 */ 0x3ffffe1, 26 }, 407 | { /* (194) |11111111|11111110|1011 */ 0xfffeb, 20 }, 408 | { /* (195) |11111111|11111110|001 */ 0x7fff1, 19 }, 409 | { /* (196) |11111111|11111111|100111 */ 0x3fffe7, 22 }, 410 | { /* (197) |11111111|11111111|1110010 */ 0x7ffff2, 23 }, 411 | { /* (198) |11111111|11111111|101000 */ 0x3fffe8, 22 }, 412 | { /* (199) |11111111|11111111|11110110|0 */ 0x1ffffec, 25 }, 413 | { /* (200) |11111111|11111111|11111000|10 */ 0x3ffffe2, 26 }, 414 | { /* (201) |11111111|11111111|11111000|11 */ 0x3ffffe3, 26 }, 415 | { /* (202) |11111111|11111111|11111001|00 */ 0x3ffffe4, 26 }, 416 | { /* (203) |11111111|11111111|11111011|110 */ 0x7ffffde, 27 }, 417 | { /* (204) |11111111|11111111|11111011|111 */ 0x7ffffdf, 27 }, 418 | { /* (205) |11111111|11111111|11111001|01 */ 0x3ffffe5, 26 }, 419 | { /* (206) |11111111|11111111|11110001 */ 0xfffff1, 24 }, 420 | { /* (207) |11111111|11111111|11110110|1 */ 0x1ffffed, 25 }, 421 | { /* (208) |11111111|11111110|010 */ 0x7fff2, 19 }, 422 | { /* (209) |11111111|11111111|00011 */ 0x1fffe3, 21 }, 423 | { /* (210) |11111111|11111111|11111001|10 */ 0x3ffffe6, 26 }, 424 | { /* (211) |11111111|11111111|11111100|000 */ 0x7ffffe0, 27 }, 425 | { /* (212) |11111111|11111111|11111100|001 */ 0x7ffffe1, 27 }, 426 | { /* (213) |11111111|11111111|11111001|11 */ 0x3ffffe7, 26 }, 427 | { /* (214) |11111111|11111111|11111100|010 */ 0x7ffffe2, 27 }, 428 | { /* (215) |11111111|11111111|11110010 */ 0xfffff2, 24 }, 429 | { /* (216) |11111111|11111111|00100 */ 0x1fffe4, 21 }, 430 | { /* (217) |11111111|11111111|00101 */ 0x1fffe5, 21 }, 431 | { /* (218) |11111111|11111111|11111010|00 */ 0x3ffffe8, 26 }, 432 | { /* (219) |11111111|11111111|11111010|01 */ 0x3ffffe9, 26 }, 433 | { /* (220) |11111111|11111111|11111111|1101 */ 0xffffffd, 28 }, 434 | { /* (221) |11111111|11111111|11111100|011 */ 0x7ffffe3, 27 }, 435 | { /* (222) |11111111|11111111|11111100|100 */ 0x7ffffe4, 27 }, 436 | { /* (223) |11111111|11111111|11111100|101 */ 0x7ffffe5, 27 }, 437 | { /* (224) |11111111|11111110|1100 */ 0xfffec, 20 }, 438 | { /* (225) |11111111|11111111|11110011 */ 0xfffff3, 24 }, 439 | { /* (226) |11111111|11111110|1101 */ 0xfffed, 20 }, 440 | { /* (227) |11111111|11111111|00110 */ 0x1fffe6, 21 }, 441 | { /* (228) |11111111|11111111|101001 */ 0x3fffe9, 22 }, 442 | { /* (229) |11111111|11111111|00111 */ 0x1fffe7, 21 }, 443 | { /* (230) |11111111|11111111|01000 */ 0x1fffe8, 21 }, 444 | { /* (231) |11111111|11111111|1110011 */ 0x7ffff3, 23 }, 445 | { /* (232) |11111111|11111111|101010 */ 0x3fffea, 22 }, 446 | { /* (233) |11111111|11111111|101011 */ 0x3fffeb, 22 }, 447 | { /* (234) |11111111|11111111|11110111|0 */ 0x1ffffee, 25 }, 448 | { /* (235) |11111111|11111111|11110111|1 */ 0x1ffffef, 25 }, 449 | { /* (236) |11111111|11111111|11110100 */ 0xfffff4, 24 }, 450 | { /* (237) |11111111|11111111|11110101 */ 0xfffff5, 24 }, 451 | { /* (238) |11111111|11111111|11111010|10 */ 0x3ffffea, 26 }, 452 | { /* (239) |11111111|11111111|1110100 */ 0x7ffff4, 23 }, 453 | { /* (240) |11111111|11111111|11111010|11 */ 0x3ffffeb, 26 }, 454 | { /* (241) |11111111|11111111|11111100|110 */ 0x7ffffe6, 27 }, 455 | { /* (242) |11111111|11111111|11111011|00 */ 0x3ffffec, 26 }, 456 | { /* (243) |11111111|11111111|11111011|01 */ 0x3ffffed, 26 }, 457 | { /* (244) |11111111|11111111|11111100|111 */ 0x7ffffe7, 27 }, 458 | { /* (245) |11111111|11111111|11111101|000 */ 0x7ffffe8, 27 }, 459 | { /* (246) |11111111|11111111|11111101|001 */ 0x7ffffe9, 27 }, 460 | { /* (247) |11111111|11111111|11111101|010 */ 0x7ffffea, 27 }, 461 | { /* (248) |11111111|11111111|11111101|011 */ 0x7ffffeb, 27 }, 462 | { /* (249) |11111111|11111111|11111111|1110 */ 0xffffffe, 28 }, 463 | { /* (250) |11111111|11111111|11111101|100 */ 0x7ffffec, 27 }, 464 | { /* (251) |11111111|11111111|11111101|101 */ 0x7ffffed, 27 }, 465 | { /* (252) |11111111|11111111|11111101|110 */ 0x7ffffee, 27 }, 466 | { /* (253) |11111111|11111111|11111101|111 */ 0x7ffffef, 27 }, 467 | { /* (254) |11111111|11111111|11111110|000 */ 0x7fffff0, 27 }, 468 | { /* (255) |11111111|11111111|11111011|10 */ 0x3ffffee, 26 }, 469 | { /* EOS (256) |11111111|11111111|11111111|111111 */ 0x3fffffff, 30 }, 470 | }; 471 | 472 | #endif /* HPACK_INTERNAL */ 473 | #endif /* HPACK_H */ 474 | -------------------------------------------------------------------------------- /hpack.md: -------------------------------------------------------------------------------- 1 | HPACK(3) - Library Functions Manual 2 | 3 | # NAME 4 | 5 | **hpack\_init**, 6 | **hpack\_table\_new**, 7 | **hpack\_table\_free**, 8 | **hpack\_table\_size**, 9 | **hpack\_decode**, 10 | **hpack\_encode**, 11 | **hpack\_header\_new**, 12 | **hpack\_header\_add**, 13 | **hpack\_header\_free**, 14 | **hpack\_headerblock\_new**, 15 | **hpack\_headerblock\_free**, 16 | **hpack\_huffman\_decode**, 17 | **hpack\_huffman\_decode\_str**, 18 | **hpack\_huffman\_encode** - HPACK header compression for HTTP/2 19 | 20 | # SYNOPSIS 21 | 22 | **#include <sys/queue.h>** 23 | **#include <hpack.h>** 24 | 25 | *int* 26 | **hpack\_init**(*void*); 27 | 28 | *struct hpack\_table \*‌* 29 | **hpack\_table\_new**(*size\_t max\_table\_size*); 30 | 31 | *void* 32 | **hpack\_table\_free**(*struct hpack\_table \*hpack*); 33 | 34 | *size\_t* 35 | **hpack\_table\_size**(*struct hpack\_table \*hpack*); 36 | 37 | *struct hpack\_headerblock \*‌* 38 | **hpack\_decode**(*unsigned char \*data*, *size\_t len*, *struct hpack\_table \*hpack*); 39 | 40 | *unsigned char \*‌* 41 | **hpack\_encode**(*struct hpack\_headerblock \*hdrs*, *size\_t \*encoded\_len*, *struct hpack\_table \*hpack*); 42 | 43 | *struct hpack\_header \*‌* 44 | **hpack\_header\_new**(*void*); 45 | 46 | *struct hpack\_header \*‌* 47 | **hpack\_header\_add**(*struct hpack\_headerblock \*hdrs*, *const char \*key*, *const char \*value*, *enum hpack\_header\_index index*); 48 | 49 | *void* 50 | **hpack\_header\_free**(*struct hpack\_header \*hdr*); 51 | 52 | *struct hpack\_headerblock \*‌* 53 | **hpack\_headerblock\_new**(*void*); 54 | 55 | *void* 56 | **hpack\_headerblock\_free**(*struct hpack\_headerblock \*hdrs*); 57 | 58 | *unsigned char \*‌* 59 | **hpack\_huffman\_decode**(*unsigned char \*data*, *size\_t len*, *size\_t \*decoded\_len*); 60 | 61 | *char \*‌* 62 | **hpack\_huffman\_decode\_str**(*unsigned char \*data*, *size\_t len*); 63 | 64 | *unsigned char \*‌* 65 | **hpack\_huffman\_encode**(*unsigned char \*data*, *size\_t len*, *size\_t \*encoded\_len*); 66 | 67 | # DESCRIPTION 68 | 69 | The 70 | **hpack** 71 | family of functions provides an API to decode and encode HPACK header 72 | compression for HTTP/2. 73 | 74 | The 75 | *hpack\_header* 76 | and 77 | *hpack\_headerblock* 78 | structures are defined as 79 | <*sys/queue.h*> 80 | tail queue element and head of the following types: 81 | 82 | struct hpack_header { 83 | char *hdr_name; 84 | char *hdr_value; 85 | enum hpack_header_index hdr_index; 86 | TAILQ_ENTRY(hpack_header) hdr_entry; 87 | }; 88 | TAILQ_HEAD(hpack_headerblock, hpack_header); 89 | 90 | The 91 | *index* 92 | argument can be specified as one of the following values: 93 | `HPACK_INDEX`, 94 | `HPACK_NO_INDEX`, 95 | or 96 | `HPACK_NEVER_INDEX` 97 | to add the header to the index of the dynamic HPACK table, 98 | to exclude the header from the index, 99 | or to exclude the header from the index and to mark it as sensitive to 100 | never include it in the index. 101 | 102 | # RETURN VALUES 103 | 104 | **hpack\_init**() 105 | returns 0 on success or -1 on error. 106 | 107 | **hpack\_table\_size**() 108 | returns the current size of the dynamic HPACK table or 0 if it is empty. 109 | 110 | **hpack\_table\_new**(), 111 | **hpack\_decode**(), 112 | **hpack\_encode**(), 113 | **hpack\_header\_new**(), 114 | **hpack\_header\_add**(), 115 | **hpack\_headerblock\_new**(), 116 | **hpack\_huffman\_decode**(), 117 | **hpack\_huffman\_decode\_str**(), 118 | and 119 | **hpack\_huffman\_encode**() 120 | return 121 | `NULL` 122 | on error or an out-of-memory condition. 123 | 124 | # SEE ALSO 125 | 126 | queue(3), 127 | relayd(8) 128 | 129 | # STANDARDS 130 | 131 | R. Peon, 132 | H. Ruellan, 133 | *HPACK: Header Compression for HTTP/2*, 134 | RFC 7541, 135 | May 2015. 136 | 137 | # HISTORY 138 | 139 | The 140 | **hpack** 141 | API first appeared on 142 | [https://github.com/reyk/hpack](https://github.com/reyk/hpack). 143 | 144 | # AUTHORS 145 | 146 | Reyk Floeter <[reyk@openbsd.org](mailto:reyk@openbsd.org)> 147 | 148 | OpenBSD 6.5 - May 23, 2019 149 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | .PATH: ${.CURDIR}/.. 2 | 3 | LIB= hpack 4 | MAN= hpack.3 5 | 6 | .include 7 | -------------------------------------------------------------------------------- /lib/shlib_version: -------------------------------------------------------------------------------- 1 | major=0 2 | minor=1 3 | -------------------------------------------------------------------------------- /regress/Makefile: -------------------------------------------------------------------------------- 1 | HPACKSRCDIR= ${.CURDIR}/.. 2 | HPACKTESTDIR+= ${.CURDIR}/hpack-test-samples 3 | HPACKTESTDIR+= ${.CURDIR}/hpack-test-case 4 | 5 | .PATH: ${HPACKSRCDIR} 6 | 7 | PROG= hpacktest 8 | SRCS+= main.c jsmn.c json.c 9 | CFLAGS+= -DJSMN_PARENT_LINKS 10 | 11 | REGRESS_TARGETS?= test 12 | 13 | test: ${PROG} 14 | ./${PROG} -v ${HPACKTESTDIR} 15 | 16 | .include 17 | -------------------------------------------------------------------------------- /regress/extern.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD$ */ 2 | 3 | /* 4 | * Copyright (c) 2019 Reyk Floeter 5 | * Copyright (c) 2016 Kristaps Dzonsons 6 | * 7 | * Permission to use, copy, modify, and distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | */ 19 | 20 | #include "jsmn.h" 21 | 22 | #ifndef EXTERN_H 23 | #define EXTERN_H 24 | 25 | struct jsmnp; 26 | 27 | /* 28 | * A node in the JSMN parse tree. 29 | * Each of this corresponds to an object in the original JSMN token 30 | * list, although the contents have been extracted properly. 31 | */ 32 | struct jsmnn { 33 | struct parse *p; /* parser object */ 34 | union { 35 | char *str; /* JSMN_PRIMITIVE, JSMN_STRING */ 36 | struct jsmnp *obj; /* JSMN_OBJECT */ 37 | struct jsmnn **array; /* JSMN_ARRAY */ 38 | } d; 39 | size_t fields; /* entries in "d" */ 40 | jsmntype_t type; /* type of node */ 41 | }; 42 | 43 | /* 44 | * Objects consist of node pairs: the left-hand side (before the colon) 45 | * and the right-hand side---the data. 46 | */ 47 | struct jsmnp { 48 | struct jsmnn *lhs; /* left of colon */ 49 | struct jsmnn *rhs; /* right of colon */ 50 | }; 51 | 52 | /* JSON parsing routines */ 53 | struct jsmnn *json_parse(const char *, size_t); 54 | void json_free(struct jsmnn *); 55 | struct jsmnn *json_getarrayobj(struct jsmnn *); 56 | struct jsmnn *json_getarray(struct jsmnn *, const char *); 57 | struct jsmnn *json_getobj(struct jsmnn *, const char *); 58 | char *json_getstr(struct jsmnn *, const char *); 59 | 60 | #endif /* EXTERN_H */ 61 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/headers/headers_00.txt: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host: example.com 3 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/headers/headers_01.txt: -------------------------------------------------------------------------------- 1 | :method: GET 2 | :scheme: http 3 | :authority: yahoo.co.jp 4 | :path: / 5 | user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0 6 | accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 7 | accept-language: en-US,en;q=0.5 8 | accept-encoding: gzip, deflate 9 | connection: keep-alive 10 | cookie: B=76j09a189a6h4&b=3&s=0b 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_00.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f88f439ce75c875fa570084b958d33f8163 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8cf1e3c2fe8739ceb90ebf4aff0084b958d33f8163 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87eabfa35332fd2b0084b958d33f9b60d48e62a1849eb611589825353141e63ad52160b206c4f2f5d537 4 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_01.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b8824e5a4b849d29ad1f0088b83b5339ec327d7f882f91d35d055c87a70084b958d33f81630085b9495339e483c5837f0087b505b161cc5a93879eb193aac92a13008421cfd4c587f3e7cf9f3e7c870086f2b4e5a283ff84f07b2893 2 | 0085b8824e5a4b849d29ad1f0088b83b5339ec327d7f882f91d35d055c87a70084b958d33f81630085b9495339e483c5837f0087b505b161cc5a93879eb193aac92a13008421cfd4c587f3e7cf9f3e7c8b 3 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_02.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f871d23f67a9721e90084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fab60d48e62a18c4c002c4d51d88ca321ea62e94643d5babb0c92adc372c00af17168017c0cb6cb712f5d537f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fad60d48e62a18c4c002c795a83907415821e9a4f5309b07522b1d85a92b566f25a178b8b2f38fb4269c6a25e634b0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fbf60d48e62a18c4c002c1a9982260e99cb63121903424b62d61683165619001621e8b69a9840ea93d2d61683165899003cbadaf171680071e7da7c312f5d537f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8bf1e3c2e3a47ecf52e43d3f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fad60d48e62a18c4c002c795a83907415821e9a4f5309b07522b1d85a92b566f25a178b885f109969c75b89798d2f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fc160d48e62a18c4c002c1a9982261139ca86103a0a888bdcb5250c0431547eec040c82284842a107b0c546bdbab46a8b172b0d34e95e2e2d000e09c7db044bcc697f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fac60d48e62a18c4c002c436a4f49d26ee562c3a4e862fdb60c85a287000882202f1710be2101a75c6a25fa57370087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91996293cae6a473150b0e91fb3d4b90f4ff0084b958d33fb060d48e62a18c4c002c5a662838e4c9548620d27b10c5071c992a90c41a4f62d40ec98abc5c42f882fb6d3c089798d2ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f293cae6a473150b0e91fb3d4b90f4f0084b958d33f9a60d48e62a18c8c341c7fab69beb6ee19d78b7670b2dc4bf4ae6f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e171d23f67a9721e963f 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_03.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f878c6692d5c87a7f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f878c6692d5c87a7f0084b958d33f896251f7310f52e621ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8af1e3c2f18cd25ab90f4f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8af1e3c2f18cd25ab90f4f0084b958d33f9060d4ccc4633496c48f541e6385798d2f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e178c6692d5c87a58f008421cfd4c5a4bb0e4bfc325f82eb8165c86f04182ee0042f61bd7c417305d71abcd5e0c2ddeb9871401f 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8af1e3c2f18cd25ab90f4f0084b958d33f91608324e5626a0f18e860d4ccc4c85e634b0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e178c6692d5c87a58f008421cfd4c5a4bb0e4bfc325f82eb8165c86f04182ee0042f61bd7c417305d71abcd5e0c2ddeb9871401f 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8a40578e442469311721e90084b958d33f9f62c63c78f0c10649cac4d41e31d0c7443091d53583a560aecaed102b817e880087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e178c6692d5c87a58f 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8a40578e442469311721e90084b958d33f9962c63c78f0c10649cac4d41e31d0c7443139e92ac15de5fa230087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e178c6692d5c87a58f 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8a40578e442469311721e90084b958d33f9762c63c78f0c10649cac5a82d8c744316ac15d95da5fa230087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e178c6692d5c87a58f 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8a40578e442469311721e90084b958d33f9162c63c78f0c1a999832c15c0b817aea9bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e178c6692d5c87a58f 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8af1e3c2f18cd25ab90f4f0084b958d33f896251f7310f52e621ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff008421cfd4c5a4bb0e4bfc325f82eb8165c86f04182ee0042f61bd7c417305d71abcd5e0c2ddeb9871401f 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_07.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9a62c45845eb9eb63b898f51b1631891a72e9f16e45b8685e634bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f5cd8b18b5e342cf5fc8dee615c88470087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f5918b18ed0e9e3bd179b14b5ae44230087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9a62c45845eb9eb63b898f4962c630fe8f466ed0ed9af38bd754df0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f5fac58c74a335f3fe05beb8f12fd110087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f5a98b188b46d1d95ce4bd93b2e44230087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f5ad8b18bdb7a9afdfe5be40dabf4470087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9a62c45845eb9eb63b898f5f8c79636767338671ecb39d8bd754df0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9ab9d29aee30c21234988b8faaf2c6492a5ea2a58b116117ae7ad8ee263d6462c63b43a78ef45e6c52d6b9108 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f5a58b18c03b23e478a9bfc165fa23f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9929d29aee30c78f1e1794642c673f55c87a58f 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8e4246931171f55e58c9254bd454ff0084b958d33f9962c45845eb9eb63b898f4eb1e587fa25d3f1930bbed95ebaa60087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9ab9d29aee30c21234988b8faaf2c6492a5ea2a58b116117ae7ad8ee263d6a62c622d1b47657392f64ecb9108 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_10.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f85a5152e43d30084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f89f1e3c2f4a2a5c87a7f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8a1c880af4a072217a8a9f0084b958d33f9062834760ecf4c5761a92c9521798d2ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8c21e85d09e8ba16a5152e43d30084b958d33f8a62bb0d4964a90bcc697f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8c8e8b574248ba16a5152e43d30084b958d33f94606863c146cb0660b52d6a18a07e1865f5e634bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8c21e85d09e8ba16a5152e43d30084b958d33f8a62bb0d4964a90bcc697f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8c21e85d0922e85a9454b90f4f0084b958d33f95623b1841183312cac0e424e7310a88a634a25e634b0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d21e85d098c005d0b528a9721e90084b958d33f9c60cc3c061b66f4379c8420bae09a79c7857b08841ba26a17c4bcc6970087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d21e85d098c015d0b528a9721e90084b958d33f9e60cc600310b9799089c65bc18410b2db6e38f5e7840c175b65a657e95cdf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d21e85d098c005d0b528a9721e90084b958d33fa060cc5dbac5d0e1702fc2186fb57da86172e81c69ebb7eeddbd7f060bebf4ae6f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c78f1e17a5152e43d2c7f 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_11.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f88abd24d4950b90f4f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8b4af59cd526c3d142e43d3f0084b958d33f8d6359cd52769e8a18df60c9d58f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99f9d29aee30c78f1e178e322e43af6f562a2f84311da8354542161002ebc0003008421cfd4c5aad7b63b60c1eff6492d9e6edf6a6bdb31e0bb76ec30e1d1543f6a6bda93357afbeeb781a72f4382182eff 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8b4af59cd526c3d142e43d3f0084b958d33f8d6359cd52769e8a18df60c9d58f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99f9d29aee30c78f1e178e322e43af6f562a2f84311da8354542161002ebc0003008421cfd4c5aad7b63b60c1eff6492d9e6edf6a6bdb31e0bb76ec30e1d1543f6a6bda93357afbeeb781a72f4382182eff 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33fb062b193a8e62a182210c536d09352590c3623b6a9282a18aec3f42912860400898c7af39bb96f9631a4b8682f95c8847f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33fa663a2181d75b043d349ea61141a42a273f860b4c659242c9ba8348544e7f176d351216c5fa23f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33fa5608843005c2c209614b5308a0d215139fc3149e4b682a18450690d54d8874505b3d2e4423f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33fae60727960d48e62a1886fee6190b0d38c0e45d90b4e38f31a79ef8b45dd1164d78f5698b3e0c3be2d444842bf4ae60087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33faf62b193a8e62a18e88629b6849a92c861b11db5494150c5761fa148943020044c63d79cddcb7cb18d25c3417cafd11f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33fb162b193a8e62a18e88629b6849a92c861b120d236309a8a7726c357aec3d27604008a22d05224c7aa294d45284d86ad7e880087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8f9ac1d739888797abd24d4950b90f4f0084b958d33fa962b193a8e62a18e8860b4148931ea43020044c4858c692a18ee690a7426c356c4a6a29426c356b91080087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9919d29aee30c78f1e17abd24d4950b90f4b1008421cfd4c59cdba325f8000765004001082e38069d8ca57c00147f6a0e4f24440b7f 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_12.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f89acd524b615095c87a70084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e4602e34c842079c65d699132eb218afcffbba5c929228d7e95cdf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e4602e05c65d03ad01f75b79979b6e2dda7a5fdba331628d7e95cd0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e4604eb2dbecbad3807990084e09a8b0de3e0ebf88bd146bf4ae6f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9e62dae838e461b13e175971a65a13cfb2e38cc5d93ae9cb375f3146bf4ae60087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e4602171f6c4f882db4d0196df00a2cdeb7f2355ee98a35fa5737f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e4604f32d34db2e804e3aebad09b1450a5377471977c51afd2b9bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e4604cba1684eb2e36fbe0136f09d8ad96fe0c726d2c51afd2b9bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9f62dae838e46042682fb4f3ceb8e3edb2cb2f062e1769338dbf3451afd2b9bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f94a4b2186b10649cab50902f59aa496c2a12b90f4f0084b958d33f9e62dae838e4604eb416dc71f700cb8d3afbe07628425f73548e9146bf4ae60087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d98f9d29aee30c566a925b0a84ae43d2c7008421cfd4c5ff0a8ab35492d8542624150883f92e5f59f455bb47a9a7c9b8cdb24ab068f5da63bf828d7e860d01e92787d8dc04f37bbfa279d29978697b7fe02f93a89e85fcb677d9ad39f8f1cc06939d0de844bf9a1f1fb05e671e6312bcda58cbef70d8f566cb33191e3369e6ce8374dd97de8b323da039b4b11e9bfbf786cd8703dc3d329d9c21a59c1d6f43041fcf 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_16.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8c2d4bf8375356590c35cf64df0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff008421cfd4c5ff3d216a4d83a2a3a4c42c51da4ea54c01fb5094189d5360c9d4d54cb20a8418f5405cbd4ee64370260a5c7cb3ec9463ebb28cb29b3fa7e8dd3e9d7f6a52590c3e46ea65ed416c5e3b49d4a955984be52b8ec4989417094b246327559360c9d4d54d0040ab30a6c193afda9496430f91ba997b505b17349060d0f33d11d07db5fbc9a33f8bbbcd9b0b23ce636fcc5f052fbfb5292c861f237532f6a0b62f1da4ea54aacc25f295c7624c4a0b84a5923193aac7ad263d4881e55985139fc7 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8c2d4bf8375356590c35cf64df0084b958d33f8b63c1ba998d0335516b1cc50087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff008421cfd4c5ff3d216a4d83a2a3a4c42c51da4ea54c01fb5094189d5360c9d4d54cb20a8418f5405cbd4ee64370260a5c7cb3ec9463ebb28cb29b3fa7e8dd3e9d7f6a52590c3e46ea65ed416c5e3b49d4a955984be52b8ec4989417094b246327559360c9d4d54d0040ab30a6c193afda9496430f91ba997b505b17349060d0f33d11d07db5fbc9a33f8bbbcd9b0b23ce636fcc5f052fbfb5292c861f237532f6a0b62f1da4ea54aacc25f295c7624c4a0b84a5923193aac7ad263d4881e55985139fc7 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d8cc942fe0dd4d496430d73d9370084b958d33f9360b52fe0dd4d596430d73d933141c722f5cf5f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96e4593e94642a6a225410022502edc6c5700d298b46ff 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d8cc942fe0dd4d496430d73d9370084b958d33f9360b52fe0dd4d596430d73d933141c722f5cf5f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96df3dbf4a002a693f75040089403f71966e09d53168df 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d8cc942fe0dd4d496430d73d9370084b958d33f9360b52fe0dd4d596430d73d933141c722f5cf5f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96dc34fd280654d27eea0801128115c6d9b82754c5a37f 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d8cc942fe0dd4d496430d73d9370084b958d33f9360b52fe0dd4d596430d73d933141c722f5cf5f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96e4593e94642a6a225410022502edc6c5700d298b46ff 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d8cc942fe0dd4d496430d73d9370084b958d33f9360b52fe0dd4d596430d73d933141c722f5cf5f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96df3dbf4a002a693f75040089403f71966e09d53168df 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8fb6ba0e3917f06ea6a4b2186b9ec9bf0084b958d33f9e63c1ba9ab2c861b05a9823041b198752673583ee388961ebacb22f5d537f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96c361be940094d27eea0801128266e34e5c6df53168df008934ab547a8ab52349279713cf4724629646cad8da95d13a295b7a524607991ba50f 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8fb6ba0e3917f06ea6a4b2186b9ec9bf0084b958d33fcf63c1ba9ab2c861b043d349ea43099eda636246241317c7510d54d14c6b28887d07524712a278961ebacb22a27d7e95ccc3a2afcad7c7510d54d14c6b28887d07524712a278961ebacb22a27d7e95cd0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96df697e94640a6a225410022502edc65db816d4c5a37f008934ab547a8ab52349279770af48db924afc6565b69f6a36a47e50146e88b2046c97 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8d8cc942fe0dd4d496430d73d9370084b958d33f9360b52fe0dd4d596430d73d933141c722f5cf5f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d99c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f008c34ab52790d298b22c835442f96dc34fd280654d27eea0801128115c6d9b82754c5a37f 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_18.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f439ce75c87a7f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f88917f46a665c87a7f0084b958d33fb062791824eed45f0861d8bc1eca246021033101d0022a86988b416b9c75262453444179f7893f4582f3ef127a17e95cdf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f891dabfa1ce73ae43d3f0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff008421cfd4c593bb03548aced6b6f3e36c0efc47033f08803dff 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f88917f46a665c87a7f0084b958d33f88629331ebc0d7e88f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8cf56997f439ce71d6642e43d30084b958d33f856087a633ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f9341496d855876ae6a6cf07b2893c1a42ae43d3f0084b958d33f8860931968cd5314ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f9024e3b12bca6a87510abfa1ce73ae43d30084b958d33fa960d521365b496a4b015c0c2ade01f9e8760938ec4fdd83aa62c0dc8c1a91cc5fb41bd9600baff97def0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f008421cfd4c5c8bb03548aced6b6f3e36c0efc47033f08803dfed44150831ea89091d898926a4b00596c2fb4e89d6c2e03ed4eb177320c9803f6a576a278926a4b12123b1300596c2fb4e89f6c2e03 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f9024e3b12bca6a87510abfa1ce73ae43d30084b958d33fa960d521365b496a4b015c0c2ade019ec91824e3b13f760ea98b0372306a47317ed06f65802ebfe5f7bf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f008421cfd4c5c8bb03548aced6b6f3e36c0efc47033f08803dfed44150831ea89091d898926a4b00596c2fb4e89d6c2e03ed4eb177320c9803f6a576a278926a4b12123b1300596c2fb4e89f6c2e03 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f9024e3b12bca6a87510abfa1ce73ae43d30084b958d33fa960d521365b496a4b015c0c0ed92d44907960938ec4fdd83aa62c0dc8c1a91cc5fb41bd9600baff97de0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f008421cfd4c5c8bb03548aced6b6f3e36c0efc47033f08803dfed44150831ea89091d898926a4b00596c2fb4e89d6c2e03ed4eb177320c9803f6a576a278926a4b12123b1300596c2fb4e89f6c2e03 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f91252b8ed5fd0e739d73f72d89b6c2ae43d30084b958d33f8a63a2229681a620c4063f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad383f963e7008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9939d29aee30c0ed5fd0e739d721e963fcae0b51f 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/hex/go-hpack_19.hpacktest: -------------------------------------------------------------------------------- 1 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f43aa42f95ecb70084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 2 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8bf1e3c2fe875485f2bd96ff0084b958d33f81630087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 3 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8bf438d0bfa1d5217caf65bf0084b958d33fd06087b6a4b1c6af1133ef08a4eba9a00002fd9e87b3621b79b5e61129d72e82f3af50bde207784baad84b2fee48663c22cd09452ebd5ab5bee7aecd4630cb7f362d97833d17f8976697b14bc6f85d2bbf0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58008421cfd4c5994c15fda9e875485f369a481c682069b65d742cb617da7da6c3 4 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f8bf438d0bfa1d5217caf65bf0084b958d33fce6087b6a4b1c6af11334ca97bc766800003f67a1ecd886de6d6e7aecd4630cb7f34f45fe25d9a5ec52f1be1746cc1d89aaa69fcc2253ae5d048f60e6fcfde53738663c22cd0e8d0e399097dde4cff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58008421cfd4c5994c15fda9e875485f369a481c682069b65d742cb617da7da6c3 5 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f43aa42f95d09f0084b958d33f9d6282cc762262bbf6bfab943b335d020595fc87e99ab36e8b04e75cc43f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad3b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff 6 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f43aa42f95d09f0084b958d33f9663c78f0c05765b7d8f1e3c30663d0ea90be595ebaa6f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58 7 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f43aa42f95d09f0084b958d33f906293d920d6a0f31d833141e63af5d5370087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58 8 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f89a48bfa1d5217caf65b0084b958d33f8a63c0d249d874426da6ff0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58008421cfd4c5994c15fda9e875485f369a481c682069b65d742cb617da7da6c3 9 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f43aa42f95d09f0084b958d33fa563c78f0c05765b7d8f1e3c3158e62a1690a8ea93d6c78f1e162210c45e3c78588842e4423f0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad38e497ca582211f5f2c7cfdf6800b87008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58 10 | 0085b9495339e483c5837f0085b8824e5a4b839d29af0088b83b5339ec327d7f87f43aa42f95d09f0084b958d33f9e63c78f0c44c4563b5d6b46b4f98f7e39bd62e7e8192eb3e28eb51d7aea9b0087b505b161cc5a93bcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c1008419085ad39a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176f008b19085ad2b503aa6b47317f8b2d4b70ddf45abefb4005db008b19085ad2b16a21e435537f8a9bd9abfa5242cb40d25f008721eaa8a4498f5788ea52d6b0e83772ff0085b0b296c2d9909d29aee30c78f1e17f43aa42f95ecb58 11 | -------------------------------------------------------------------------------- /regress/hpack-test-samples/raw/go-hpack_00.hpackraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reyk/hpack/1803b3f5159b162174f80c5e9851dae580b8466e/regress/hpack-test-samples/raw/go-hpack_00.hpackraw -------------------------------------------------------------------------------- /regress/hpack-test-samples/raw/go-hpack_01.hpackraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reyk/hpack/1803b3f5159b162174f80c5e9851dae580b8466e/regress/hpack-test-samples/raw/go-hpack_01.hpackraw -------------------------------------------------------------------------------- /regress/hpack-test-samples/raw/go-hpack_02.hpackraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reyk/hpack/1803b3f5159b162174f80c5e9851dae580b8466e/regress/hpack-test-samples/raw/go-hpack_02.hpackraw -------------------------------------------------------------------------------- /regress/hpack-test-samples/raw/go-hpack_05.hpackraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reyk/hpack/1803b3f5159b162174f80c5e9851dae580b8466e/regress/hpack-test-samples/raw/go-hpack_05.hpackraw -------------------------------------------------------------------------------- /regress/hpack-test-samples/raw/go-hpack_16.hpackraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reyk/hpack/1803b3f5159b162174f80c5e9851dae580b8466e/regress/hpack-test-samples/raw/go-hpack_16.hpackraw -------------------------------------------------------------------------------- /regress/hpack-test-samples/raw/go-hpack_22.hpackraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reyk/hpack/1803b3f5159b162174f80c5e9851dae580b8466e/regress/hpack-test-samples/raw/go-hpack_22.hpackraw -------------------------------------------------------------------------------- /regress/jsmn.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010 Serge A. Zaitsev 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE.* 21 | */ 22 | #include "jsmn.h" 23 | 24 | /** 25 | * Allocates a fresh unused token from the token pull. 26 | */ 27 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 28 | jsmntok_t *tokens, size_t num_tokens) { 29 | jsmntok_t *tok; 30 | if (parser->toknext >= num_tokens) { 31 | return NULL; 32 | } 33 | tok = &tokens[parser->toknext++]; 34 | tok->start = tok->end = -1; 35 | tok->size = 0; 36 | #ifdef JSMN_PARENT_LINKS 37 | tok->parent = -1; 38 | #endif 39 | return tok; 40 | } 41 | 42 | /** 43 | * Fills token type and boundaries. 44 | */ 45 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 46 | int start, int end) { 47 | token->type = type; 48 | token->start = start; 49 | token->end = end; 50 | token->size = 0; 51 | } 52 | 53 | /** 54 | * Fills next available token with JSON primitive. 55 | */ 56 | static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 57 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 58 | jsmntok_t *token; 59 | int start; 60 | 61 | start = parser->pos; 62 | 63 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 64 | switch (js[parser->pos]) { 65 | #ifndef JSMN_STRICT 66 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 67 | case ':': 68 | #endif 69 | case '\t' : case '\r' : case '\n' : case ' ' : 70 | case ',' : case ']' : case '}' : 71 | goto found; 72 | } 73 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 74 | parser->pos = start; 75 | return JSMN_ERROR_INVAL; 76 | } 77 | } 78 | #ifdef JSMN_STRICT 79 | /* In strict mode primitive must be followed by a comma/object/array */ 80 | parser->pos = start; 81 | return JSMN_ERROR_PART; 82 | #endif 83 | 84 | found: 85 | if (tokens == NULL) { 86 | parser->pos--; 87 | return 0; 88 | } 89 | token = jsmn_alloc_token(parser, tokens, num_tokens); 90 | if (token == NULL) { 91 | parser->pos = start; 92 | return JSMN_ERROR_NOMEM; 93 | } 94 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 95 | #ifdef JSMN_PARENT_LINKS 96 | token->parent = parser->toksuper; 97 | #endif 98 | parser->pos--; 99 | return 0; 100 | } 101 | 102 | /** 103 | * Fills next token with JSON string. 104 | */ 105 | static int jsmn_parse_string(jsmn_parser *parser, const char *js, 106 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 107 | jsmntok_t *token; 108 | 109 | int start = parser->pos; 110 | 111 | parser->pos++; 112 | 113 | /* Skip starting quote */ 114 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 115 | char c = js[parser->pos]; 116 | 117 | /* Quote: end of string */ 118 | if (c == '\"') { 119 | if (tokens == NULL) { 120 | return 0; 121 | } 122 | token = jsmn_alloc_token(parser, tokens, num_tokens); 123 | if (token == NULL) { 124 | parser->pos = start; 125 | return JSMN_ERROR_NOMEM; 126 | } 127 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 128 | #ifdef JSMN_PARENT_LINKS 129 | token->parent = parser->toksuper; 130 | #endif 131 | return 0; 132 | } 133 | 134 | /* Backslash: Quoted symbol expected */ 135 | if (c == '\\' && parser->pos + 1 < len) { 136 | int i; 137 | parser->pos++; 138 | switch (js[parser->pos]) { 139 | /* Allowed escaped symbols */ 140 | case '\"': case '/' : case '\\' : case 'b' : 141 | case 'f' : case 'r' : case 'n' : case 't' : 142 | break; 143 | /* Allows escaped symbol \uXXXX */ 144 | case 'u': 145 | parser->pos++; 146 | for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 147 | /* If it isn't a hex character we have an error */ 148 | if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 149 | (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 150 | (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 151 | parser->pos = start; 152 | return JSMN_ERROR_INVAL; 153 | } 154 | parser->pos++; 155 | } 156 | parser->pos--; 157 | break; 158 | /* Unexpected symbol */ 159 | default: 160 | parser->pos = start; 161 | return JSMN_ERROR_INVAL; 162 | } 163 | } 164 | } 165 | parser->pos = start; 166 | return JSMN_ERROR_PART; 167 | } 168 | 169 | /** 170 | * Parse JSON string and fill tokens. 171 | */ 172 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 173 | jsmntok_t *tokens, unsigned int num_tokens) { 174 | int r; 175 | int i; 176 | jsmntok_t *token; 177 | int count = parser->toknext; 178 | 179 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 180 | char c; 181 | jsmntype_t type; 182 | 183 | c = js[parser->pos]; 184 | switch (c) { 185 | case '{': case '[': 186 | count++; 187 | if (tokens == NULL) { 188 | break; 189 | } 190 | token = jsmn_alloc_token(parser, tokens, num_tokens); 191 | if (token == NULL) 192 | return JSMN_ERROR_NOMEM; 193 | if (parser->toksuper != -1) { 194 | tokens[parser->toksuper].size++; 195 | #ifdef JSMN_PARENT_LINKS 196 | token->parent = parser->toksuper; 197 | #endif 198 | } 199 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 200 | token->start = parser->pos; 201 | parser->toksuper = parser->toknext - 1; 202 | break; 203 | case '}': case ']': 204 | if (tokens == NULL) 205 | break; 206 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 207 | #ifdef JSMN_PARENT_LINKS 208 | if (parser->toknext < 1) { 209 | return JSMN_ERROR_INVAL; 210 | } 211 | token = &tokens[parser->toknext - 1]; 212 | for (;;) { 213 | if (token->start != -1 && token->end == -1) { 214 | if (token->type != type) { 215 | return JSMN_ERROR_INVAL; 216 | } 217 | token->end = parser->pos + 1; 218 | parser->toksuper = token->parent; 219 | break; 220 | } 221 | if (token->parent == -1) { 222 | break; 223 | } 224 | token = &tokens[token->parent]; 225 | } 226 | #else 227 | for (i = parser->toknext - 1; i >= 0; i--) { 228 | token = &tokens[i]; 229 | if (token->start != -1 && token->end == -1) { 230 | if (token->type != type) { 231 | return JSMN_ERROR_INVAL; 232 | } 233 | parser->toksuper = -1; 234 | token->end = parser->pos + 1; 235 | break; 236 | } 237 | } 238 | /* Error if unmatched closing bracket */ 239 | if (i == -1) return JSMN_ERROR_INVAL; 240 | for (; i >= 0; i--) { 241 | token = &tokens[i]; 242 | if (token->start != -1 && token->end == -1) { 243 | parser->toksuper = i; 244 | break; 245 | } 246 | } 247 | #endif 248 | break; 249 | case '\"': 250 | r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 251 | if (r < 0) return r; 252 | count++; 253 | if (parser->toksuper != -1 && tokens != NULL) 254 | tokens[parser->toksuper].size++; 255 | break; 256 | case '\t' : case '\r' : case '\n' : case ' ': 257 | break; 258 | case ':': 259 | parser->toksuper = parser->toknext - 1; 260 | break; 261 | case ',': 262 | if (tokens != NULL && parser->toksuper != -1 && 263 | tokens[parser->toksuper].type != JSMN_ARRAY && 264 | tokens[parser->toksuper].type != JSMN_OBJECT) { 265 | #ifdef JSMN_PARENT_LINKS 266 | parser->toksuper = tokens[parser->toksuper].parent; 267 | #else 268 | for (i = parser->toknext - 1; i >= 0; i--) { 269 | if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 270 | if (tokens[i].start != -1 && tokens[i].end == -1) { 271 | parser->toksuper = i; 272 | break; 273 | } 274 | } 275 | } 276 | #endif 277 | } 278 | break; 279 | #ifdef JSMN_STRICT 280 | /* In strict mode primitives are: numbers and booleans */ 281 | case '-': case '0': case '1' : case '2': case '3' : case '4': 282 | case '5': case '6': case '7' : case '8': case '9': 283 | case 't': case 'f': case 'n' : 284 | /* And they must not be keys of the object */ 285 | if (tokens != NULL && parser->toksuper != -1) { 286 | jsmntok_t *t = &tokens[parser->toksuper]; 287 | if (t->type == JSMN_OBJECT || 288 | (t->type == JSMN_STRING && t->size != 0)) { 289 | return JSMN_ERROR_INVAL; 290 | } 291 | } 292 | #else 293 | /* In non-strict mode every unquoted value is a primitive */ 294 | default: 295 | #endif 296 | r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 297 | if (r < 0) return r; 298 | count++; 299 | if (parser->toksuper != -1 && tokens != NULL) 300 | tokens[parser->toksuper].size++; 301 | break; 302 | 303 | #ifdef JSMN_STRICT 304 | /* Unexpected char in strict mode */ 305 | default: 306 | return JSMN_ERROR_INVAL; 307 | #endif 308 | } 309 | } 310 | 311 | if (tokens != NULL) { 312 | for (i = parser->toknext - 1; i >= 0; i--) { 313 | /* Unmatched opened object or array */ 314 | if (tokens[i].start != -1 && tokens[i].end == -1) { 315 | return JSMN_ERROR_PART; 316 | } 317 | } 318 | } 319 | 320 | return count; 321 | } 322 | 323 | /** 324 | * Creates a new parser based over a given buffer with an array of tokens 325 | * available. 326 | */ 327 | void jsmn_init(jsmn_parser *parser) { 328 | parser->pos = 0; 329 | parser->toknext = 0; 330 | parser->toksuper = -1; 331 | } 332 | 333 | -------------------------------------------------------------------------------- /regress/jsmn.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010 Serge A. Zaitsev 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE.* 21 | */ 22 | #ifndef __JSMN_H_ 23 | #define __JSMN_H_ 24 | 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /** 32 | * JSON type identifier. Basic types are: 33 | * o Object 34 | * o Array 35 | * o String 36 | * o Other primitive: number, boolean (true/false) or null 37 | */ 38 | typedef enum { 39 | JSMN_UNDEFINED = 0, 40 | JSMN_OBJECT = 1, 41 | JSMN_ARRAY = 2, 42 | JSMN_STRING = 3, 43 | JSMN_PRIMITIVE = 4 44 | } jsmntype_t; 45 | 46 | enum jsmnerr { 47 | /* Not enough tokens were provided */ 48 | JSMN_ERROR_NOMEM = -1, 49 | /* Invalid character inside JSON string */ 50 | JSMN_ERROR_INVAL = -2, 51 | /* The string is not a full JSON packet, more bytes expected */ 52 | JSMN_ERROR_PART = -3 53 | }; 54 | 55 | /** 56 | * JSON token description. 57 | * @param type type (object, array, string etc.) 58 | * @param start start position in JSON data string 59 | * @param end end position in JSON data string 60 | */ 61 | typedef struct { 62 | jsmntype_t type; 63 | int start; 64 | int end; 65 | int size; 66 | #ifdef JSMN_PARENT_LINKS 67 | int parent; 68 | #endif 69 | } jsmntok_t; 70 | 71 | /** 72 | * JSON parser. Contains an array of token blocks available. Also stores 73 | * the string being parsed now and current position in that string 74 | */ 75 | typedef struct { 76 | unsigned int pos; /* offset in the JSON string */ 77 | unsigned int toknext; /* next token to allocate */ 78 | int toksuper; /* superior token node, e.g parent object or array */ 79 | } jsmn_parser; 80 | 81 | /** 82 | * Create JSON parser over an array of tokens 83 | */ 84 | void jsmn_init(jsmn_parser *parser); 85 | 86 | /** 87 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 88 | * a single JSON object. 89 | */ 90 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 91 | jsmntok_t *tokens, unsigned int num_tokens); 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif /* __JSMN_H_ */ 98 | -------------------------------------------------------------------------------- /regress/json.c: -------------------------------------------------------------------------------- 1 | /* $Id: json.c,v 1.11 2019/01/31 15:55:48 benno Exp $ */ 2 | /* 3 | * Copyright (c) 2016 Kristaps Dzonsons 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "jsmn.h" 27 | #include "extern.h" 28 | 29 | /* 30 | * Object for converting the JSMN token array into a tree. 31 | */ 32 | struct parse { 33 | struct jsmnn *nodes; /* all nodes */ 34 | size_t cur; /* current number */ 35 | size_t max; /* nodes in "nodes" */ 36 | }; 37 | 38 | /* 39 | * Recursive part for convertin a JSMN token array into a tree. 40 | * See "example/jsondump.c" for its construction (it's the same except 41 | * for how it handles allocation errors). 42 | */ 43 | static ssize_t 44 | build(struct parse *parse, struct jsmnn **np, 45 | jsmntok_t *t, const char *js, size_t sz) 46 | { 47 | size_t i, j; 48 | struct jsmnn *n; 49 | ssize_t tmp; 50 | 51 | if (sz == 0) 52 | return 0; 53 | 54 | assert(parse->cur < parse->max); 55 | n = *np = &parse->nodes[parse->cur++]; 56 | n->p = parse; 57 | n->type = t->type; 58 | 59 | switch (t->type) { 60 | case JSMN_STRING: 61 | /* FALLTHROUGH */ 62 | case JSMN_PRIMITIVE: 63 | n->fields = 1; 64 | n->d.str = strndup 65 | (js + t->start, 66 | t->end - t->start); 67 | if (n->d.str == NULL) 68 | break; 69 | return 1; 70 | case JSMN_OBJECT: 71 | n->fields = t->size; 72 | n->d.obj = calloc(n->fields, 73 | sizeof(struct jsmnp)); 74 | if (n->d.obj == NULL) 75 | break; 76 | for (i = j = 0; i < (size_t)t->size; i++) { 77 | tmp = build(parse, 78 | &n->d.obj[i].lhs, 79 | t + 1 + j, js, sz - j); 80 | if (tmp < 0) 81 | break; 82 | j += tmp; 83 | tmp = build(parse, 84 | &n->d.obj[i].rhs, 85 | t + 1 + j, js, sz - j); 86 | if (tmp < 0) 87 | break; 88 | j += tmp; 89 | } 90 | if (i < (size_t)t->size) 91 | break; 92 | return j + 1; 93 | case JSMN_ARRAY: 94 | n->fields = t->size; 95 | n->d.array = calloc(n->fields, 96 | sizeof(struct jsmnn *)); 97 | if (n->d.array == NULL) 98 | break; 99 | for (i = j = 0; i < (size_t)t->size; i++) { 100 | tmp = build(parse, 101 | &n->d.array[i], 102 | t + 1 + j, js, sz - j); 103 | if (tmp < 0) 104 | break; 105 | j += tmp; 106 | } 107 | if (i < (size_t)t->size) 108 | break; 109 | return j + 1; 110 | default: 111 | break; 112 | } 113 | 114 | return -1; 115 | } 116 | 117 | /* 118 | * Fully free up a parse sequence. 119 | * This handles all nodes sequentially, not recursively. 120 | */ 121 | static void 122 | jsmnparse_free(struct parse *p) 123 | { 124 | size_t i; 125 | 126 | if (p == NULL) 127 | return; 128 | for (i = 0; i < p->max; i++) { 129 | struct jsmnn *n = &p->nodes[i]; 130 | switch (n->type) { 131 | case JSMN_ARRAY: 132 | free(n->d.array); 133 | break; 134 | case JSMN_OBJECT: 135 | free(n->d.obj); 136 | break; 137 | case JSMN_PRIMITIVE: 138 | free(n->d.str); 139 | break; 140 | case JSMN_STRING: 141 | free(n->d.str); 142 | break; 143 | case JSMN_UNDEFINED: 144 | break; 145 | } 146 | } 147 | free(p->nodes); 148 | free(p); 149 | } 150 | 151 | /* 152 | * Allocate a tree representation of "t". 153 | * This returns NULL on allocation failure or when sz is zero, in which 154 | * case all resources allocated along the way are freed already. 155 | */ 156 | static struct jsmnn * 157 | jsmntree_alloc(jsmntok_t *t, const char *js, size_t sz) 158 | { 159 | struct jsmnn *first; 160 | struct parse *p; 161 | 162 | if (sz == 0) 163 | return NULL; 164 | 165 | p = calloc(1, sizeof(struct parse)); 166 | if (p == NULL) 167 | return NULL; 168 | 169 | p->max = sz; 170 | p->nodes = calloc(p->max, sizeof(struct jsmnn)); 171 | if (p->nodes == NULL) { 172 | free(p); 173 | return NULL; 174 | } 175 | 176 | if (build(p, &first, t, js, sz) < 0) { 177 | jsmnparse_free(p); 178 | first = NULL; 179 | } 180 | 181 | return first; 182 | } 183 | 184 | /* 185 | * Call through to free parse contents. 186 | */ 187 | void 188 | json_free(struct jsmnn *first) 189 | { 190 | 191 | if (first != NULL) 192 | jsmnparse_free(first->p); 193 | } 194 | 195 | /* 196 | * Just check that the array object is in fact an object. 197 | */ 198 | struct jsmnn * 199 | json_getarrayobj(struct jsmnn *n) 200 | { 201 | 202 | return n->type != JSMN_OBJECT ? NULL : n; 203 | } 204 | 205 | /* 206 | * Extract an array from the returned JSON object, making sure that it's 207 | * the correct type. 208 | * Returns NULL on failure. 209 | */ 210 | struct jsmnn * 211 | json_getarray(struct jsmnn *n, const char *name) 212 | { 213 | size_t i; 214 | 215 | if (n->type != JSMN_OBJECT) 216 | return NULL; 217 | for (i = 0; i < n->fields; i++) { 218 | if (n->d.obj[i].lhs->type != JSMN_STRING && 219 | n->d.obj[i].lhs->type != JSMN_PRIMITIVE) 220 | continue; 221 | else if (strcmp(name, n->d.obj[i].lhs->d.str)) 222 | continue; 223 | break; 224 | } 225 | if (i == n->fields) 226 | return NULL; 227 | if (n->d.obj[i].rhs->type != JSMN_ARRAY) 228 | return NULL; 229 | return n->d.obj[i].rhs; 230 | } 231 | 232 | /* 233 | * Extract subtree from the returned JSON object, making sure that it's 234 | * the correct type. 235 | * Returns NULL on failure. 236 | */ 237 | struct jsmnn * 238 | json_getobj(struct jsmnn *n, const char *name) 239 | { 240 | size_t i; 241 | 242 | if (n->type != JSMN_OBJECT) 243 | return NULL; 244 | for (i = 0; i < n->fields; i++) { 245 | if (n->d.obj[i].lhs->type != JSMN_STRING && 246 | n->d.obj[i].lhs->type != JSMN_PRIMITIVE) 247 | continue; 248 | else if (strcmp(name, n->d.obj[i].lhs->d.str)) 249 | continue; 250 | break; 251 | } 252 | if (i == n->fields) 253 | return NULL; 254 | if (n->d.obj[i].rhs->type != JSMN_OBJECT) 255 | return NULL; 256 | return n->d.obj[i].rhs; 257 | } 258 | 259 | /* 260 | * Extract a single string from the returned JSON object, making sure 261 | * that it's the correct type. 262 | * Returns NULL on failure. 263 | */ 264 | char * 265 | json_getstr(struct jsmnn *n, const char *name) 266 | { 267 | size_t i; 268 | char *cp; 269 | 270 | if (n->type != JSMN_OBJECT) 271 | return NULL; 272 | for (i = 0; i < n->fields; i++) { 273 | if (n->d.obj[i].lhs->type != JSMN_STRING && 274 | n->d.obj[i].lhs->type != JSMN_PRIMITIVE) 275 | continue; 276 | else if (strcmp(name, n->d.obj[i].lhs->d.str)) 277 | continue; 278 | break; 279 | } 280 | if (i == n->fields) 281 | return NULL; 282 | if (n->d.obj[i].rhs->type != JSMN_STRING && 283 | n->d.obj[i].rhs->type != JSMN_PRIMITIVE) 284 | return NULL; 285 | 286 | cp = strdup(n->d.obj[i].rhs->d.str); 287 | if (cp == NULL) 288 | warn("strdup"); 289 | return cp; 290 | } 291 | 292 | /* 293 | * Parse an HTTP response body from a buffer of size "sz". 294 | * Returns an opaque pointer on success, otherwise NULL on error. 295 | */ 296 | struct jsmnn * 297 | json_parse(const char *buf, size_t sz) 298 | { 299 | struct jsmnn *n; 300 | jsmn_parser p; 301 | jsmntok_t *tok; 302 | int r; 303 | size_t tokcount; 304 | 305 | jsmn_init(&p); 306 | tokcount = 32768; 307 | 308 | /* Do this until we don't need any more tokens. */ 309 | again: 310 | tok = calloc(tokcount, sizeof(jsmntok_t)); 311 | if (tok == NULL) { 312 | warn("calloc"); 313 | return NULL; 314 | } 315 | 316 | /* Actually try to parse the JSON into the tokens. */ 317 | 318 | r = jsmn_parse(&p, buf, sz, tok, tokcount); 319 | if (r < 0 && r == JSMN_ERROR_NOMEM) { 320 | tokcount *= 2; 321 | free(tok); 322 | goto again; 323 | } else if (r < 0) { 324 | warnx("jsmn_parse: %d", r); 325 | free(tok); 326 | return NULL; 327 | } 328 | 329 | /* Now parse the tokens into a tree. */ 330 | 331 | n = jsmntree_alloc(tok, buf, r); 332 | free(tok); 333 | return n; 334 | } 335 | -------------------------------------------------------------------------------- /regress/main.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD$ */ 2 | 3 | /* 4 | * Copyright (c) 2019 Reyk Floeter 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "hpack.h" 34 | #include "extern.h" 35 | 36 | static int encode_huffman(const char *); 37 | static int decode_huffman(const char *); 38 | 39 | int verbose; 40 | int encode; 41 | 42 | static void 43 | log(int level, const char *fmt, ...) 44 | { 45 | va_list ap; 46 | 47 | if (verbose < level) 48 | return; 49 | 50 | va_start(ap, fmt); 51 | vprintf(fmt, ap); 52 | va_end(ap); 53 | } 54 | 55 | static const char * 56 | json_uascii_decode(char *str) 57 | { 58 | char *p, *q; 59 | char hex[5]; 60 | unsigned long x; 61 | 62 | hex[4] = '\0'; 63 | p = q = str; 64 | 65 | while (*p != '\0') { 66 | if (*p != '\\') { 67 | *q = *p; 68 | p++; 69 | q++; 70 | continue; 71 | } 72 | switch (*(p + 1)) { 73 | case 'u': 74 | /* Encoding character is followed by four hex chars */ 75 | if (!(isxdigit((unsigned char)p[2]) && 76 | isxdigit((unsigned char)p[3]) && 77 | isxdigit((unsigned char)p[4]) && 78 | isxdigit((unsigned char)p[5]))) 79 | return (NULL); 80 | 81 | hex[0] = p[2]; 82 | hex[1] = p[3]; 83 | hex[2] = p[4]; 84 | hex[3] = p[5]; 85 | 86 | /* We don't support non-ASCII chars */ 87 | if ((x = strtoul(hex, NULL, 16)) > 0x7f) 88 | return (NULL); 89 | *q = (char)x; 90 | p += 5; 91 | break; 92 | case '"': 93 | *q = '"'; 94 | p++; 95 | break; 96 | default: 97 | *q = *p; 98 | break; 99 | } 100 | p++; 101 | q++; 102 | } 103 | *q = '\0'; 104 | 105 | return (str); 106 | } 107 | 108 | static int 109 | hpack_headerblock_cmp(struct hpack_headerblock *a, 110 | struct hpack_headerblock *b) 111 | { 112 | struct hpack_header *ha, *hb; 113 | 114 | for (ha = TAILQ_FIRST(a), hb = TAILQ_FIRST(b); 115 | !(ha == NULL && hb == NULL); 116 | ha = TAILQ_NEXT(ha, hdr_entry), 117 | hb = TAILQ_NEXT(hb, hdr_entry)) { 118 | #define ONE_NULL(_a, _b) ( \ 119 | ((_a) != NULL && (_b) == NULL) || \ 120 | ((_a) == NULL && (_b) != NULL) \ 121 | ) 122 | if (ONE_NULL(ha, hb) || 123 | ONE_NULL(ha->hdr_name, hb->hdr_name) || 124 | ONE_NULL(ha->hdr_value, hb->hdr_value)) 125 | return (-1); 126 | #undef ONE_NULL 127 | if (ha->hdr_name != NULL && 128 | strcmp(ha->hdr_name, hb->hdr_name) != 0) 129 | return (-2); 130 | if (ha->hdr_value != NULL && 131 | strcmp(ha->hdr_value, hb->hdr_value) != 0) 132 | return (-3); 133 | } 134 | 135 | return (0); 136 | } 137 | 138 | static int 139 | hpack_headerblock_print(const char *prefix, struct hpack_headerblock *hdrs) 140 | { 141 | struct hpack_header *hdr; 142 | 143 | if (hdrs == NULL) 144 | return (0); 145 | if (TAILQ_EMPTY(hdrs)) { 146 | log(2, "%s: empty headers\n", prefix); 147 | return (-1); 148 | } 149 | 150 | TAILQ_FOREACH(hdr, hdrs, hdr_entry) { 151 | if (hdr->hdr_name == NULL || hdr->hdr_value == NULL) { 152 | if (prefix != NULL) 153 | log(2, "%s invalid header: %s: %s\n", prefix, 154 | hdr->hdr_name == NULL ? 155 | "(null)" : hdr->hdr_name, 156 | hdr->hdr_value == NULL ? 157 | "(null)" : hdr->hdr_value); 158 | return (-1); 159 | } 160 | if (prefix != NULL) 161 | log(2, "%s %s: %s\n", prefix, 162 | hdr->hdr_name, hdr->hdr_value); 163 | } 164 | 165 | return (0); 166 | } 167 | 168 | static int 169 | x2i(const char *s) 170 | { 171 | char ss[3]; 172 | 173 | ss[0] = s[0]; 174 | ss[1] = s[1]; 175 | ss[2] = 0; 176 | 177 | if (!isxdigit(s[0]) || !isxdigit(s[1])) { 178 | log(2, "string needs to be specified in hex digits\n"); 179 | return (-1); 180 | } 181 | return ((int)strtoul(ss, NULL, 16)); 182 | } 183 | 184 | static ssize_t 185 | parsehex(const char *hex, unsigned char *buf, size_t len) 186 | { 187 | ssize_t datalen; 188 | unsigned int i; 189 | int c; 190 | 191 | memset(buf, 0, len); 192 | if (strncmp(hex, "0x", 2) == 0) 193 | hex += 2; 194 | datalen = strlen(hex) / 2; 195 | if (datalen > (ssize_t)len) 196 | return (-1); 197 | 198 | for (i = 0; i < datalen; i++) { 199 | if ((c = x2i(hex + 2 * i)) == -1) 200 | return (-1); 201 | buf[i] = (unsigned char)c; 202 | } 203 | 204 | return (datalen); 205 | } 206 | 207 | static int 208 | parse_data(unsigned char *buf, size_t len, 209 | struct hpack_headerblock *test, struct hpack_table *hpack) 210 | { 211 | struct hpack_headerblock *hdrs = NULL; 212 | int ret = -1; 213 | 214 | if ((hdrs = hpack_decode(buf, len, hpack)) == NULL) { 215 | log(2, "hpack_decode\n"); 216 | goto fail; 217 | } 218 | 219 | if (test != NULL && hpack_headerblock_print(NULL, test) == -1) { 220 | log(2, "test headers invalid\n"); 221 | goto fail; 222 | } 223 | if (hpack_headerblock_print(NULL, hdrs) == -1) { 224 | log(2, "parsed headers invalid\n"); 225 | goto fail; 226 | } 227 | if (test != NULL && (ret = hpack_headerblock_cmp(hdrs, test)) != 0) { 228 | log(2, "test headers mismatched (returned %d)\n", ret); 229 | ret = -1; 230 | goto fail; 231 | } 232 | 233 | ret = 0; 234 | fail: 235 | if (ret != 0) { 236 | hpack_headerblock_print(">>> header:", test); 237 | hpack_headerblock_print("<<< parsed:", hdrs); 238 | } 239 | hpack_headerblock_free(hdrs); 240 | return (ret); 241 | } 242 | 243 | static int 244 | parse_hex(const char *hex, struct hpack_headerblock *test, 245 | struct hpack_table *hpack) 246 | { 247 | unsigned char buf[8192]; 248 | ssize_t len; 249 | 250 | if ((len = parsehex(hex, buf, sizeof(buf))) == -1) { 251 | log(2, "wire format is not a hex string\n"); 252 | return (-1); 253 | } 254 | 255 | if (parse_data(buf, len, test, hpack) == -1) 256 | return (-1); 257 | 258 | log(2, ">>> wire: %s\n", hex); 259 | return (0); 260 | } 261 | 262 | static ssize_t 263 | parse_input(const char *name, size_t init_table_size) 264 | { 265 | struct hpack_table *hpack = NULL; 266 | FILE *fp; 267 | char buf[BUFSIZ]; 268 | ssize_t ok = 0, ret = -1; 269 | 270 | if (encode) 271 | return (-1); 272 | if (strcmp("-", name) == 0) 273 | fp = stdin; 274 | else if ((fp = fopen(name, "r")) == NULL) 275 | return (-1); 276 | 277 | if ((hpack = hpack_table_new(init_table_size)) == NULL) 278 | goto done; 279 | 280 | while (fgets(buf, sizeof(buf), fp) != NULL) { 281 | buf[strcspn(buf, "\r\n")] = '\0'; 282 | if (parse_hex(buf, NULL, hpack) == -1) { 283 | log(1, "hex HPACK decoding failed\n"); 284 | goto done; 285 | } 286 | ok++; 287 | } 288 | 289 | ret = ok; 290 | done: 291 | if (fp != NULL && fp != stdin) 292 | fclose(fp); 293 | hpack_table_free(hpack); 294 | 295 | return (ret); 296 | } 297 | 298 | static int 299 | parse_raw(const char *name, size_t init_table_size) 300 | { 301 | char buf[65535], *ptr = NULL, *k, *v; 302 | struct hpack_table *hpack = NULL; 303 | struct hpack_headerblock *hdrs = NULL; 304 | FILE *fp; 305 | int ret = -1; 306 | size_t len; 307 | 308 | if (strcmp("-", name) == 0) 309 | fp = stdin; 310 | else if ((fp = fopen(name, "r")) == NULL) 311 | goto done; 312 | if ((hpack = hpack_table_new(init_table_size)) == NULL) 313 | goto done; 314 | if (encode) { 315 | if ((hdrs = hpack_headerblock_new()) == NULL) 316 | goto done; 317 | while (fgets(buf, sizeof(buf), fp) != NULL) { 318 | buf[strcspn(buf, "\r\n")] = '\0'; 319 | k = buf; 320 | if ((v = strchr(k + 1, ':')) != NULL) { 321 | *v++ = '\0'; 322 | v += strspn(v, " \t"); 323 | } else if (isupper(buf[0])) { 324 | /* cheap way to test for the method */ 325 | buf[strcspn(buf, " \t")] = '\0'; 326 | k = ":method"; 327 | v = buf; 328 | } else 329 | v = ""; 330 | log(2, "adding header '%s: %s'\n", k, v); 331 | if (hpack_header_add(hdrs, 332 | k, v, HPACK_INDEX) == NULL) 333 | goto done; 334 | } 335 | if ((ptr = hpack_encode(hdrs, &len, hpack)) == NULL) { 336 | log(1, "raw HPACK decoding failed\n"); 337 | goto done; 338 | } 339 | } else { 340 | if ((len = fread(buf, 1, sizeof(buf), fp)) < 1) { 341 | if (feof(fp)) 342 | ret = 0; 343 | goto done; 344 | } 345 | ptr = buf; 346 | } 347 | 348 | if ((hdrs = hpack_decode(ptr, len, hpack)) == NULL) { 349 | log(1, "raw HPACK decoding failed\n"); 350 | goto done; 351 | } 352 | 353 | ret = 0; 354 | done: 355 | if (ptr != buf) 356 | free(ptr); 357 | if (fp != NULL && fp != stdin) 358 | fclose(fp); 359 | hpack_headerblock_free(hdrs); 360 | hpack_table_free(hpack); 361 | 362 | return (ret); 363 | } 364 | 365 | static int 366 | parse_dir(char *argv[], size_t init_table_size) 367 | { 368 | struct hpack_table *hpack = NULL, *hpack2 = NULL; 369 | struct hpack_headerblock *test = NULL; 370 | FTS *fts; 371 | FTSENT *ftsp = NULL; 372 | char *str = NULL, *wire = NULL, *tblsz; 373 | FILE *fp; 374 | off_t size; 375 | int ret = -1; 376 | struct jsmnn *json = NULL, *cases, *obj, *hdr, *hdrs; 377 | size_t i = 0, j, k; 378 | ssize_t ok = 0; 379 | const char *errstr = NULL; 380 | size_t table_size, file_table_size, len; 381 | 382 | if (encode) 383 | return (-1); 384 | if ((fts = fts_open(argv, FTS_COMFOLLOW|FTS_NOCHDIR, 385 | NULL)) == NULL) { 386 | errstr = "failed to open directory"; 387 | goto done; 388 | } 389 | 390 | while ((ftsp = fts_read(fts)) != NULL) { 391 | if (ftsp->fts_info != FTS_F) 392 | continue; 393 | 394 | file_table_size = init_table_size; 395 | 396 | if (fnmatch("*.hpacktest", ftsp->fts_name, 397 | FNM_PATHNAME) != FNM_NOMATCH) { 398 | if ((ok = parse_input(ftsp->fts_accpath, 399 | file_table_size)) < 0) { 400 | errstr = "hex input file parsing failed"; 401 | goto done; 402 | } 403 | goto next; 404 | } else if (fnmatch("*.hpackraw", ftsp->fts_name, 405 | FNM_PATHNAME) != FNM_NOMATCH) { 406 | if (parse_raw(ftsp->fts_accpath, 407 | file_table_size) == -1) { 408 | errstr = "raw input file parsing failed"; 409 | goto done; 410 | } 411 | ok = 1; 412 | goto next; 413 | } else if (fnmatch("headers_??.txt", ftsp->fts_name, 414 | FNM_PATHNAME) != FNM_NOMATCH) { 415 | if (encode_huffman(ftsp->fts_accpath) == -1) { 416 | errstr = "huffman encoding failed"; 417 | goto done; 418 | } 419 | ok = 1; 420 | goto next; 421 | } else if (fnmatch("story_*.json", ftsp->fts_name, 422 | FNM_PATHNAME) == FNM_NOMATCH) 423 | continue; 424 | size = ftsp->fts_statp->st_size; 425 | ok = 0; 426 | 427 | if ((fp = fopen(ftsp->fts_accpath, "r")) == NULL) 428 | continue; 429 | 430 | if ((str = malloc(size)) == NULL) { 431 | fclose(fp); 432 | continue; 433 | } 434 | if ((off_t)fread(str, 1, size, fp) != size) { 435 | fclose(fp); 436 | free(str); 437 | continue; 438 | } 439 | fclose(fp); 440 | 441 | if ((json = json_parse(str, size)) == NULL) { 442 | errstr = "json parsing failed"; 443 | goto done; 444 | } 445 | if ((cases = json_getarray(json, "cases")) == NULL) { 446 | errstr = "no test cases found"; 447 | goto done; 448 | } 449 | 450 | for (i = 0; i < cases->fields; i++) { 451 | if ((obj = 452 | json_getarrayobj(cases->d.array[i])) == NULL) 453 | continue; 454 | if ((wire = json_getstr(obj, "wire")) == NULL) { 455 | /* ignore test case without wire definition */ 456 | ret = 0; 457 | goto done; 458 | } 459 | if ((tblsz = json_getstr(obj, 460 | "header_table_size")) != NULL) { 461 | table_size = strtonum(tblsz, 462 | 0, LONG_MAX, &errstr); 463 | free(tblsz); 464 | if (errstr != NULL) 465 | goto done; 466 | } else 467 | table_size = file_table_size; 468 | if ((hdrs = json_getarray(obj, "headers")) == NULL) { 469 | errstr = "no headers found"; 470 | goto done; 471 | } 472 | if ((test = hpack_headerblock_new()) == NULL) 473 | goto done; 474 | for (j = 0; j < hdrs->fields; j++) { 475 | if ((hdr = json_getarrayobj(hdrs->d.array[j])) 476 | == NULL) 477 | continue; 478 | for (k = 0; k < hdr->fields; k++) { 479 | if (hdr->d.obj[k].lhs->type != 480 | JSMN_STRING && 481 | hdr->d.obj[k].lhs->type != 482 | JSMN_PRIMITIVE) 483 | continue; 484 | if (json_uascii_decode( 485 | hdr->d.obj[k].rhs->d.str) == NULL) { 486 | errstr = "invalid JSON value"; 487 | goto done; 488 | } 489 | if (hpack_header_add(test, 490 | hdr->d.obj[k].lhs->d.str, 491 | hdr->d.obj[k].rhs->d.str, 0) == NULL) { 492 | errstr = "failed to add header"; 493 | goto done; 494 | } 495 | } 496 | } 497 | 498 | if (hpack == NULL) { 499 | if (table_size > file_table_size) 500 | file_table_size = table_size; 501 | if ((hpack = 502 | hpack_table_new(file_table_size)) == NULL) { 503 | errstr = "failed to get HPACK table"; 504 | goto done; 505 | } 506 | if ((hpack2 = 507 | hpack_table_new(file_table_size)) == NULL) { 508 | errstr = "failed to get HPACK table"; 509 | goto done; 510 | } 511 | } 512 | 513 | if (parse_hex(wire, test, hpack) == -1) { 514 | errstr = "failed to parse HPACK"; 515 | goto done; 516 | } 517 | 518 | if (hpack_table_size(hpack) > table_size) { 519 | errstr = "invalid table size"; 520 | goto done; 521 | } 522 | 523 | /* Test encoding by re-encoding of the header */ 524 | free(wire); 525 | if ((wire = hpack_encode(test, &len, hpack2)) == NULL) { 526 | errstr = "re-encoding failed"; 527 | goto done; 528 | } 529 | if (parse_data(wire, len, test, hpack2) == -1) { 530 | errstr = "re-decoding failed"; 531 | goto done; 532 | } 533 | 534 | ok++; 535 | hpack_headerblock_free(test); 536 | test = NULL; 537 | free(wire); 538 | wire = NULL; 539 | } 540 | 541 | i = 0; 542 | hpack_table_free(hpack); 543 | hpack_table_free(hpack2); 544 | hpack = hpack2 = NULL; 545 | json_free(json); 546 | json = NULL; 547 | free(str); 548 | str = NULL; 549 | 550 | next: 551 | log(1, "SUCCESS: %s: %zu tests\n", ftsp->fts_path, ok); 552 | } 553 | 554 | ret = 0; 555 | done: 556 | if (errstr != NULL && ftsp != NULL && i != 0) 557 | log(1, "FAILED: %s: %s in test %zu\n", 558 | ftsp->fts_path, errstr, i); 559 | else if (errstr != NULL && ftsp != NULL) 560 | log(1, "FAILED: %s: %s\n", 561 | ftsp->fts_path, errstr); 562 | else if (errstr != NULL) 563 | log(1, "FAILED: %s\n", errstr); 564 | free(wire); 565 | hpack_table_free(hpack); 566 | hpack_table_free(hpack2); 567 | hpack_headerblock_free(test); 568 | json_free(json); 569 | free(str); 570 | fts_close(fts); 571 | 572 | return (ret); 573 | } 574 | 575 | static int 576 | encode_huffman(const char *name) 577 | { 578 | char buf[65535]; 579 | char *enc = NULL, *dec = NULL; 580 | FILE *fp; 581 | int ret = -1; 582 | size_t len = 0, enclen = 0, declen = 0; 583 | 584 | if (strcmp("-", name) == 0) 585 | fp = stdin; 586 | else if ((fp = fopen(name, "r")) == NULL) 587 | goto done; 588 | if ((len = fread(buf, 1, sizeof(buf), fp)) < 1) { 589 | if (feof(fp)) 590 | ret = 0; 591 | goto done; 592 | } 593 | if ((enc = hpack_huffman_encode(buf, len, &enclen)) == NULL) 594 | goto done; 595 | if ((dec = hpack_huffman_decode(enc, enclen, &declen)) == NULL) 596 | goto done; 597 | if (memcmp(dec, buf, len) != 0) 598 | goto done; 599 | 600 | ret = 0; 601 | done: 602 | log(2, "%s: huffman lengths: raw input %zu," 603 | " encoded output %zu, decoded %zu\n", 604 | ret == 0 ? "SUCCESS": "FAILED" , len, enclen, declen); 605 | if (fp != NULL && fp != stdin) 606 | fclose(fp); 607 | free(enc); 608 | free(dec); 609 | 610 | return (ret); 611 | } 612 | 613 | static int 614 | decode_huffman(const char *name) 615 | { 616 | char buf[65535]; 617 | char *enc = NULL, *dec = NULL; 618 | FILE *fp; 619 | int ret = -1; 620 | size_t len = 0, enclen = 0, declen = 0; 621 | 622 | if (strcmp("-", name) == 0) 623 | fp = stdin; 624 | else if ((fp = fopen(name, "r")) == NULL) 625 | goto done; 626 | if ((len = fread(buf, 1, sizeof(buf), fp)) < 1) { 627 | if (feof(fp)) 628 | ret = 0; 629 | goto done; 630 | } 631 | if ((dec = hpack_huffman_decode(buf, len, &declen)) == NULL) 632 | goto done; 633 | if ((enc = hpack_huffman_encode(dec, declen, &enclen)) == NULL) 634 | goto done; 635 | if (memcmp(enc, buf, len) != 0) 636 | goto done; 637 | 638 | ret = 0; 639 | done: 640 | log(2, "%s: huffman lengths: raw input %zu," 641 | " decoded output %zu, encoded %zu\n", 642 | ret == 0 ? "SUCCESS": "FAILED" , len, declen, enclen); 643 | if (fp != NULL && fp != stdin) 644 | fclose(fp); 645 | free(enc); 646 | free(dec); 647 | 648 | return (ret); 649 | } 650 | 651 | static __dead void 652 | usage(void) 653 | { 654 | extern char *__progname; 655 | 656 | fprintf(stderr, "usage: %s [-d|e file] [-h hex] [-p input-file]" 657 | " [-r raw-file] [-x hex] [dir ...]\n", __progname); 658 | exit(1); 659 | } 660 | 661 | int 662 | main(int argc, char *argv[]) 663 | { 664 | const char *hex = NULL, *input = NULL, *raw = NULL; 665 | const char *huffenc = NULL, *huffdec = NULL; 666 | int ch, ret; 667 | 668 | if (hpack_init() == -1) 669 | return (1); 670 | 671 | while ((ch = getopt(argc, argv, "d:Ee:h:i:r:v")) != -1) { 672 | switch (ch) { 673 | case 'd': 674 | huffdec = optarg; 675 | break; 676 | case 'E': 677 | encode = 1; 678 | break; 679 | case 'e': 680 | huffenc = optarg; 681 | break; 682 | case 'h': 683 | hex = optarg; 684 | break; 685 | case 'i': 686 | input = optarg; 687 | break; 688 | case 'r': 689 | raw = optarg; 690 | break; 691 | case 'v': 692 | verbose++; 693 | break; 694 | default: 695 | usage(); 696 | } 697 | } 698 | argc -= optind; 699 | argv += optind; 700 | 701 | if (huffdec != NULL) 702 | ret = decode_huffman(huffdec); 703 | else if (huffenc != NULL) 704 | ret = encode_huffman(huffenc); 705 | else if (hex != NULL) 706 | ret = parse_hex(hex, NULL, NULL); 707 | else if (input != NULL) 708 | ret = parse_input(input, 4096); 709 | else if (raw != NULL) 710 | ret = parse_raw(raw, 4096); 711 | else if (argc > 0) 712 | ret = parse_dir(argv, 4096); 713 | else 714 | usage(); 715 | if (ret == -1) 716 | return (1); 717 | 718 | return (0); 719 | } 720 | --------------------------------------------------------------------------------