1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "nghttp2_hd_test.h"
26
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include <CUnit/CUnit.h>
31
32 #include "nghttp2_hd.h"
33 #include "nghttp2_frame.h"
34 #include "nghttp2_test_helper.h"
35
test_nghttp2_hd_deflate(void)36 void test_nghttp2_hd_deflate(void) {
37 nghttp2_hd_deflater deflater;
38 nghttp2_hd_inflater inflater;
39 nghttp2_nv nva1[] = {MAKE_NV(":path", "/my-example/index.html"),
40 MAKE_NV(":scheme", "https"), MAKE_NV("hello", "world")};
41 nghttp2_nv nva2[] = {MAKE_NV(":path", "/script.js"),
42 MAKE_NV(":scheme", "https")};
43 nghttp2_nv nva3[] = {MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k2=v2"),
44 MAKE_NV("via", "proxy")};
45 nghttp2_nv nva4[] = {MAKE_NV(":path", "/style.css"),
46 MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k1=v1")};
47 nghttp2_nv nva5[] = {MAKE_NV(":path", "/style.css"),
48 MAKE_NV("x-nghttp2", "")};
49 nghttp2_bufs bufs;
50 ssize_t blocklen;
51 nva_out out;
52 int rv;
53 nghttp2_mem *mem;
54
55 mem = nghttp2_mem_default();
56 frame_pack_bufs_init(&bufs);
57
58 nva_out_init(&out);
59 CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem));
60 CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem));
61
62 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
63 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
64
65 CU_ASSERT(0 == rv);
66 CU_ASSERT(blocklen > 0);
67 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
68
69 CU_ASSERT(3 == out.nvlen);
70 assert_nv_equal(nva1, out.nva, 3, mem);
71
72 nva_out_reset(&out, mem);
73 nghttp2_bufs_reset(&bufs);
74
75 /* Second headers */
76 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
77 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
78
79 CU_ASSERT(0 == rv);
80 CU_ASSERT(blocklen > 0);
81 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
82
83 CU_ASSERT(2 == out.nvlen);
84 assert_nv_equal(nva2, out.nva, 2, mem);
85
86 nva_out_reset(&out, mem);
87 nghttp2_bufs_reset(&bufs);
88
89 /* Third headers, including same header field name, but value is not
90 the same. */
91 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva3, ARRLEN(nva3));
92 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
93
94 CU_ASSERT(0 == rv);
95 CU_ASSERT(blocklen > 0);
96 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
97
98 CU_ASSERT(3 == out.nvlen);
99 assert_nv_equal(nva3, out.nva, 3, mem);
100
101 nva_out_reset(&out, mem);
102 nghttp2_bufs_reset(&bufs);
103
104 /* Fourth headers, including duplicate header fields. */
105 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva4, ARRLEN(nva4));
106 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
107
108 CU_ASSERT(0 == rv);
109 CU_ASSERT(blocklen > 0);
110 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
111
112 CU_ASSERT(3 == out.nvlen);
113 assert_nv_equal(nva4, out.nva, 3, mem);
114
115 nva_out_reset(&out, mem);
116 nghttp2_bufs_reset(&bufs);
117
118 /* Fifth headers includes empty value */
119 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva5, ARRLEN(nva5));
120 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
121
122 CU_ASSERT(0 == rv);
123 CU_ASSERT(blocklen > 0);
124 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
125
126 CU_ASSERT(2 == out.nvlen);
127 assert_nv_equal(nva5, out.nva, 2, mem);
128
129 nva_out_reset(&out, mem);
130 nghttp2_bufs_reset(&bufs);
131
132 /* Cleanup */
133 nghttp2_bufs_free(&bufs);
134 nghttp2_hd_inflate_free(&inflater);
135 nghttp2_hd_deflate_free(&deflater);
136 }
137
test_nghttp2_hd_deflate_same_indexed_repr(void)138 void test_nghttp2_hd_deflate_same_indexed_repr(void) {
139 nghttp2_hd_deflater deflater;
140 nghttp2_hd_inflater inflater;
141 nghttp2_nv nva1[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha")};
142 nghttp2_nv nva2[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha"),
143 MAKE_NV("host", "alpha")};
144 nghttp2_bufs bufs;
145 ssize_t blocklen;
146 nva_out out;
147 int rv;
148 nghttp2_mem *mem;
149
150 mem = nghttp2_mem_default();
151 frame_pack_bufs_init(&bufs);
152
153 nva_out_init(&out);
154 CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem));
155 CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem));
156
157 /* Encode 2 same headers. Emit 1 literal reprs and 1 index repr. */
158 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
159 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
160
161 CU_ASSERT(0 == rv);
162 CU_ASSERT(blocklen > 0);
163 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
164
165 CU_ASSERT(2 == out.nvlen);
166 assert_nv_equal(nva1, out.nva, 2, mem);
167
168 nva_out_reset(&out, mem);
169 nghttp2_bufs_reset(&bufs);
170
171 /* Encode 3 same headers. This time, emits 3 index reprs. */
172 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
173 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
174
175 CU_ASSERT(0 == rv);
176 CU_ASSERT(blocklen == 3);
177 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
178
179 CU_ASSERT(3 == out.nvlen);
180 assert_nv_equal(nva2, out.nva, 3, mem);
181
182 nva_out_reset(&out, mem);
183 nghttp2_bufs_reset(&bufs);
184
185 /* Cleanup */
186 nghttp2_bufs_free(&bufs);
187 nghttp2_hd_inflate_free(&inflater);
188 nghttp2_hd_deflate_free(&deflater);
189 }
190
test_nghttp2_hd_inflate_indexed(void)191 void test_nghttp2_hd_inflate_indexed(void) {
192 nghttp2_hd_inflater inflater;
193 nghttp2_bufs bufs;
194 ssize_t blocklen;
195 nghttp2_nv nv = MAKE_NV(":path", "/");
196 nva_out out;
197 nghttp2_mem *mem;
198
199 mem = nghttp2_mem_default();
200 frame_pack_bufs_init(&bufs);
201
202 nva_out_init(&out);
203 nghttp2_hd_inflate_init(&inflater, mem);
204
205 nghttp2_bufs_addb(&bufs, (1 << 7) | 4);
206
207 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
208
209 CU_ASSERT(1 == blocklen);
210 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
211
212 CU_ASSERT(1 == out.nvlen);
213
214 assert_nv_equal(&nv, out.nva, 1, mem);
215
216 nva_out_reset(&out, mem);
217 nghttp2_bufs_reset(&bufs);
218
219 /* index = 0 is error */
220 nghttp2_bufs_addb(&bufs, 1 << 7);
221
222 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
223
224 CU_ASSERT(1 == blocklen);
225 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
226 inflate_hd(&inflater, &out, &bufs, 0, mem));
227
228 nghttp2_bufs_free(&bufs);
229 nghttp2_hd_inflate_free(&inflater);
230 }
231
test_nghttp2_hd_inflate_indname_noinc(void)232 void test_nghttp2_hd_inflate_indname_noinc(void) {
233 nghttp2_hd_inflater inflater;
234 nghttp2_bufs bufs;
235 ssize_t blocklen;
236 nghttp2_nv nv[] = {/* Huffman */
237 MAKE_NV("user-agent", "nghttp2"),
238 /* Expecting no huffman */
239 MAKE_NV("user-agent", "x")};
240 size_t i;
241 nva_out out;
242 nghttp2_mem *mem;
243
244 mem = nghttp2_mem_default();
245 frame_pack_bufs_init(&bufs);
246
247 nva_out_init(&out);
248 nghttp2_hd_inflate_init(&inflater, mem);
249
250 for (i = 0; i < ARRLEN(nv); ++i) {
251 CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv[i],
252 NGHTTP2_HD_WITHOUT_INDEXING));
253
254 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
255
256 CU_ASSERT(blocklen > 0);
257 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
258
259 CU_ASSERT(1 == out.nvlen);
260 assert_nv_equal(&nv[i], out.nva, 1, mem);
261 CU_ASSERT(0 == inflater.ctx.hd_table.len);
262 CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
263
264 nva_out_reset(&out, mem);
265 nghttp2_bufs_reset(&bufs);
266 }
267
268 nghttp2_bufs_free(&bufs);
269 nghttp2_hd_inflate_free(&inflater);
270 }
271
test_nghttp2_hd_inflate_indname_inc(void)272 void test_nghttp2_hd_inflate_indname_inc(void) {
273 nghttp2_hd_inflater inflater;
274 nghttp2_bufs bufs;
275 ssize_t blocklen;
276 nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
277 nva_out out;
278 nghttp2_mem *mem;
279
280 mem = nghttp2_mem_default();
281 frame_pack_bufs_init(&bufs);
282
283 nva_out_init(&out);
284 nghttp2_hd_inflate_init(&inflater, mem);
285
286 CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv,
287 NGHTTP2_HD_WITH_INDEXING));
288
289 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
290
291 CU_ASSERT(blocklen > 0);
292 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
293
294 CU_ASSERT(1 == out.nvlen);
295 assert_nv_equal(&nv, out.nva, 1, mem);
296 CU_ASSERT(1 == inflater.ctx.hd_table.len);
297 CU_ASSERT(62 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
298 assert_nv_equal(
299 &nv,
300 nghttp2_hd_inflate_get_table_entry(
301 &inflater, NGHTTP2_STATIC_TABLE_LENGTH + inflater.ctx.hd_table.len),
302 1, mem);
303
304 nva_out_reset(&out, mem);
305 nghttp2_bufs_free(&bufs);
306 nghttp2_hd_inflate_free(&inflater);
307 }
308
test_nghttp2_hd_inflate_indname_inc_eviction(void)309 void test_nghttp2_hd_inflate_indname_inc_eviction(void) {
310 nghttp2_hd_inflater inflater;
311 nghttp2_bufs bufs;
312 ssize_t blocklen;
313 uint8_t value[1025];
314 nva_out out;
315 nghttp2_nv nv;
316 nghttp2_mem *mem;
317
318 mem = nghttp2_mem_default();
319 frame_pack_bufs_init(&bufs);
320
321 nva_out_init(&out);
322 nghttp2_hd_inflate_init(&inflater, mem);
323
324 memset(value, '0', sizeof(value));
325 value[sizeof(value) - 1] = '\0';
326 nv.value = value;
327 nv.valuelen = sizeof(value) - 1;
328
329 nv.flags = NGHTTP2_NV_FLAG_NONE;
330
331 CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14, &nv,
332 NGHTTP2_HD_WITH_INDEXING));
333 CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15, &nv,
334 NGHTTP2_HD_WITH_INDEXING));
335 CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, &nv,
336 NGHTTP2_HD_WITH_INDEXING));
337 CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 17, &nv,
338 NGHTTP2_HD_WITH_INDEXING));
339
340 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
341
342 CU_ASSERT(blocklen > 0);
343
344 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
345
346 CU_ASSERT(4 == out.nvlen);
347 CU_ASSERT(14 == out.nva[0].namelen);
348 CU_ASSERT(0 == memcmp("accept-charset", out.nva[0].name, out.nva[0].namelen));
349 CU_ASSERT(sizeof(value) - 1 == out.nva[0].valuelen);
350
351 nva_out_reset(&out, mem);
352 nghttp2_bufs_reset(&bufs);
353
354 CU_ASSERT(3 == inflater.ctx.hd_table.len);
355 CU_ASSERT(64 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
356
357 nghttp2_bufs_free(&bufs);
358 nghttp2_hd_inflate_free(&inflater);
359 }
360
test_nghttp2_hd_inflate_newname_noinc(void)361 void test_nghttp2_hd_inflate_newname_noinc(void) {
362 nghttp2_hd_inflater inflater;
363 nghttp2_bufs bufs;
364 ssize_t blocklen;
365 nghttp2_nv nv[] = {/* Expecting huffman for both */
366 MAKE_NV("my-long-content-length", "nghttp2"),
367 /* Expecting no huffman for both */
368 MAKE_NV("x", "y"),
369 /* Huffman for key only */
370 MAKE_NV("my-long-content-length", "y"),
371 /* Huffman for value only */
372 MAKE_NV("x", "nghttp2")};
373 size_t i;
374 nva_out out;
375 nghttp2_mem *mem;
376
377 mem = nghttp2_mem_default();
378 frame_pack_bufs_init(&bufs);
379
380 nva_out_init(&out);
381 nghttp2_hd_inflate_init(&inflater, mem);
382 for (i = 0; i < ARRLEN(nv); ++i) {
383 CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv[i],
384 NGHTTP2_HD_WITHOUT_INDEXING));
385
386 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
387
388 CU_ASSERT(blocklen > 0);
389 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
390
391 CU_ASSERT(1 == out.nvlen);
392 assert_nv_equal(&nv[i], out.nva, 1, mem);
393 CU_ASSERT(0 == inflater.ctx.hd_table.len);
394
395 nva_out_reset(&out, mem);
396 nghttp2_bufs_reset(&bufs);
397 }
398
399 nghttp2_bufs_free(&bufs);
400 nghttp2_hd_inflate_free(&inflater);
401 }
402
test_nghttp2_hd_inflate_newname_inc(void)403 void test_nghttp2_hd_inflate_newname_inc(void) {
404 nghttp2_hd_inflater inflater;
405 nghttp2_bufs bufs;
406 ssize_t blocklen;
407 nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
408 nva_out out;
409 nghttp2_mem *mem;
410
411 mem = nghttp2_mem_default();
412 frame_pack_bufs_init(&bufs);
413
414 nva_out_init(&out);
415 nghttp2_hd_inflate_init(&inflater, mem);
416
417 CU_ASSERT(
418 0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
419
420 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
421
422 CU_ASSERT(blocklen > 0);
423 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
424
425 CU_ASSERT(1 == out.nvlen);
426 assert_nv_equal(&nv, out.nva, 1, mem);
427 CU_ASSERT(1 == inflater.ctx.hd_table.len);
428 assert_nv_equal(
429 &nv,
430 nghttp2_hd_inflate_get_table_entry(
431 &inflater, NGHTTP2_STATIC_TABLE_LENGTH + inflater.ctx.hd_table.len),
432 1, mem);
433
434 nva_out_reset(&out, mem);
435 nghttp2_bufs_free(&bufs);
436 nghttp2_hd_inflate_free(&inflater);
437 }
438
test_nghttp2_hd_inflate_clearall_inc(void)439 void test_nghttp2_hd_inflate_clearall_inc(void) {
440 nghttp2_hd_inflater inflater;
441 nghttp2_bufs bufs;
442 ssize_t blocklen;
443 nghttp2_nv nv;
444 uint8_t value[4061];
445 nva_out out;
446 nghttp2_mem *mem;
447
448 mem = nghttp2_mem_default();
449 bufs_large_init(&bufs, 8192);
450
451 nva_out_init(&out);
452 /* Total 4097 bytes space required to hold this entry */
453 nv.name = (uint8_t *)"alpha";
454 nv.namelen = strlen((char *)nv.name);
455 memset(value, '0', sizeof(value));
456 value[sizeof(value) - 1] = '\0';
457 nv.value = value;
458 nv.valuelen = sizeof(value) - 1;
459
460 nv.flags = NGHTTP2_NV_FLAG_NONE;
461
462 nghttp2_hd_inflate_init(&inflater, mem);
463
464 CU_ASSERT(
465 0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
466
467 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
468
469 CU_ASSERT(blocklen > 0);
470 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
471
472 CU_ASSERT(1 == out.nvlen);
473 assert_nv_equal(&nv, out.nva, 1, mem);
474 CU_ASSERT(0 == inflater.ctx.hd_table.len);
475
476 nva_out_reset(&out, mem);
477
478 /* Do it again */
479 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
480
481 CU_ASSERT(1 == out.nvlen);
482 assert_nv_equal(&nv, out.nva, 1, mem);
483 CU_ASSERT(0 == inflater.ctx.hd_table.len);
484
485 nva_out_reset(&out, mem);
486 nghttp2_bufs_reset(&bufs);
487
488 /* This time, 4096 bytes space required, which is just fits in the
489 header table */
490 nv.valuelen = sizeof(value) - 2;
491
492 CU_ASSERT(
493 0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
494
495 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
496
497 CU_ASSERT(blocklen > 0);
498 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
499
500 CU_ASSERT(1 == out.nvlen);
501 assert_nv_equal(&nv, out.nva, 1, mem);
502 CU_ASSERT(1 == inflater.ctx.hd_table.len);
503
504 nva_out_reset(&out, mem);
505 nghttp2_bufs_reset(&bufs);
506
507 nghttp2_bufs_free(&bufs);
508 nghttp2_hd_inflate_free(&inflater);
509 }
510
test_nghttp2_hd_inflate_zero_length_huffman(void)511 void test_nghttp2_hd_inflate_zero_length_huffman(void) {
512 nghttp2_hd_inflater inflater;
513 nghttp2_bufs bufs;
514 /* Literal header without indexing - new name */
515 uint8_t data[] = {0x40, 0x01, 0x78 /* 'x' */, 0x80};
516 nva_out out;
517 nghttp2_mem *mem;
518
519 mem = nghttp2_mem_default();
520 frame_pack_bufs_init(&bufs);
521
522 nva_out_init(&out);
523
524 nghttp2_bufs_add(&bufs, data, sizeof(data));
525
526 /* /\* Literal header without indexing - new name *\/ */
527 /* ptr[0] = 0x40; */
528 /* ptr[1] = 1; */
529 /* ptr[2] = 'x'; */
530 /* ptr[3] = 0x80; */
531
532 nghttp2_hd_inflate_init(&inflater, mem);
533 CU_ASSERT(4 == inflate_hd(&inflater, &out, &bufs, 0, mem));
534
535 CU_ASSERT(1 == out.nvlen);
536 CU_ASSERT(1 == out.nva[0].namelen);
537 CU_ASSERT('x' == out.nva[0].name[0]);
538 CU_ASSERT(NULL == out.nva[0].value);
539 CU_ASSERT(0 == out.nva[0].valuelen);
540
541 nva_out_reset(&out, mem);
542 nghttp2_bufs_free(&bufs);
543 nghttp2_hd_inflate_free(&inflater);
544 }
545
test_nghttp2_hd_inflate_expect_table_size_update(void)546 void test_nghttp2_hd_inflate_expect_table_size_update(void) {
547 nghttp2_hd_inflater inflater;
548 nghttp2_bufs bufs;
549 nghttp2_mem *mem;
550 /* Indexed Header: :method: GET */
551 uint8_t data[] = {0x82};
552 nva_out out;
553
554 mem = nghttp2_mem_default();
555 frame_pack_bufs_init(&bufs);
556 nva_out_init(&out);
557
558 nghttp2_bufs_add(&bufs, data, sizeof(data));
559 nghttp2_hd_inflate_init(&inflater, mem);
560 /* This will make inflater require table size update in the next
561 inflation. */
562 nghttp2_hd_inflate_change_table_size(&inflater, 4095);
563 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
564 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
565 inflate_hd(&inflater, &out, &bufs, 0, mem));
566
567 nva_out_reset(&out, mem);
568 nghttp2_hd_inflate_free(&inflater);
569
570 /* This does not require for encoder to emit table size update since
571 * size is not changed. */
572 nghttp2_hd_inflate_init(&inflater, mem);
573 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
574 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) ==
575 inflate_hd(&inflater, &out, &bufs, 0, mem));
576
577 nva_out_reset(&out, mem);
578 nghttp2_hd_inflate_free(&inflater);
579
580 /* This does not require for encodre to emit table size update since
581 new size is larger than current size. */
582 nghttp2_hd_inflate_init(&inflater, mem);
583 nghttp2_hd_inflate_change_table_size(&inflater, 4097);
584 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) ==
585 inflate_hd(&inflater, &out, &bufs, 0, mem));
586
587 nva_out_reset(&out, mem);
588 nghttp2_hd_inflate_free(&inflater);
589
590 /* Received table size is strictly larger than minimum table size */
591 nghttp2_hd_inflate_init(&inflater, mem);
592 nghttp2_hd_inflate_change_table_size(&inflater, 111);
593 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
594
595 nghttp2_bufs_reset(&bufs);
596 nghttp2_hd_emit_table_size(&bufs, 112);
597
598 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
599 inflate_hd(&inflater, &out, &bufs, 0, mem));
600
601 nva_out_reset(&out, mem);
602 nghttp2_hd_inflate_free(&inflater);
603
604 /* Receiving 2 table size updates, min and last value */
605 nghttp2_hd_inflate_init(&inflater, mem);
606 nghttp2_hd_inflate_change_table_size(&inflater, 111);
607 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
608
609 nghttp2_bufs_reset(&bufs);
610 nghttp2_hd_emit_table_size(&bufs, 111);
611 nghttp2_hd_emit_table_size(&bufs, 4096);
612
613 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) ==
614 inflate_hd(&inflater, &out, &bufs, 0, mem));
615
616 nva_out_reset(&out, mem);
617 nghttp2_hd_inflate_free(&inflater);
618
619 /* 2nd update is larger than last value */
620 nghttp2_hd_inflate_init(&inflater, mem);
621 nghttp2_hd_inflate_change_table_size(&inflater, 111);
622 nghttp2_hd_inflate_change_table_size(&inflater, 4095);
623
624 nghttp2_bufs_reset(&bufs);
625 nghttp2_hd_emit_table_size(&bufs, 111);
626 nghttp2_hd_emit_table_size(&bufs, 4096);
627
628 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
629 inflate_hd(&inflater, &out, &bufs, 0, mem));
630
631 nva_out_reset(&out, mem);
632 nghttp2_hd_inflate_free(&inflater);
633
634 nghttp2_bufs_free(&bufs);
635 }
636
test_nghttp2_hd_inflate_unexpected_table_size_update(void)637 void test_nghttp2_hd_inflate_unexpected_table_size_update(void) {
638 nghttp2_hd_inflater inflater;
639 nghttp2_bufs bufs;
640 nghttp2_mem *mem;
641 /* Indexed Header: :method: GET, followed by table size update.
642 This violates RFC 7541. */
643 uint8_t data[] = {0x82, 0x20};
644 nva_out out;
645
646 mem = nghttp2_mem_default();
647 frame_pack_bufs_init(&bufs);
648 nva_out_init(&out);
649
650 nghttp2_bufs_add(&bufs, data, sizeof(data));
651 nghttp2_hd_inflate_init(&inflater, mem);
652 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
653 inflate_hd(&inflater, &out, &bufs, 0, mem));
654
655 nva_out_reset(&out, mem);
656 nghttp2_bufs_free(&bufs);
657 nghttp2_hd_inflate_free(&inflater);
658 }
659
test_nghttp2_hd_ringbuf_reserve(void)660 void test_nghttp2_hd_ringbuf_reserve(void) {
661 nghttp2_hd_deflater deflater;
662 nghttp2_hd_inflater inflater;
663 nghttp2_nv nv;
664 nghttp2_bufs bufs;
665 nva_out out;
666 int i;
667 ssize_t rv;
668 ssize_t blocklen;
669 nghttp2_mem *mem;
670
671 mem = nghttp2_mem_default();
672 frame_pack_bufs_init(&bufs);
673 nva_out_init(&out);
674
675 nv.flags = NGHTTP2_NV_FLAG_NONE;
676 nv.name = (uint8_t *)"a";
677 nv.namelen = strlen((const char *)nv.name);
678 nv.valuelen = 4;
679 nv.value = mem->malloc(nv.valuelen + 1, NULL);
680 memset(nv.value, 0, nv.valuelen);
681
682 nghttp2_hd_deflate_init2(&deflater, 8000, mem);
683 nghttp2_hd_inflate_init(&inflater, mem);
684
685 nghttp2_hd_inflate_change_table_size(&inflater, 8000);
686 nghttp2_hd_deflate_change_table_size(&deflater, 8000);
687
688 for (i = 0; i < 150; ++i) {
689 memcpy(nv.value, &i, sizeof(i));
690 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv, 1);
691 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
692
693 CU_ASSERT(0 == rv);
694 CU_ASSERT(blocklen > 0);
695
696 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
697
698 CU_ASSERT(1 == out.nvlen);
699 assert_nv_equal(&nv, out.nva, 1, mem);
700
701 nva_out_reset(&out, mem);
702 nghttp2_bufs_reset(&bufs);
703 }
704
705 nghttp2_bufs_free(&bufs);
706 nghttp2_hd_inflate_free(&inflater);
707 nghttp2_hd_deflate_free(&deflater);
708
709 mem->free(nv.value, NULL);
710 }
711
test_nghttp2_hd_change_table_size(void)712 void test_nghttp2_hd_change_table_size(void) {
713 nghttp2_hd_deflater deflater;
714 nghttp2_hd_inflater inflater;
715 nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
716 nghttp2_nv nva2[] = {MAKE_NV(":path", "/")};
717 nghttp2_bufs bufs;
718 ssize_t rv;
719 nva_out out;
720 ssize_t blocklen;
721 nghttp2_mem *mem;
722
723 mem = nghttp2_mem_default();
724 frame_pack_bufs_init(&bufs);
725
726 nva_out_init(&out);
727
728 nghttp2_hd_deflate_init(&deflater, mem);
729 nghttp2_hd_inflate_init(&inflater, mem);
730
731 /* inflater changes notifies 8000 max header table size */
732 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
733 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
734
735 CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
736
737 CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
738 CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
739
740 /* This will emit encoding context update with header table size 4096 */
741 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
742 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
743
744 CU_ASSERT(0 == rv);
745 CU_ASSERT(blocklen > 0);
746 CU_ASSERT(2 == deflater.ctx.hd_table.len);
747 CU_ASSERT(63 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
748 CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
749
750 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
751 CU_ASSERT(2 == inflater.ctx.hd_table.len);
752 CU_ASSERT(63 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
753 CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
754 CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
755
756 nva_out_reset(&out, mem);
757 nghttp2_bufs_reset(&bufs);
758
759 /* inflater changes header table size to 1024 */
760 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 1024));
761 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 1024));
762
763 CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
764
765 CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
766 CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
767
768 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
769 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
770
771 CU_ASSERT(0 == rv);
772 CU_ASSERT(blocklen > 0);
773 CU_ASSERT(2 == deflater.ctx.hd_table.len);
774 CU_ASSERT(63 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
775 CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
776
777 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
778 CU_ASSERT(2 == inflater.ctx.hd_table.len);
779 CU_ASSERT(63 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
780 CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
781 CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
782
783 nva_out_reset(&out, mem);
784 nghttp2_bufs_reset(&bufs);
785
786 /* inflater changes header table size to 0 */
787 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
788 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
789
790 CU_ASSERT(0 == deflater.ctx.hd_table.len);
791 CU_ASSERT(61 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
792 CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
793
794 CU_ASSERT(0 == inflater.ctx.hd_table.len);
795 CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
796 CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
797 CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
798
799 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
800 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
801
802 CU_ASSERT(0 == rv);
803 CU_ASSERT(blocklen > 0);
804 CU_ASSERT(0 == deflater.ctx.hd_table.len);
805 CU_ASSERT(61 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
806 CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
807
808 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
809 CU_ASSERT(0 == inflater.ctx.hd_table.len);
810 CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
811 CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
812 CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
813
814 nva_out_reset(&out, mem);
815 nghttp2_bufs_reset(&bufs);
816
817 nghttp2_bufs_free(&bufs);
818 nghttp2_hd_inflate_free(&inflater);
819 nghttp2_hd_deflate_free(&deflater);
820
821 /* Check table buffer is expanded */
822 frame_pack_bufs_init(&bufs);
823
824 nghttp2_hd_deflate_init2(&deflater, 8192, mem);
825 nghttp2_hd_inflate_init(&inflater, mem);
826
827 /* First inflater changes header table size to 8000 */
828 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
829 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
830
831 CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
832 CU_ASSERT(8000 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
833 CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
834 CU_ASSERT(4096 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
835 CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
836
837 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
838 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
839
840 CU_ASSERT(0 == rv);
841 CU_ASSERT(blocklen > 0);
842 CU_ASSERT(2 == deflater.ctx.hd_table.len);
843 CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
844
845 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
846 CU_ASSERT(2 == inflater.ctx.hd_table.len);
847 CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
848 CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
849
850 nva_out_reset(&out, mem);
851 nghttp2_bufs_reset(&bufs);
852
853 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383));
854 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383));
855
856 CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
857 CU_ASSERT(8192 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
858
859 CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
860 CU_ASSERT(8000 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
861 CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
862
863 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
864 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
865
866 CU_ASSERT(0 == rv);
867 CU_ASSERT(blocklen > 0);
868 CU_ASSERT(2 == deflater.ctx.hd_table.len);
869 CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
870
871 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
872 CU_ASSERT(2 == inflater.ctx.hd_table.len);
873 CU_ASSERT(8192 == inflater.ctx.hd_table_bufsize_max);
874 CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
875
876 nva_out_reset(&out, mem);
877 nghttp2_bufs_reset(&bufs);
878
879 /* Lastly, check the error condition */
880
881 rv = nghttp2_hd_emit_table_size(&bufs, 25600);
882 CU_ASSERT(rv == 0);
883 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
884 inflate_hd(&inflater, &out, &bufs, 0, mem));
885
886 nva_out_reset(&out, mem);
887 nghttp2_bufs_reset(&bufs);
888
889 nghttp2_hd_inflate_free(&inflater);
890 nghttp2_hd_deflate_free(&deflater);
891
892 /* Check that encoder can handle the case where its allowable buffer
893 size is less than default size, 4096 */
894 nghttp2_hd_deflate_init2(&deflater, 1024, mem);
895 nghttp2_hd_inflate_init(&inflater, mem);
896
897 CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
898
899 /* This emits context update with buffer size 1024 */
900 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
901 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
902
903 CU_ASSERT(0 == rv);
904 CU_ASSERT(blocklen > 0);
905 CU_ASSERT(2 == deflater.ctx.hd_table.len);
906 CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
907
908 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
909 CU_ASSERT(2 == inflater.ctx.hd_table.len);
910 CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
911 CU_ASSERT(4096 == inflater.settings_hd_table_bufsize_max);
912
913 nva_out_reset(&out, mem);
914 nghttp2_bufs_reset(&bufs);
915
916 nghttp2_hd_inflate_free(&inflater);
917 nghttp2_hd_deflate_free(&deflater);
918
919 /* Check that table size UINT32_MAX can be received */
920 nghttp2_hd_deflate_init2(&deflater, UINT32_MAX, mem);
921 nghttp2_hd_inflate_init(&inflater, mem);
922
923 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, UINT32_MAX));
924 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, UINT32_MAX));
925
926 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
927 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
928
929 CU_ASSERT(0 == rv);
930 CU_ASSERT(UINT32_MAX == deflater.ctx.hd_table_bufsize_max);
931
932 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
933 CU_ASSERT(UINT32_MAX == inflater.ctx.hd_table_bufsize_max);
934 CU_ASSERT(UINT32_MAX == inflater.settings_hd_table_bufsize_max);
935
936 nva_out_reset(&out, mem);
937 nghttp2_bufs_reset(&bufs);
938
939 nghttp2_hd_inflate_free(&inflater);
940 nghttp2_hd_deflate_free(&deflater);
941
942 /* Check that context update emitted twice */
943 nghttp2_hd_deflate_init2(&deflater, 4096, mem);
944 nghttp2_hd_inflate_init(&inflater, mem);
945
946 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
947 CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 3000));
948 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
949 CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 3000));
950
951 CU_ASSERT(0 == deflater.min_hd_table_bufsize_max);
952 CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max);
953
954 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, 1);
955 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
956
957 CU_ASSERT(0 == rv);
958 CU_ASSERT(3 < blocklen);
959 CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max);
960 CU_ASSERT(UINT32_MAX == deflater.min_hd_table_bufsize_max);
961
962 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
963 CU_ASSERT(3000 == inflater.ctx.hd_table_bufsize_max);
964 CU_ASSERT(3000 == inflater.settings_hd_table_bufsize_max);
965
966 nva_out_reset(&out, mem);
967 nghttp2_bufs_reset(&bufs);
968
969 nghttp2_hd_inflate_free(&inflater);
970 nghttp2_hd_deflate_free(&deflater);
971
972 nghttp2_bufs_free(&bufs);
973 }
974
check_deflate_inflate(nghttp2_hd_deflater * deflater,nghttp2_hd_inflater * inflater,nghttp2_nv * nva,size_t nvlen,nghttp2_mem * mem)975 static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
976 nghttp2_hd_inflater *inflater,
977 nghttp2_nv *nva, size_t nvlen,
978 nghttp2_mem *mem) {
979 nghttp2_bufs bufs;
980 ssize_t blocklen;
981 nva_out out;
982 int rv;
983
984 frame_pack_bufs_init(&bufs);
985
986 nva_out_init(&out);
987 rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen);
988 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
989
990 CU_ASSERT(0 == rv);
991 CU_ASSERT(blocklen >= 0);
992
993 CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
994
995 CU_ASSERT(nvlen == out.nvlen);
996 assert_nv_equal(nva, out.nva, nvlen, mem);
997
998 nva_out_reset(&out, mem);
999 nghttp2_bufs_free(&bufs);
1000 }
1001
test_nghttp2_hd_deflate_inflate(void)1002 void test_nghttp2_hd_deflate_inflate(void) {
1003 nghttp2_hd_deflater deflater;
1004 nghttp2_hd_inflater inflater;
1005 nghttp2_nv nv1[] = {
1006 MAKE_NV(":status", "200 OK"),
1007 MAKE_NV("access-control-allow-origin", "*"),
1008 MAKE_NV("cache-control", "private, max-age=0, must-revalidate"),
1009 MAKE_NV("content-length", "76073"),
1010 MAKE_NV("content-type", "text/html"),
1011 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1012 MAKE_NV("expires", "Sat, 27 Jul 2013 06:22:12 GMT"),
1013 MAKE_NV("server", "Apache"),
1014 MAKE_NV("vary", "foobar"),
1015 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1016 MAKE_NV("x-cache", "MISS from alphabravo"),
1017 MAKE_NV("x-cache-action", "MISS"),
1018 MAKE_NV("x-cache-age", "0"),
1019 MAKE_NV("x-cache-lookup", "MISS from alphabravo:3128"),
1020 MAKE_NV("x-lb-nocache", "true"),
1021 };
1022 nghttp2_nv nv2[] = {
1023 MAKE_NV(":status", "304 Not Modified"),
1024 MAKE_NV("age", "0"),
1025 MAKE_NV("cache-control", "max-age=56682045"),
1026 MAKE_NV("content-type", "text/css"),
1027 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1028 MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1029 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:15 GMT"),
1030 MAKE_NV("vary", "Accept-Encoding"),
1031 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1032 MAKE_NV("x-cache", "HIT from alphabravo"),
1033 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128")};
1034 nghttp2_nv nv3[] = {
1035 MAKE_NV(":status", "304 Not Modified"),
1036 MAKE_NV("age", "0"),
1037 MAKE_NV("cache-control", "max-age=56682072"),
1038 MAKE_NV("content-type", "text/css"),
1039 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1040 MAKE_NV("expires", "Thu, 14 May 2015 07:23:24 GMT"),
1041 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:13 GMT"),
1042 MAKE_NV("vary", "Accept-Encoding"),
1043 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1044 MAKE_NV("x-cache", "HIT from alphabravo"),
1045 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1046 };
1047 nghttp2_nv nv4[] = {
1048 MAKE_NV(":status", "304 Not Modified"),
1049 MAKE_NV("age", "0"),
1050 MAKE_NV("cache-control", "max-age=56682022"),
1051 MAKE_NV("content-type", "text/css"),
1052 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1053 MAKE_NV("expires", "Thu, 14 May 2015 07:22:34 GMT"),
1054 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:14 GMT"),
1055 MAKE_NV("vary", "Accept-Encoding"),
1056 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1057 MAKE_NV("x-cache", "HIT from alphabravo"),
1058 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1059 };
1060 nghttp2_nv nv5[] = {
1061 MAKE_NV(":status", "304 Not Modified"),
1062 MAKE_NV("age", "0"),
1063 MAKE_NV("cache-control", "max-age=4461139"),
1064 MAKE_NV("content-type", "application/x-javascript"),
1065 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1066 MAKE_NV("expires", "Mon, 16 Sep 2013 21:34:31 GMT"),
1067 MAKE_NV("last-modified", "Thu, 05 May 2011 09:15:59 GMT"),
1068 MAKE_NV("vary", "Accept-Encoding"),
1069 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1070 MAKE_NV("x-cache", "HIT from alphabravo"),
1071 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1072 };
1073 nghttp2_nv nv6[] = {
1074 MAKE_NV(":status", "304 Not Modified"),
1075 MAKE_NV("age", "0"),
1076 MAKE_NV("cache-control", "max-age=18645951"),
1077 MAKE_NV("content-type", "application/x-javascript"),
1078 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1079 MAKE_NV("expires", "Fri, 28 Feb 2014 01:48:03 GMT"),
1080 MAKE_NV("last-modified", "Tue, 12 Jul 2011 16:02:59 GMT"),
1081 MAKE_NV("vary", "Accept-Encoding"),
1082 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1083 MAKE_NV("x-cache", "HIT from alphabravo"),
1084 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1085 };
1086 nghttp2_nv nv7[] = {
1087 MAKE_NV(":status", "304 Not Modified"),
1088 MAKE_NV("age", "0"),
1089 MAKE_NV("cache-control", "max-age=31536000"),
1090 MAKE_NV("content-type", "application/javascript"),
1091 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1092 MAKE_NV("etag", "\"6807-4dc5b54e0dcc0\""),
1093 MAKE_NV("expires", "Wed, 21 May 2014 08:32:17 GMT"),
1094 MAKE_NV("last-modified", "Fri, 10 May 2013 11:18:51 GMT"),
1095 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1096 MAKE_NV("x-cache", "HIT from alphabravo"),
1097 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1098 };
1099 nghttp2_nv nv8[] = {
1100 MAKE_NV(":status", "304 Not Modified"),
1101 MAKE_NV("age", "0"),
1102 MAKE_NV("cache-control", "max-age=31536000"),
1103 MAKE_NV("content-type", "application/javascript"),
1104 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1105 MAKE_NV("etag", "\"41c6-4de7d28585b00\""),
1106 MAKE_NV("expires", "Thu, 12 Jun 2014 10:00:58 GMT"),
1107 MAKE_NV("last-modified", "Thu, 06 Jun 2013 14:30:36 GMT"),
1108 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1109 MAKE_NV("x-cache", "HIT from alphabravo"),
1110 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1111 };
1112 nghttp2_nv nv9[] = {
1113 MAKE_NV(":status", "304 Not Modified"),
1114 MAKE_NV("age", "0"),
1115 MAKE_NV("cache-control", "max-age=31536000"),
1116 MAKE_NV("content-type", "application/javascript"),
1117 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1118 MAKE_NV("etag", "\"19d6e-4dc5b35a541c0\""),
1119 MAKE_NV("expires", "Wed, 21 May 2014 08:32:18 GMT"),
1120 MAKE_NV("last-modified", "Fri, 10 May 2013 11:10:07 GMT"),
1121 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1122 MAKE_NV("x-cache", "HIT from alphabravo"),
1123 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1124 };
1125 nghttp2_nv nv10[] = {
1126 MAKE_NV(":status", "304 Not Modified"),
1127 MAKE_NV("age", "0"),
1128 MAKE_NV("cache-control", "max-age=56682045"),
1129 MAKE_NV("content-type", "text/css"),
1130 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1131 MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1132 MAKE_NV("last-modified", "Tue, 14 May 2013 07:21:53 GMT"),
1133 MAKE_NV("vary", "Accept-Encoding"),
1134 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1135 MAKE_NV("x-cache", "HIT from alphabravo"),
1136 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1137 };
1138 nghttp2_mem *mem;
1139
1140 mem = nghttp2_mem_default();
1141
1142 nghttp2_hd_deflate_init(&deflater, mem);
1143 nghttp2_hd_inflate_init(&inflater, mem);
1144
1145 check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1), mem);
1146 check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2), mem);
1147 check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3), mem);
1148 check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4), mem);
1149 check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5), mem);
1150 check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6), mem);
1151 check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7), mem);
1152 check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8), mem);
1153 check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9), mem);
1154 check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10), mem);
1155
1156 nghttp2_hd_inflate_free(&inflater);
1157 nghttp2_hd_deflate_free(&deflater);
1158 }
1159
test_nghttp2_hd_no_index(void)1160 void test_nghttp2_hd_no_index(void) {
1161 nghttp2_hd_deflater deflater;
1162 nghttp2_hd_inflater inflater;
1163 nghttp2_bufs bufs;
1164 ssize_t blocklen;
1165 nghttp2_nv nva[] = {
1166 MAKE_NV(":method", "GET"), MAKE_NV(":method", "POST"),
1167 MAKE_NV(":path", "/foo"), MAKE_NV("version", "HTTP/1.1"),
1168 MAKE_NV(":method", "GET"),
1169 };
1170 size_t i;
1171 nva_out out;
1172 int rv;
1173 nghttp2_mem *mem;
1174
1175 mem = nghttp2_mem_default();
1176
1177 /* 1st :method: GET can be indexable, last one is not */
1178 for (i = 1; i < ARRLEN(nva); ++i) {
1179 nva[i].flags = NGHTTP2_NV_FLAG_NO_INDEX;
1180 }
1181
1182 frame_pack_bufs_init(&bufs);
1183
1184 nva_out_init(&out);
1185
1186 nghttp2_hd_deflate_init(&deflater, mem);
1187 nghttp2_hd_inflate_init(&inflater, mem);
1188
1189 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1190 blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
1191
1192 CU_ASSERT(0 == rv);
1193 CU_ASSERT(blocklen > 0);
1194 CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
1195
1196 CU_ASSERT(ARRLEN(nva) == out.nvlen);
1197 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1198
1199 CU_ASSERT(out.nva[0].flags == NGHTTP2_NV_FLAG_NONE);
1200 for (i = 1; i < ARRLEN(nva); ++i) {
1201 CU_ASSERT(out.nva[i].flags == NGHTTP2_NV_FLAG_NO_INDEX);
1202 }
1203
1204 nva_out_reset(&out, mem);
1205
1206 nghttp2_bufs_free(&bufs);
1207 nghttp2_hd_inflate_free(&inflater);
1208 nghttp2_hd_deflate_free(&deflater);
1209 }
1210
test_nghttp2_hd_deflate_bound(void)1211 void test_nghttp2_hd_deflate_bound(void) {
1212 nghttp2_hd_deflater deflater;
1213 nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), MAKE_NV("alpha", "bravo")};
1214 nghttp2_bufs bufs;
1215 size_t bound, bound2;
1216 nghttp2_mem *mem;
1217
1218 mem = nghttp2_mem_default();
1219 frame_pack_bufs_init(&bufs);
1220
1221 nghttp2_hd_deflate_init(&deflater, mem);
1222
1223 bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1224
1225 CU_ASSERT(12 + 6 * 2 * 2 + nva[0].namelen + nva[0].valuelen + nva[1].namelen +
1226 nva[1].valuelen ==
1227 bound);
1228
1229 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1230
1231 CU_ASSERT(bound > (size_t)nghttp2_bufs_len(&bufs));
1232
1233 bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1234
1235 CU_ASSERT(bound == bound2);
1236
1237 nghttp2_bufs_free(&bufs);
1238 nghttp2_hd_deflate_free(&deflater);
1239 }
1240
test_nghttp2_hd_public_api(void)1241 void test_nghttp2_hd_public_api(void) {
1242 nghttp2_hd_deflater *deflater;
1243 nghttp2_hd_inflater *inflater;
1244 nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
1245 uint8_t buf[4096];
1246 size_t buflen;
1247 ssize_t blocklen;
1248 nghttp2_bufs bufs;
1249 nghttp2_mem *mem;
1250
1251 mem = nghttp2_mem_default();
1252
1253 CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
1254 CU_ASSERT(0 == nghttp2_hd_inflate_new(&inflater));
1255
1256 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1257
1258 blocklen = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, ARRLEN(nva));
1259
1260 CU_ASSERT(blocklen > 0);
1261
1262 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1263 bufs.head->buf.last += blocklen;
1264
1265 CU_ASSERT(blocklen == inflate_hd(inflater, NULL, &bufs, 0, mem));
1266
1267 nghttp2_bufs_wrap_free(&bufs);
1268
1269 nghttp2_hd_inflate_del(inflater);
1270 nghttp2_hd_deflate_del(deflater);
1271
1272 /* See NGHTTP2_ERR_INSUFF_BUFSIZE */
1273 CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
1274
1275 blocklen = nghttp2_hd_deflate_hd(deflater, buf, (size_t)(blocklen - 1), nva,
1276 ARRLEN(nva));
1277
1278 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1279
1280 nghttp2_hd_deflate_del(deflater);
1281 }
1282
test_nghttp2_hd_deflate_hd_vec(void)1283 void test_nghttp2_hd_deflate_hd_vec(void) {
1284 nghttp2_hd_deflater *deflater;
1285 nghttp2_hd_inflater *inflater;
1286 nghttp2_nv nva[] = {
1287 MAKE_NV(":method", "PUT"),
1288 MAKE_NV(":scheme", "https"),
1289 MAKE_NV(":authority", "localhost:3000"),
1290 MAKE_NV(":path", "/usr/foo/alpha/bravo"),
1291 MAKE_NV("content-type", "image/png"),
1292 MAKE_NV("content-length", "1000000007"),
1293 };
1294 uint8_t buf[4096];
1295 ssize_t blocklen;
1296 nghttp2_mem *mem;
1297 nghttp2_vec vec[256];
1298 size_t buflen;
1299 nghttp2_bufs bufs;
1300 nva_out out;
1301 size_t i;
1302
1303 mem = nghttp2_mem_default();
1304
1305 nva_out_init(&out);
1306
1307 nghttp2_hd_deflate_new(&deflater, 4096);
1308 nghttp2_hd_inflate_new(&inflater);
1309
1310 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1311
1312 vec[0].base = &buf[0];
1313 vec[0].len = buflen / 2;
1314 vec[1].base = &buf[buflen / 2];
1315 vec[1].len = buflen / 2;
1316
1317 blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva));
1318
1319 CU_ASSERT(blocklen > 0);
1320
1321 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1322 bufs.head->buf.last += blocklen;
1323
1324 CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
1325
1326 CU_ASSERT(ARRLEN(nva) == out.nvlen);
1327 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1328
1329 nghttp2_bufs_wrap_free(&bufs);
1330
1331 nghttp2_hd_inflate_del(inflater);
1332 nghttp2_hd_deflate_del(deflater);
1333 nva_out_reset(&out, mem);
1334
1335 /* check the case when veclen is 0 */
1336 nghttp2_hd_deflate_new(&deflater, 4096);
1337 nghttp2_hd_inflate_new(&inflater);
1338
1339 blocklen = nghttp2_hd_deflate_hd_vec(deflater, NULL, 0, nva, ARRLEN(nva));
1340
1341 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1342
1343 nghttp2_hd_inflate_del(inflater);
1344 nghttp2_hd_deflate_del(deflater);
1345
1346 /* check the case when chunk length is 0 */
1347 vec[0].base = NULL;
1348 vec[0].len = 0;
1349 vec[1].base = NULL;
1350 vec[1].len = 0;
1351
1352 nghttp2_hd_deflate_new(&deflater, 4096);
1353 nghttp2_hd_inflate_new(&inflater);
1354
1355 blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva));
1356
1357 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1358
1359 nghttp2_hd_inflate_del(inflater);
1360 nghttp2_hd_deflate_del(deflater);
1361
1362 /* check the case where chunk size differs in each chunk */
1363 nghttp2_hd_deflate_new(&deflater, 4096);
1364 nghttp2_hd_inflate_new(&inflater);
1365
1366 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1367
1368 vec[0].base = &buf[0];
1369 vec[0].len = buflen / 2;
1370 vec[1].base = &buf[buflen / 2];
1371 vec[1].len = (buflen / 2) + 1;
1372
1373 blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva));
1374
1375 CU_ASSERT(blocklen > 0);
1376
1377 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1378 bufs.head->buf.last += blocklen;
1379
1380 CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
1381 CU_ASSERT(ARRLEN(nva) == out.nvlen);
1382 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1383
1384 nghttp2_bufs_wrap_free(&bufs);
1385
1386 nghttp2_hd_inflate_del(inflater);
1387 nghttp2_hd_deflate_del(deflater);
1388 nva_out_reset(&out, mem);
1389
1390 /* check the case where chunk size is 1 */
1391 nghttp2_hd_deflate_new(&deflater, 4096);
1392 nghttp2_hd_inflate_new(&inflater);
1393
1394 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1395
1396 assert(buflen <= ARRLEN(vec));
1397
1398 for (i = 0; i < buflen; ++i) {
1399 vec[i].base = &buf[i];
1400 vec[i].len = 1;
1401 }
1402
1403 blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, buflen, nva, ARRLEN(nva));
1404
1405 CU_ASSERT(blocklen > 0);
1406
1407 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1408 bufs.head->buf.last += blocklen;
1409
1410 CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
1411 CU_ASSERT(ARRLEN(nva) == out.nvlen);
1412 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1413
1414 nghttp2_bufs_wrap_free(&bufs);
1415
1416 nghttp2_hd_inflate_del(inflater);
1417 nghttp2_hd_deflate_del(deflater);
1418 nva_out_reset(&out, mem);
1419 }
1420
encode_length(uint8_t * buf,uint64_t n,size_t prefix)1421 static size_t encode_length(uint8_t *buf, uint64_t n, size_t prefix) {
1422 size_t k = (size_t)((1 << prefix) - 1);
1423 size_t len = 0;
1424 *buf = (uint8_t)(*buf & ~k);
1425 if (n >= k) {
1426 *buf = (uint8_t)(*buf | k);
1427 ++buf;
1428 n -= k;
1429 ++len;
1430 } else {
1431 *buf = (uint8_t)(*buf | n);
1432 ++buf;
1433 return 1;
1434 }
1435 do {
1436 ++len;
1437 if (n >= 128) {
1438 *buf = (uint8_t)((1 << 7) | (n & 0x7f));
1439 ++buf;
1440 n >>= 7;
1441 } else {
1442 *buf++ = (uint8_t)n;
1443 break;
1444 }
1445 } while (n);
1446 return len;
1447 }
1448
test_nghttp2_hd_decode_length(void)1449 void test_nghttp2_hd_decode_length(void) {
1450 uint32_t out;
1451 size_t shift;
1452 int fin;
1453 uint8_t buf[16];
1454 uint8_t *bufp;
1455 size_t len;
1456 ssize_t rv;
1457 size_t i;
1458
1459 memset(buf, 0, sizeof(buf));
1460 len = encode_length(buf, UINT32_MAX, 7);
1461
1462 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1463
1464 CU_ASSERT((ssize_t)len == rv);
1465 CU_ASSERT(0 != fin);
1466 CU_ASSERT(UINT32_MAX == out);
1467
1468 /* Make sure that we can decode integer if we feed 1 byte at a
1469 time */
1470 out = 0;
1471 shift = 0;
1472 fin = 0;
1473 bufp = buf;
1474
1475 for (i = 0; i < len; ++i, ++bufp) {
1476 rv = nghttp2_hd_decode_length(&out, &shift, &fin, out, shift, bufp,
1477 bufp + 1, 7);
1478
1479 CU_ASSERT(rv == 1);
1480
1481 if (fin) {
1482 break;
1483 }
1484 }
1485
1486 CU_ASSERT(i == len - 1);
1487 CU_ASSERT(0 != fin);
1488 CU_ASSERT(UINT32_MAX == out);
1489
1490 /* Check overflow case */
1491 memset(buf, 0, sizeof(buf));
1492 len = encode_length(buf, 1ll << 32, 7);
1493
1494 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1495
1496 CU_ASSERT(-1 == rv);
1497
1498 /* Check the case that shift goes beyond 32 bits */
1499 buf[0] = 255;
1500 buf[1] = 128;
1501 buf[2] = 128;
1502 buf[3] = 128;
1503 buf[4] = 128;
1504 buf[5] = 128;
1505 buf[6] = 1;
1506
1507 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + 7, 8);
1508
1509 CU_ASSERT(-1 == rv);
1510 }
1511
test_nghttp2_hd_huff_encode(void)1512 void test_nghttp2_hd_huff_encode(void) {
1513 int rv;
1514 ssize_t len;
1515 nghttp2_buf outbuf;
1516 nghttp2_bufs bufs;
1517 nghttp2_hd_huff_decode_context ctx;
1518 const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
1519 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
1520 uint8_t b[256];
1521
1522 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1523 frame_pack_bufs_init(&bufs);
1524
1525 rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
1526
1527 CU_ASSERT(rv == 0);
1528
1529 nghttp2_hd_huff_decode_context_init(&ctx);
1530
1531 len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos,
1532 nghttp2_bufs_len(&bufs), 1);
1533
1534 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == len);
1535 CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_buf_len(&outbuf));
1536
1537 CU_ASSERT(0 == memcmp(t1, outbuf.pos, sizeof(t1)));
1538
1539 nghttp2_bufs_free(&bufs);
1540 }
1541
test_nghttp2_hd_huff_decode(void)1542 void test_nghttp2_hd_huff_decode(void) {
1543 const uint8_t e[] = {0x1f, 0xff, 0xff, 0xff, 0xff, 0xff};
1544 nghttp2_hd_huff_decode_context ctx;
1545 nghttp2_buf outbuf;
1546 uint8_t b[256];
1547 ssize_t len;
1548
1549 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1550 nghttp2_hd_huff_decode_context_init(&ctx);
1551 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 1, 1);
1552
1553 CU_ASSERT(1 == len);
1554 CU_ASSERT(0 == memcmp("a", outbuf.pos, 1));
1555
1556 /* Premature sequence must elicit decoding error */
1557 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1558 nghttp2_hd_huff_decode_context_init(&ctx);
1559 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 1);
1560
1561 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == len);
1562
1563 /* Fully decoding EOS is error */
1564 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1565 nghttp2_hd_huff_decode_context_init(&ctx);
1566 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 6);
1567
1568 CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == len);
1569
1570 /* Check failure state */
1571 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1572 nghttp2_hd_huff_decode_context_init(&ctx);
1573 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 5, 0);
1574
1575 CU_ASSERT(5 == len);
1576 CU_ASSERT(nghttp2_hd_huff_decode_failure_state(&ctx));
1577 }
1578