2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
25 #include "nghttp2_hd.h"
31 #include "nghttp2_helper.h"
32 #include "nghttp2_int.h"
34 #define STATIC_TABLE_LENGTH 61
36 /* Make scalar initialization form of nghttp2_nv */
37 #define MAKE_STATIC_ENT(I, N, V, NH, VH) \
40 { (uint8_t *) N, (uint8_t *)V, sizeof(N) - 1, sizeof(V) - 1, 0 } \
41 , NH, VH, 1, NGHTTP2_HD_FLAG_NONE \
46 /* Generated by mkstatictbl.py */
47 /* Sorted by hash(name) and its table index */
48 static nghttp2_hd_static_entry static_table[] = {
49 MAKE_STATIC_ENT(20, "age", "", 96511u, 0u),
50 MAKE_STATIC_ENT(59, "via", "", 116750u, 0u),
51 MAKE_STATIC_ENT(32, "date", "", 3076014u, 0u),
52 MAKE_STATIC_ENT(33, "etag", "", 3123477u, 0u),
53 MAKE_STATIC_ENT(36, "from", "", 3151786u, 0u),
54 MAKE_STATIC_ENT(37, "host", "", 3208616u, 0u),
55 MAKE_STATIC_ENT(44, "link", "", 3321850u, 0u),
56 MAKE_STATIC_ENT(58, "vary", "", 3612210u, 0u),
57 MAKE_STATIC_ENT(38, "if-match", "", 34533653u, 0u),
58 MAKE_STATIC_ENT(41, "if-range", "", 39145613u, 0u),
59 MAKE_STATIC_ENT(3, ":path", "/", 56997727u, 47u),
60 MAKE_STATIC_ENT(4, ":path", "/index.html", 56997727u, 2144181430u),
61 MAKE_STATIC_ENT(21, "allow", "", 92906313u, 0u),
62 MAKE_STATIC_ENT(49, "range", "", 108280125u, 0u),
63 MAKE_STATIC_ENT(14, "accept-charset", "", 124285319u, 0u),
64 MAKE_STATIC_ENT(43, "last-modified", "", 150043680u, 0u),
65 MAKE_STATIC_ENT(48, "proxy-authorization", "", 329532250u, 0u),
66 MAKE_STATIC_ENT(57, "user-agent", "", 486342275u, 0u),
67 MAKE_STATIC_ENT(40, "if-none-match", "", 646073760u, 0u),
68 MAKE_STATIC_ENT(30, "content-type", "", 785670158u, 0u),
69 MAKE_STATIC_ENT(16, "accept-language", "", 802785917u, 0u),
70 MAKE_STATIC_ENT(50, "referer", "", 1085069613u, 0u),
71 MAKE_STATIC_ENT(51, "refresh", "", 1085444827u, 0u),
72 MAKE_STATIC_ENT(55, "strict-transport-security", "", 1153852136u, 0u),
73 MAKE_STATIC_ENT(54, "set-cookie", "", 1237214767u, 0u),
74 MAKE_STATIC_ENT(56, "transfer-encoding", "", 1274458357u, 0u),
75 MAKE_STATIC_ENT(17, "accept-ranges", "", 1397189435u, 0u),
76 MAKE_STATIC_ENT(42, "if-unmodified-since", "", 1454068927u, 0u),
77 MAKE_STATIC_ENT(46, "max-forwards", "", 1619948695u, 0u),
78 MAKE_STATIC_ENT(45, "location", "", 1901043637u, 0u),
79 MAKE_STATIC_ENT(52, "retry-after", "", 1933352567u, 0u),
80 MAKE_STATIC_ENT(25, "content-encoding", "", 2095084583u, 0u),
81 MAKE_STATIC_ENT(28, "content-location", "", 2284906121u, 0u),
82 MAKE_STATIC_ENT(39, "if-modified-since", "", 2302095846u, 0u),
83 MAKE_STATIC_ENT(18, "accept", "", 2871506184u, 0u),
84 MAKE_STATIC_ENT(29, "content-range", "", 2878374633u, 0u),
85 MAKE_STATIC_ENT(22, "authorization", "", 2909397113u, 0u),
86 MAKE_STATIC_ENT(31, "cookie", "", 2940209764u, 0u),
87 MAKE_STATIC_ENT(0, ":authority", "", 2962729033u, 0u),
88 MAKE_STATIC_ENT(35, "expires", "", 2985731892u, 0u),
89 MAKE_STATIC_ENT(34, "expect", "", 3005803609u, 0u),
90 MAKE_STATIC_ENT(24, "content-disposition", "", 3027699811u, 0u),
91 MAKE_STATIC_ENT(26, "content-language", "", 3065240108u, 0u),
92 MAKE_STATIC_ENT(1, ":method", "GET", 3153018267u, 70454u),
93 MAKE_STATIC_ENT(2, ":method", "POST", 3153018267u, 2461856u),
94 MAKE_STATIC_ENT(27, "content-length", "", 3162187450u, 0u),
95 MAKE_STATIC_ENT(19, "access-control-allow-origin", "", 3297999203u, 0u),
96 MAKE_STATIC_ENT(5, ":scheme", "http", 3322585695u, 3213448u),
97 MAKE_STATIC_ENT(6, ":scheme", "https", 3322585695u, 99617003u),
98 MAKE_STATIC_ENT(7, ":status", "200", 3338091692u, 49586u),
99 MAKE_STATIC_ENT(8, ":status", "204", 3338091692u, 49590u),
100 MAKE_STATIC_ENT(9, ":status", "206", 3338091692u, 49592u),
101 MAKE_STATIC_ENT(10, ":status", "304", 3338091692u, 50551u),
102 MAKE_STATIC_ENT(11, ":status", "400", 3338091692u, 51508u),
103 MAKE_STATIC_ENT(12, ":status", "404", 3338091692u, 51512u),
104 MAKE_STATIC_ENT(13, ":status", "500", 3338091692u, 52469u),
105 MAKE_STATIC_ENT(53, "server", "", 3389140803u, 0u),
106 MAKE_STATIC_ENT(47, "proxy-authenticate", "", 3993199572u, 0u),
107 MAKE_STATIC_ENT(60, "www-authenticate", "", 4051929931u, 0u),
108 MAKE_STATIC_ENT(23, "cache-control", "", 4086191634u, 0u),
109 MAKE_STATIC_ENT(15, "accept-encoding", "gzip, deflate", 4127597688u,
113 /* Index to the position in static_table */
114 const size_t static_table_index[] = {
115 38, 43, 44, 10, 11, 47, 48, 49, 50, 51, 52, 53, 54, 55, 14, 60,
116 20, 26, 34, 46, 0, 12, 36, 59, 41, 31, 42, 45, 32, 35, 19, 37,
117 2, 3, 40, 39, 4, 5, 8, 33, 18, 9, 27, 15, 6, 29, 28, 57,
118 16, 13, 21, 22, 30, 56, 24, 23, 25, 17, 7, 1, 58};
120 const size_t NGHTTP2_STATIC_TABLE_LENGTH =
121 sizeof(static_table) / sizeof(static_table[0]);
123 static int memeq(const void *s1, const void *s2, size_t n) {
124 const uint8_t *a = (const uint8_t *)s1, *b = (const uint8_t *)s2;
127 c |= (*a++) ^ (*b++);
133 static uint32_t hash(const uint8_t *s, size_t n) {
142 int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
143 size_t namelen, uint8_t *value, size_t valuelen,
144 uint32_t name_hash, uint32_t value_hash,
148 /* Since nghttp2_hd_entry is used for indexing, ent->nv.flags always
149 NGHTTP2_NV_FLAG_NONE */
150 ent->nv.flags = NGHTTP2_NV_FLAG_NONE;
152 if ((flags & NGHTTP2_HD_FLAG_NAME_ALLOC) &&
153 (flags & NGHTTP2_HD_FLAG_NAME_GIFT) == 0) {
155 /* We should not allow empty header field name */
158 ent->nv.name = nghttp2_memdup(name, namelen, mem);
159 if (ent->nv.name == NULL) {
160 rv = NGHTTP2_ERR_NOMEM;
167 if ((flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) &&
168 (flags & NGHTTP2_HD_FLAG_VALUE_GIFT) == 0) {
170 ent->nv.value = NULL;
172 ent->nv.value = nghttp2_memdup(value, valuelen, mem);
173 if (ent->nv.value == NULL) {
174 rv = NGHTTP2_ERR_NOMEM;
179 ent->nv.value = value;
181 ent->nv.namelen = namelen;
182 ent->nv.valuelen = valuelen;
186 ent->name_hash = name_hash;
187 ent->value_hash = value_hash;
192 if (flags & NGHTTP2_HD_FLAG_NAME_ALLOC) {
193 nghttp2_mem_free(mem, ent->nv.name);
199 void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem) {
200 assert(ent->ref == 0);
201 if (ent->flags & NGHTTP2_HD_FLAG_NAME_ALLOC) {
202 nghttp2_mem_free(mem, ent->nv.name);
204 if (ent->flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) {
205 nghttp2_mem_free(mem, ent->nv.value);
209 static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
212 for (size = 1; size < bufsize; size <<= 1)
214 ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
215 if (ringbuf->buffer == NULL) {
216 return NGHTTP2_ERR_NOMEM;
218 ringbuf->mask = size - 1;
224 static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
226 assert(idx < ringbuf->len);
227 return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
230 static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
234 nghttp2_hd_entry **buffer;
236 if (ringbuf->mask + 1 >= bufsize) {
239 for (size = 1; size < bufsize; size <<= 1)
241 buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
242 if (buffer == NULL) {
243 return NGHTTP2_ERR_NOMEM;
245 for (i = 0; i < ringbuf->len; ++i) {
246 buffer[i] = hd_ringbuf_get(ringbuf, i);
248 nghttp2_mem_free(mem, ringbuf->buffer);
249 ringbuf->buffer = buffer;
250 ringbuf->mask = size - 1;
255 static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
257 if (ringbuf == NULL) {
260 for (i = 0; i < ringbuf->len; ++i) {
261 nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
263 nghttp2_hd_entry_free(ent, mem);
264 nghttp2_mem_free(mem, ent);
266 nghttp2_mem_free(mem, ringbuf->buffer);
269 static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
270 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
273 rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
279 ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
285 static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
286 assert(ringbuf->len > 0);
290 static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
294 context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
295 rv = hd_ringbuf_init(&context->hd_table, context->hd_table_bufsize_max /
296 NGHTTP2_HD_ENTRY_OVERHEAD,
302 context->hd_table_bufsize = 0;
306 static void hd_context_free(nghttp2_hd_context *context) {
307 hd_ringbuf_free(&context->hd_table, context->mem);
310 int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
311 return nghttp2_hd_deflate_init2(
312 deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
315 int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
316 size_t deflate_hd_table_bufsize_max,
319 rv = hd_context_init(&deflater->ctx, mem);
324 if (deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
325 deflater->notify_table_size_change = 1;
326 deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max;
328 deflater->notify_table_size_change = 0;
331 deflater->deflate_hd_table_bufsize_max = deflate_hd_table_bufsize_max;
332 deflater->min_hd_table_bufsize_max = UINT32_MAX;
337 int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
340 rv = hd_context_init(&inflater->ctx, mem);
345 inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
347 inflater->ent_keep = NULL;
348 inflater->nv_keep = NULL;
350 inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
351 inflater->state = NGHTTP2_HD_STATE_OPCODE;
353 rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0,
360 inflater->huffman_encoded = 0;
364 inflater->newnamelen = 0;
365 inflater->index_required = 0;
366 inflater->no_index = 0;
371 hd_context_free(&inflater->ctx);
376 static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
379 mem = inflater->ctx.mem;
380 if (inflater->ent_keep) {
381 if (inflater->ent_keep->ref == 0) {
382 nghttp2_hd_entry_free(inflater->ent_keep, mem);
383 nghttp2_mem_free(mem, inflater->ent_keep);
385 inflater->ent_keep = NULL;
388 nghttp2_mem_free(mem, inflater->nv_keep);
389 inflater->nv_keep = NULL;
392 void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
393 hd_context_free(&deflater->ctx);
396 void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
397 hd_inflate_keep_free(inflater);
398 nghttp2_bufs_free(&inflater->nvbufs);
399 hd_context_free(&inflater->ctx);
402 static size_t entry_room(size_t namelen, size_t valuelen) {
403 return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
406 static int emit_indexed_header(nghttp2_nv *nv_out, nghttp2_hd_entry *ent) {
407 DEBUGF(fprintf(stderr, "inflatehd: header emission: "));
408 DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr));
409 DEBUGF(fprintf(stderr, ": "));
410 DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr));
411 DEBUGF(fprintf(stderr, "\n"));
412 /* ent->ref may be 0. This happens if the encoder emits literal
413 block larger than header table capacity with indexing. */
418 static int emit_literal_header(nghttp2_nv *nv_out, nghttp2_nv *nv) {
419 DEBUGF(fprintf(stderr, "inflatehd: header emission: "));
420 DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr));
421 DEBUGF(fprintf(stderr, ": "));
422 DEBUGF(fwrite(nv->value, nv->valuelen, 1, stderr));
423 DEBUGF(fprintf(stderr, "\n"));
428 static size_t count_encoded_length(size_t n, size_t prefix) {
429 size_t k = (1 << prefix) - 1;
439 for (; n >= 128; n >>= 7, ++len)
445 static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
446 size_t k = (1 << prefix) - 1;
447 uint8_t *begin = buf;
459 for (; n >= 128; n >>= 7) {
460 *buf++ = (1 << 7) | (n & 0x7f);
465 return (size_t)(buf - begin);
469 * Decodes |prefix| prefixed integer stored from |in|. The |last|
470 * represents the 1 beyond the last of the valid contiguous memory
471 * region from |in|. The decoded integer must be less than or equal
474 * If the |initial| is nonzero, it is used as a initial value, this
475 * function assumes the |in| starts with intermediate data.
477 * An entire integer is decoded successfully, decoded, the |*final| is
480 * This function stores the decoded integer in |*res| if it succeed,
481 * including partial decoding (in this case, number of shift to make
482 * in the next call will be stored in |*shift_ptr|) and returns number
483 * of bytes processed, or returns -1, indicating decoding error.
485 static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final,
486 uint32_t initial, size_t shift, uint8_t *in,
487 uint8_t *last, size_t prefix) {
488 uint32_t k = (1 << prefix) - 1;
489 uint32_t n = initial;
496 if ((*in & k) != k) {
506 return (ssize_t)(in - start);
510 for (; in != last; ++in, shift += 7) {
511 uint32_t add = *in & 0x7f;
513 if ((UINT32_MAX >> shift) < add) {
514 DEBUGF(fprintf(stderr, "inflate: integer overflow on shift\n"));
520 if (UINT32_MAX - add < n) {
521 DEBUGF(fprintf(stderr, "inflate: integer overflow on addition\n"));
527 if ((*in & (1 << 7)) == 0) {
536 return (ssize_t)(in - start);
541 return (ssize_t)(in + 1 - start);
544 static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
550 DEBUGF(fprintf(stderr, "deflatehd: emit table_size=%zu\n", table_size));
552 blocklen = count_encoded_length(table_size, 5);
554 if (sizeof(sb) < blocklen) {
555 return NGHTTP2_ERR_HEADER_COMP;
562 encode_length(bufp, table_size, 5);
564 rv = nghttp2_bufs_add(bufs, sb, blocklen);
572 static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
578 blocklen = count_encoded_length(idx + 1, 7);
580 DEBUGF(fprintf(stderr, "deflatehd: emit indexed index=%zu, %zu bytes\n", idx,
583 if (sizeof(sb) < blocklen) {
584 return NGHTTP2_ERR_HEADER_COMP;
589 encode_length(bufp, idx + 1, 7);
591 rv = nghttp2_bufs_add(bufs, sb, blocklen);
599 static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
607 enclen = nghttp2_hd_huff_encode_count(str, len);
615 blocklen = count_encoded_length(enclen, 7);
617 DEBUGF(fprintf(stderr, "deflatehd: emit string str="));
618 DEBUGF(fwrite(str, len, 1, stderr));
619 DEBUGF(fprintf(stderr, ", length=%zu, huffman=%d, encoded_length=%zu\n", len,
622 if (sizeof(sb) < blocklen) {
623 return NGHTTP2_ERR_HEADER_COMP;
627 *bufp = huffman ? 1 << 7 : 0;
628 encode_length(bufp, enclen, 7);
630 rv = nghttp2_bufs_add(bufs, sb, blocklen);
636 rv = nghttp2_hd_huff_encode(bufs, str, len);
638 assert(enclen == len);
639 rv = nghttp2_bufs_add(bufs, str, len);
645 static uint8_t pack_first_byte(int inc_indexing, int no_index) {
657 static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
658 const nghttp2_nv *nv, int inc_indexing) {
666 no_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0;
674 DEBUGF(fprintf(stderr, "deflatehd: emit indname index=%zu, valuelen=%zu, "
675 "indexing=%d, no_index=%d\n",
676 idx, nv->valuelen, inc_indexing, no_index));
678 blocklen = count_encoded_length(idx + 1, prefixlen);
680 if (sizeof(sb) < blocklen) {
681 return NGHTTP2_ERR_HEADER_COMP;
686 *bufp = pack_first_byte(inc_indexing, no_index);
688 encode_length(bufp, idx + 1, prefixlen);
690 rv = nghttp2_bufs_add(bufs, sb, blocklen);
695 rv = emit_string(bufs, nv->value, nv->valuelen);
703 static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
708 no_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0;
710 DEBUGF(fprintf(stderr, "deflatehd: emit newname namelen=%zu, valuelen=%zu, "
711 "indexing=%d, no_index=%d\n",
712 nv->namelen, nv->valuelen, inc_indexing, no_index));
714 rv = nghttp2_bufs_addb(bufs, pack_first_byte(inc_indexing, no_index));
719 rv = emit_string(bufs, nv->name, nv->namelen);
724 rv = emit_string(bufs, nv->value, nv->valuelen);
732 static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context,
733 const nghttp2_nv *nv,
736 uint8_t entry_flags) {
738 nghttp2_hd_entry *new_ent;
743 room = entry_room(nv->namelen, nv->valuelen);
745 while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
746 context->hd_table.len > 0) {
748 size_t idx = context->hd_table.len - 1;
749 nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
751 context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
753 DEBUGF(fprintf(stderr, "hpack: remove item from header table: "));
754 DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr));
755 DEBUGF(fprintf(stderr, ": "));
756 DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr));
757 DEBUGF(fprintf(stderr, "\n"));
758 hd_ringbuf_pop_back(&context->hd_table);
759 if (--ent->ref == 0) {
760 nghttp2_hd_entry_free(ent, mem);
761 nghttp2_mem_free(mem, ent);
765 new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
766 if (new_ent == NULL) {
770 rv = nghttp2_hd_entry_init(new_ent, entry_flags, nv->name, nv->namelen,
771 nv->value, nv->valuelen, name_hash, value_hash,
774 nghttp2_mem_free(mem, new_ent);
778 if (room > context->hd_table_bufsize_max) {
779 /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
780 immediately evicted. */
783 rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
788 if ((entry_flags & NGHTTP2_HD_FLAG_NAME_ALLOC) &&
789 (entry_flags & NGHTTP2_HD_FLAG_NAME_GIFT)) {
790 /* nv->name are managed by caller. */
791 new_ent->nv.name = NULL;
792 new_ent->nv.namelen = 0;
794 if ((entry_flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) &&
795 (entry_flags & NGHTTP2_HD_FLAG_VALUE_GIFT)) {
796 /* nv->value are managed by caller. */
797 new_ent->nv.value = NULL;
798 new_ent->nv.valuelen = 0;
801 nghttp2_hd_entry_free(new_ent, mem);
802 nghttp2_mem_free(mem, new_ent);
807 context->hd_table_bufsize += room;
812 static int name_eq(const nghttp2_nv *a, const nghttp2_nv *b) {
813 return a->namelen == b->namelen && memeq(a->name, b->name, a->namelen);
816 static int value_eq(const nghttp2_nv *a, const nghttp2_nv *b) {
817 return a->valuelen == b->valuelen && memeq(a->value, b->value, a->valuelen);
822 /* Nonzero if both name and value are matched. */
823 uint8_t name_value_match;
826 static search_result search_hd_table(nghttp2_hd_context *context,
827 const nghttp2_nv *nv, uint32_t name_hash,
828 uint32_t value_hash) {
829 ssize_t left = -1, right = (ssize_t)STATIC_TABLE_LENGTH;
830 search_result res = {-1, 0};
832 int use_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) == 0;
834 /* Search dynamic table first, so that we can find recently used
837 for (i = 0; i < context->hd_table.len; ++i) {
838 nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i);
839 if (ent->name_hash != name_hash || !name_eq(&ent->nv, nv)) {
843 if (res.index == -1) {
844 res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH);
847 if (ent->value_hash == value_hash && value_eq(&ent->nv, nv)) {
848 res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH);
849 res.name_value_match = 1;
855 while (right - left > 1) {
856 ssize_t mid = (left + right) / 2;
857 nghttp2_hd_entry *ent = &static_table[mid].ent;
858 if (ent->name_hash < name_hash) {
865 for (i = right; i < STATIC_TABLE_LENGTH; ++i) {
866 nghttp2_hd_entry *ent = &static_table[i].ent;
867 if (ent->name_hash != name_hash) {
871 if (name_eq(&ent->nv, nv)) {
872 if (res.index == -1) {
873 res.index = (ssize_t)(static_table[i].index);
875 if (use_index && ent->value_hash == value_hash &&
876 value_eq(&ent->nv, nv)) {
877 res.index = (ssize_t)(static_table[i].index);
878 res.name_value_match = 1;
887 static void hd_context_shrink_table_size(nghttp2_hd_context *context) {
892 while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
893 context->hd_table.len > 0) {
894 size_t idx = context->hd_table.len - 1;
895 nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
896 context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
897 hd_ringbuf_pop_back(&context->hd_table);
898 if (--ent->ref == 0) {
899 nghttp2_hd_entry_free(ent, mem);
900 nghttp2_mem_free(mem, ent);
905 int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
906 size_t settings_hd_table_bufsize_max) {
907 size_t next_bufsize = nghttp2_min(settings_hd_table_bufsize_max,
908 deflater->deflate_hd_table_bufsize_max);
910 deflater->ctx.hd_table_bufsize_max = next_bufsize;
912 deflater->min_hd_table_bufsize_max =
913 nghttp2_min(deflater->min_hd_table_bufsize_max, next_bufsize);
915 deflater->notify_table_size_change = 1;
917 hd_context_shrink_table_size(&deflater->ctx);
921 int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
922 size_t settings_hd_table_bufsize_max) {
923 inflater->settings_hd_table_bufsize_max = settings_hd_table_bufsize_max;
924 inflater->ctx.hd_table_bufsize_max = settings_hd_table_bufsize_max;
925 hd_context_shrink_table_size(&inflater->ctx);
929 #define INDEX_RANGE_VALID(context, idx) \
930 ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
932 static size_t get_max_index(nghttp2_hd_context *context) {
933 return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH - 1;
936 nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
938 assert(INDEX_RANGE_VALID(context, idx));
939 if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
940 return hd_ringbuf_get(&context->hd_table,
941 idx - NGHTTP2_STATIC_TABLE_LENGTH);
943 return &static_table[static_table_index[idx]].ent;
947 #define name_match(NV, NAME) \
948 (nv->namelen == sizeof(NAME) - 1 && memeq(nv->name, NAME, sizeof(NAME) - 1))
950 static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater,
951 const nghttp2_nv *nv) {
952 if ((nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) ||
953 entry_room(nv->namelen, nv->valuelen) >
954 deflater->ctx.hd_table_bufsize_max * 3 / 4) {
958 return !name_match(nv, NGHTTP2_XHD);
959 #else /* !NGHTTP2_XHD */
960 return !name_match(nv, ":path") && !name_match(nv, "content-length") &&
961 !name_match(nv, "set-cookie") && !name_match(nv, "etag") &&
962 !name_match(nv, "if-modified-since") &&
963 !name_match(nv, "if-none-match") && !name_match(nv, "location") &&
964 !name_match(nv, "age");
965 #endif /* !NGHTTP2_XHD */
968 static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
969 const nghttp2_nv *nv) {
974 uint32_t name_hash = hash(nv->name, nv->namelen);
975 uint32_t value_hash = hash(nv->value, nv->valuelen);
978 DEBUGF(fprintf(stderr, "deflatehd: deflating "));
979 DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr));
980 DEBUGF(fprintf(stderr, ": "));
981 DEBUGF(fwrite(nv->value, nv->valuelen, 1, stderr));
982 DEBUGF(fprintf(stderr, "\n"));
984 mem = deflater->ctx.mem;
986 res = search_hd_table(&deflater->ctx, nv, name_hash, value_hash);
990 if (res.name_value_match) {
992 DEBUGF(fprintf(stderr, "deflatehd: name/value match index=%zd\n", idx));
994 rv = emit_indexed_block(bufs, idx);
1002 if (res.index != -1) {
1003 DEBUGF(fprintf(stderr, "deflatehd: name match index=%zd\n", res.index));
1006 if (hd_deflate_should_indexing(deflater, nv)) {
1007 nghttp2_hd_entry *new_ent;
1008 if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) {
1009 nghttp2_nv nv_indname;
1011 nv_indname.name = nghttp2_hd_table_get(&deflater->ctx, idx)->nv.name;
1013 add_hd_table_incremental(&deflater->ctx, &nv_indname, name_hash,
1014 value_hash, NGHTTP2_HD_FLAG_VALUE_ALLOC);
1016 new_ent = add_hd_table_incremental(
1017 &deflater->ctx, nv, name_hash, value_hash,
1018 NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC);
1021 return NGHTTP2_ERR_HEADER_COMP;
1023 if (new_ent->ref == 0) {
1024 nghttp2_hd_entry_free(new_ent, mem);
1025 nghttp2_mem_free(mem, new_ent);
1030 rv = emit_newname_block(bufs, nv, incidx);
1032 rv = emit_indname_block(bufs, idx, nv, incidx);
1041 int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1042 nghttp2_bufs *bufs, const nghttp2_nv *nv,
1047 if (deflater->ctx.bad) {
1048 return NGHTTP2_ERR_HEADER_COMP;
1051 if (deflater->notify_table_size_change) {
1052 size_t min_hd_table_bufsize_max;
1054 min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
1056 deflater->notify_table_size_change = 0;
1057 deflater->min_hd_table_bufsize_max = UINT32_MAX;
1059 if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
1061 rv = emit_table_size(bufs, min_hd_table_bufsize_max);
1068 rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
1075 for (i = 0; i < nvlen; ++i) {
1076 rv = deflate_nv(deflater, bufs, &nv[i]);
1083 fprintf(stderr, "deflatehd: all input name/value pairs were deflated\n"));
1087 DEBUGF(fprintf(stderr, "deflatehd: error return %d\n", rv));
1089 deflater->ctx.bad = 1;
1093 ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
1094 size_t buflen, const nghttp2_nv *nv,
1100 mem = deflater->ctx.mem;
1102 rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
1108 rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1110 buflen = nghttp2_bufs_len(&bufs);
1112 nghttp2_bufs_wrap_free(&bufs);
1114 if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1115 return NGHTTP2_ERR_INSUFF_BUFSIZE;
1122 return (ssize_t)buflen;
1125 size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_,
1126 const nghttp2_nv *nva, size_t nvlen) {
1130 /* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
1131 1 using 4 bit prefix requires 6 bytes. We may emit this at most
1135 /* Use Literal Header Field without indexing - New Name, since it is
1136 most space consuming format. Also we choose the less one between
1137 non-huffman and huffman, so using literal byte count is
1138 sufficient for upper bound.
1140 Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes. We
1141 need 2 of this for |nvlen| header fields. */
1144 for (i = 0; i < nvlen; ++i) {
1145 n += nva[i].namelen + nva[i].valuelen;
1151 int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
1152 size_t deflate_hd_table_bufsize_max) {
1153 return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
1157 int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
1158 size_t deflate_hd_table_bufsize_max,
1161 nghttp2_hd_deflater *deflater;
1164 mem = nghttp2_mem_default();
1167 deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
1169 if (deflater == NULL) {
1170 return NGHTTP2_ERR_NOMEM;
1173 rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
1176 nghttp2_mem_free(mem, deflater);
1181 *deflater_ptr = deflater;
1186 void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
1189 mem = deflater->ctx.mem;
1191 nghttp2_hd_deflate_free(deflater);
1193 nghttp2_mem_free(mem, deflater);
1196 static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
1197 const uint8_t *in) {
1198 inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1202 * Decodes the integer from the range [in, last). The result is
1203 * assigned to |inflater->left|. If the |inflater->left| is 0, then
1204 * it performs variable integer decoding from scratch. Otherwise, it
1205 * uses the |inflater->left| as the initial value and continues to
1206 * decode assuming that [in, last) begins with intermediary sequence.
1208 * This function returns the number of bytes read if it succeeds, or
1209 * one of the following negative error codes:
1211 * NGHTTP2_ERR_HEADER_COMP
1212 * Integer decoding failed
1214 static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
1215 uint8_t *in, uint8_t *last, size_t prefix,
1222 rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1223 inflater->shift, in, last, prefix);
1226 DEBUGF(fprintf(stderr, "inflatehd: integer decoding failed\n"));
1227 return NGHTTP2_ERR_HEADER_COMP;
1232 stderr, "inflatehd: integer exceeded the maximum value %zu\n", maxlen));
1233 return NGHTTP2_ERR_HEADER_COMP;
1236 inflater->left = out;
1238 DEBUGF(fprintf(stderr, "inflatehd: decoded integer is %u\n", out));
1244 * Reads |inflater->left| bytes from the range [in, last) and performs
1245 * huffman decoding against them and pushes the result into the
1248 * This function returns the number of bytes read if it succeeds, or
1249 * one of the following negative error codes:
1253 * NGHTTP2_ERR_HEADER_COMP
1254 * Huffman decoding failed
1255 * NGHTTP2_ERR_BUFFER_ERROR
1256 * Out of buffer space.
1258 static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
1259 nghttp2_bufs *bufs, uint8_t *in,
1263 if ((size_t)(last - in) >= inflater->left) {
1264 last = in + inflater->left;
1267 readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs, in,
1271 DEBUGF(fprintf(stderr, "inflatehd: huffman decoding failed\n"));
1274 inflater->left -= (size_t)readlen;
1279 * Reads |inflater->left| bytes from the range [in, last) and copies
1280 * them into the |buffer|.
1282 * This function returns the number of bytes read if it succeeds, or
1283 * one of the following negative error codes:
1287 * NGHTTP2_ERR_HEADER_COMP
1288 * Header decompression failed
1289 * NGHTTP2_ERR_BUFFER_ERROR
1290 * Out of buffer space.
1292 static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater,
1293 nghttp2_bufs *bufs, uint8_t *in, uint8_t *last) {
1295 size_t len = nghttp2_min((size_t)(last - in), inflater->left);
1296 rv = nghttp2_bufs_add(bufs, in, len);
1300 inflater->left -= len;
1301 return (ssize_t)len;
1305 * Finalize indexed header representation reception. If header is
1306 * emitted, |*nv_out| is filled with that value and 0 is returned. If
1307 * no header is emitted, 1 is returned.
1309 * This function returns either 0 or 1 if it succeeds, or one of the
1310 * following negative error codes:
1315 static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
1316 nghttp2_nv *nv_out) {
1317 nghttp2_hd_entry *ent = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1319 emit_indexed_header(nv_out, ent);
1324 static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv,
1331 if (inflater->index_required ||
1332 inflater->nvbufs.head != inflater->nvbufs.cur) {
1334 rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf);
1337 return NGHTTP2_ERR_NOMEM;
1347 nv->namelen = inflater->newnamelen;
1350 nv->value = buf + nv->namelen;
1351 nv->valuelen = buflen - nv->namelen;
1356 /* If we are not going to store header in header table and
1357 name/value are in first chunk, we just refer them from nv,
1358 instead of mallocing another memory. */
1360 pbuf = &inflater->nvbufs.head->buf;
1366 nv->name = pbuf->pos;
1367 nv->namelen = inflater->newnamelen;
1370 nv->value = pbuf->pos + nv->namelen;
1371 nv->valuelen = nghttp2_buf_len(pbuf) - nv->namelen;
1373 /* Resetting does not change the content of first buffer */
1374 nghttp2_bufs_reset(&inflater->nvbufs);
1380 * Finalize literal header representation - new name- reception. If
1381 * header is emitted, |*nv_out| is filled with that value and 0 is
1384 * This function returns 0 if it succeeds, or one of the following
1385 * negative error codes:
1390 static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
1391 nghttp2_nv *nv_out) {
1396 mem = inflater->ctx.mem;
1398 rv = hd_inflate_remove_bufs(inflater, &nv, 0 /* name and value */);
1400 return NGHTTP2_ERR_NOMEM;
1403 if (inflater->no_index) {
1404 nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1406 nv.flags = NGHTTP2_NV_FLAG_NONE;
1409 if (inflater->index_required) {
1410 nghttp2_hd_entry *new_ent;
1413 /* nv->value points to the middle of the buffer pointed by
1414 nv->name. So we just need to keep track of nv->name for memory
1416 ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
1419 add_hd_table_incremental(&inflater->ctx, &nv, hash(nv.name, nv.namelen),
1420 hash(nv.value, nv.valuelen), ent_flags);
1423 emit_indexed_header(nv_out, new_ent);
1424 inflater->ent_keep = new_ent;
1429 nghttp2_mem_free(mem, nv.name);
1431 return NGHTTP2_ERR_NOMEM;
1434 emit_literal_header(nv_out, &nv);
1436 if (nv.name != inflater->nvbufs.head->buf.pos) {
1437 inflater->nv_keep = nv.name;
1444 * Finalize literal header representation - indexed name-
1445 * reception. If header is emitted, |*nv_out| is filled with that
1446 * value and 0 is returned.
1448 * This function returns 0 if it succeeds, or one of the following
1449 * negative error codes:
1454 static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
1455 nghttp2_nv *nv_out) {
1458 nghttp2_hd_entry *ent_name;
1461 mem = inflater->ctx.mem;
1463 rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
1465 return NGHTTP2_ERR_NOMEM;
1468 if (inflater->no_index) {
1469 nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1471 nv.flags = NGHTTP2_NV_FLAG_NONE;
1474 ent_name = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1476 nv.name = ent_name->nv.name;
1477 nv.namelen = ent_name->nv.namelen;
1479 if (inflater->index_required) {
1480 nghttp2_hd_entry *new_ent;
1484 ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
1485 static_name = inflater->index < NGHTTP2_STATIC_TABLE_LENGTH;
1488 ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC;
1489 /* For entry in static table, we must not touch ref, because it
1490 is shared by threads */
1494 new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->name_hash,
1495 hash(nv.value, nv.valuelen), ent_flags);
1497 if (!static_name && --ent_name->ref == 0) {
1498 nghttp2_hd_entry_free(ent_name, mem);
1499 nghttp2_mem_free(mem, ent_name);
1503 emit_indexed_header(nv_out, new_ent);
1505 inflater->ent_keep = new_ent;
1510 nghttp2_mem_free(mem, nv.value);
1512 return NGHTTP2_ERR_NOMEM;
1515 emit_literal_header(nv_out, &nv);
1517 if (nv.value != inflater->nvbufs.head->buf.pos) {
1518 inflater->nv_keep = nv.value;
1524 ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
1525 int *inflate_flags, uint8_t *in, size_t inlen,
1528 uint8_t *first = in;
1529 uint8_t *last = in + inlen;
1532 if (inflater->ctx.bad) {
1533 return NGHTTP2_ERR_HEADER_COMP;
1536 DEBUGF(fprintf(stderr, "inflatehd: start state=%d\n", inflater->state));
1537 hd_inflate_keep_free(inflater);
1538 *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1539 for (; in != last;) {
1540 switch (inflater->state) {
1541 case NGHTTP2_HD_STATE_OPCODE:
1542 if ((*in & 0xe0u) == 0x20u) {
1543 DEBUGF(fprintf(stderr, "inflatehd: header table size change\n"));
1544 inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1545 inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1546 } else if (*in & 0x80u) {
1547 DEBUGF(fprintf(stderr, "inflatehd: indexed repr\n"));
1548 inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1549 inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1551 if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1553 fprintf(stderr, "inflatehd: literal header repr - new name\n"));
1554 inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1555 inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1557 DEBUGF(fprintf(stderr,
1558 "inflatehd: literal header repr - indexed name\n"));
1559 inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1560 inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1562 inflater->index_required = (*in & 0x40) != 0;
1563 inflater->no_index = (*in & 0xf0u) == 0x10u;
1564 DEBUGF(fprintf(stderr, "inflatehd: indexing required=%d, no_index=%d\n",
1565 inflater->index_required, inflater->no_index));
1566 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1571 inflater->shift = 0;
1573 case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1575 rv = hd_inflate_read_len(inflater, &rfin, in, last, 5,
1576 inflater->settings_hd_table_bufsize_max);
1584 DEBUGF(fprintf(stderr, "inflatehd: table_size=%zu\n", inflater->left));
1585 inflater->ctx.hd_table_bufsize_max = inflater->left;
1586 hd_context_shrink_table_size(&inflater->ctx);
1587 inflater->state = NGHTTP2_HD_STATE_OPCODE;
1589 case NGHTTP2_HD_STATE_READ_INDEX: {
1592 if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1594 } else if (inflater->index_required) {
1601 rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
1602 get_max_index(&inflater->ctx) + 1);
1613 if (inflater->left == 0) {
1614 rv = NGHTTP2_ERR_HEADER_COMP;
1618 DEBUGF(fprintf(stderr, "inflatehd: index=%zu\n", inflater->left));
1619 if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1620 inflater->index = inflater->left;
1623 rv = hd_inflate_commit_indexed(inflater, nv_out);
1627 inflater->state = NGHTTP2_HD_STATE_OPCODE;
1628 /* If rv == 1, no header was emitted */
1630 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
1631 return (ssize_t)(in - first);
1634 inflater->index = inflater->left;
1637 inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
1641 case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
1642 hd_inflate_set_huffman_encoded(inflater, in);
1643 inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
1645 inflater->shift = 0;
1646 DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
1647 inflater->huffman_encoded != 0));
1649 case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
1651 rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
1657 DEBUGF(fprintf(stderr,
1658 "inflatehd: integer not fully decoded. current=%zu\n",
1664 if (inflater->huffman_encoded) {
1665 nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
1667 inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
1669 inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
1672 case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
1673 rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
1680 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
1682 if (inflater->left) {
1683 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
1689 inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
1691 inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
1694 case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
1695 rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
1702 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
1703 if (inflater->left) {
1704 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
1710 inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
1712 inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
1715 case NGHTTP2_HD_STATE_CHECK_VALUELEN:
1716 hd_inflate_set_huffman_encoded(inflater, in);
1717 inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
1719 inflater->shift = 0;
1720 DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
1721 inflater->huffman_encoded != 0));
1723 case NGHTTP2_HD_STATE_READ_VALUELEN:
1725 rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
1736 DEBUGF(fprintf(stderr, "inflatehd: valuelen=%zu\n", inflater->left));
1737 if (inflater->left == 0) {
1738 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1739 rv = hd_inflate_commit_newname(inflater, nv_out);
1741 rv = hd_inflate_commit_indname(inflater, nv_out);
1746 inflater->state = NGHTTP2_HD_STATE_OPCODE;
1747 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
1748 return (ssize_t)(in - first);
1751 if (inflater->huffman_encoded) {
1752 nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
1754 inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
1756 inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
1759 case NGHTTP2_HD_STATE_READ_VALUEHUFF:
1760 rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
1767 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
1769 if (inflater->left) {
1770 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
1776 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1777 rv = hd_inflate_commit_newname(inflater, nv_out);
1779 rv = hd_inflate_commit_indname(inflater, nv_out);
1786 inflater->state = NGHTTP2_HD_STATE_OPCODE;
1787 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
1789 return (ssize_t)(in - first);
1790 case NGHTTP2_HD_STATE_READ_VALUE:
1791 rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
1793 DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv,
1794 nghttp2_strerror((int)rv)));
1800 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
1802 if (inflater->left) {
1803 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
1808 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1809 rv = hd_inflate_commit_newname(inflater, nv_out);
1811 rv = hd_inflate_commit_indname(inflater, nv_out);
1818 inflater->state = NGHTTP2_HD_STATE_OPCODE;
1819 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
1821 return (ssize_t)(in - first);
1827 DEBUGF(fprintf(stderr, "inflatehd: all input bytes were processed\n"));
1830 DEBUGF(fprintf(stderr, "inflatehd: in_final set\n"));
1832 if (inflater->state != NGHTTP2_HD_STATE_OPCODE) {
1833 DEBUGF(fprintf(stderr, "inflatehd: unacceptable state=%d\n",
1835 rv = NGHTTP2_ERR_HEADER_COMP;
1839 *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
1841 return (ssize_t)(in - first);
1844 if (in_final && inflater->state != NGHTTP2_HD_STATE_OPCODE) {
1845 DEBUGF(fprintf(stderr, "inflatehd: input ended prematurely\n"));
1847 rv = NGHTTP2_ERR_HEADER_COMP;
1851 return (ssize_t)(in - first);
1854 DEBUGF(fprintf(stderr, "inflatehd: error return %zd\n", rv));
1856 inflater->ctx.bad = 1;
1860 int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
1861 hd_inflate_keep_free(inflater);
1865 int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) {
1866 return nghttp2_hd_inflate_new2(inflater_ptr, NULL);
1869 int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
1872 nghttp2_hd_inflater *inflater;
1875 mem = nghttp2_mem_default();
1878 inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater));
1880 if (inflater == NULL) {
1881 return NGHTTP2_ERR_NOMEM;
1884 rv = nghttp2_hd_inflate_init(inflater, mem);
1887 nghttp2_mem_free(mem, inflater);
1892 *inflater_ptr = inflater;
1897 void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
1900 mem = inflater->ctx.mem;
1901 nghttp2_hd_inflate_free(inflater);
1903 nghttp2_mem_free(mem, inflater);
1906 int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1907 nghttp2_nv *nv, int inc_indexing) {
1909 return emit_indname_block(bufs, idx, nv, inc_indexing);
1912 int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
1914 return emit_newname_block(bufs, nv, inc_indexing);
1917 int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
1918 return emit_table_size(bufs, table_size);
1921 ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
1922 uint32_t initial, size_t shift, uint8_t *in,
1923 uint8_t *last, size_t prefix) {
1924 return decode_length(res, shift_ptr, final, initial, shift, in, last, prefix);