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 /* Make scalar initialization form of nghttp2_hd_entry */
35 #define MAKE_STATIC_ENT(N, V, T, H) \
37 { NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1 } \
38 , {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
39 {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
43 /* Generated by mkstatictbl.py */
44 /* 3rd parameter is nghttp2_token value for header field name. We use
45 first enum value if same header names are repeated (e.g.,
47 static nghttp2_hd_static_entry static_table[] = {
48 MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
49 MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
50 MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
51 MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
52 MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
53 MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
54 MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
55 MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
56 MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
57 MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
58 MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
59 MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
60 MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
61 MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
62 MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
63 MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
64 MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
65 MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
66 MAKE_STATIC_ENT("accept", "", 18, 136609321u),
67 MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
68 MAKE_STATIC_ENT("age", "", 20, 742476188u),
69 MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
70 MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
71 MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
72 MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
73 MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
74 MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
75 MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
76 MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
77 MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
78 MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
79 MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
80 MAKE_STATIC_ENT("date", "", 32, 3564297305u),
81 MAKE_STATIC_ENT("etag", "", 33, 113792960u),
82 MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
83 MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
84 MAKE_STATIC_ENT("from", "", 36, 2513272949u),
85 MAKE_STATIC_ENT("host", "", 37, 2952701295u),
86 MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
87 MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
88 MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
89 MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
90 MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
91 MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
92 MAKE_STATIC_ENT("link", "", 44, 232457833u),
93 MAKE_STATIC_ENT("location", "", 45, 200649126u),
94 MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
95 MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
96 MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
97 MAKE_STATIC_ENT("range", "", 49, 4208725202u),
98 MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
99 MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
100 MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
101 MAKE_STATIC_ENT("server", "", 53, 1085029842u),
102 MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
103 MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
104 MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
105 MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
106 MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
107 MAKE_STATIC_ENT("via", "", 59, 1762798611u),
108 MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
111 static int memeq(const void *s1, const void *s2, size_t n) {
112 return memcmp(s1, s2, n) == 0;
116 * This function was generated by genlibtokenlookup.py. Inspired by
117 * h2o header lookup. https://github.com/h2o/h2o
119 static int32_t lookup_token(const uint8_t *name, size_t namelen) {
124 if (lstreq("t", name, 1)) {
125 return NGHTTP2_TOKEN_TE;
133 if (lstreq("vi", name, 2)) {
134 return NGHTTP2_TOKEN_VIA;
138 if (lstreq("ag", name, 2)) {
139 return NGHTTP2_TOKEN_AGE;
147 if (lstreq("dat", name, 3)) {
148 return NGHTTP2_TOKEN_DATE;
152 if (lstreq("eta", name, 3)) {
153 return NGHTTP2_TOKEN_ETAG;
157 if (lstreq("lin", name, 3)) {
158 return NGHTTP2_TOKEN_LINK;
162 if (lstreq("fro", name, 3)) {
163 return NGHTTP2_TOKEN_FROM;
167 if (lstreq("hos", name, 3)) {
168 return NGHTTP2_TOKEN_HOST;
172 if (lstreq("var", name, 3)) {
173 return NGHTTP2_TOKEN_VARY;
181 if (lstreq("rang", name, 4)) {
182 return NGHTTP2_TOKEN_RANGE;
186 if (lstreq(":pat", name, 4)) {
187 return NGHTTP2_TOKEN__PATH;
191 if (lstreq("allo", name, 4)) {
192 return NGHTTP2_TOKEN_ALLOW;
200 if (lstreq("cooki", name, 5)) {
201 return NGHTTP2_TOKEN_COOKIE;
205 if (lstreq("serve", name, 5)) {
206 return NGHTTP2_TOKEN_SERVER;
210 if (lstreq("accep", name, 5)) {
211 return NGHTTP2_TOKEN_ACCEPT;
213 if (lstreq("expec", name, 5)) {
214 return NGHTTP2_TOKEN_EXPECT;
222 if (lstreq(":metho", name, 6)) {
223 return NGHTTP2_TOKEN__METHOD;
227 if (lstreq(":schem", name, 6)) {
228 return NGHTTP2_TOKEN__SCHEME;
230 if (lstreq("upgrad", name, 6)) {
231 return NGHTTP2_TOKEN_UPGRADE;
235 if (lstreq("refres", name, 6)) {
236 return NGHTTP2_TOKEN_REFRESH;
240 if (lstreq("refere", name, 6)) {
241 return NGHTTP2_TOKEN_REFERER;
245 if (lstreq(":statu", name, 6)) {
246 return NGHTTP2_TOKEN__STATUS;
248 if (lstreq("expire", name, 6)) {
249 return NGHTTP2_TOKEN_EXPIRES;
257 if (lstreq("if-rang", name, 7)) {
258 return NGHTTP2_TOKEN_IF_RANGE;
262 if (lstreq("if-matc", name, 7)) {
263 return NGHTTP2_TOKEN_IF_MATCH;
267 if (lstreq("locatio", name, 7)) {
268 return NGHTTP2_TOKEN_LOCATION;
276 if (lstreq("keep-aliv", name, 9)) {
277 return NGHTTP2_TOKEN_KEEP_ALIVE;
279 if (lstreq("set-cooki", name, 9)) {
280 return NGHTTP2_TOKEN_SET_COOKIE;
284 if (lstreq("connectio", name, 9)) {
285 return NGHTTP2_TOKEN_CONNECTION;
289 if (lstreq("user-agen", name, 9)) {
290 return NGHTTP2_TOKEN_USER_AGENT;
294 if (lstreq(":authorit", name, 9)) {
295 return NGHTTP2_TOKEN__AUTHORITY;
303 if (lstreq("retry-afte", name, 10)) {
304 return NGHTTP2_TOKEN_RETRY_AFTER;
312 if (lstreq("content-typ", name, 11)) {
313 return NGHTTP2_TOKEN_CONTENT_TYPE;
317 if (lstreq("max-forward", name, 11)) {
318 return NGHTTP2_TOKEN_MAX_FORWARDS;
326 if (lstreq("last-modifie", name, 12)) {
327 return NGHTTP2_TOKEN_LAST_MODIFIED;
331 if (lstreq("content-rang", name, 12)) {
332 return NGHTTP2_TOKEN_CONTENT_RANGE;
336 if (lstreq("if-none-matc", name, 12)) {
337 return NGHTTP2_TOKEN_IF_NONE_MATCH;
341 if (lstreq("cache-contro", name, 12)) {
342 return NGHTTP2_TOKEN_CACHE_CONTROL;
346 if (lstreq("authorizatio", name, 12)) {
347 return NGHTTP2_TOKEN_AUTHORIZATION;
351 if (lstreq("accept-range", name, 12)) {
352 return NGHTTP2_TOKEN_ACCEPT_RANGES;
360 if (lstreq("content-lengt", name, 13)) {
361 return NGHTTP2_TOKEN_CONTENT_LENGTH;
365 if (lstreq("accept-charse", name, 13)) {
366 return NGHTTP2_TOKEN_ACCEPT_CHARSET;
374 if (lstreq("accept-languag", name, 14)) {
375 return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
379 if (lstreq("accept-encodin", name, 14)) {
380 return NGHTTP2_TOKEN_ACCEPT_ENCODING;
388 if (lstreq("content-languag", name, 15)) {
389 return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
391 if (lstreq("www-authenticat", name, 15)) {
392 return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
396 if (lstreq("content-encodin", name, 15)) {
397 return NGHTTP2_TOKEN_CONTENT_ENCODING;
401 if (lstreq("content-locatio", name, 15)) {
402 return NGHTTP2_TOKEN_CONTENT_LOCATION;
404 if (lstreq("proxy-connectio", name, 15)) {
405 return NGHTTP2_TOKEN_PROXY_CONNECTION;
413 if (lstreq("if-modified-sinc", name, 16)) {
414 return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
418 if (lstreq("transfer-encodin", name, 16)) {
419 return NGHTTP2_TOKEN_TRANSFER_ENCODING;
427 if (lstreq("proxy-authenticat", name, 17)) {
428 return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
436 if (lstreq("if-unmodified-sinc", name, 18)) {
437 return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
441 if (lstreq("content-dispositio", name, 18)) {
442 return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
444 if (lstreq("proxy-authorizatio", name, 18)) {
445 return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
453 if (lstreq("strict-transport-securit", name, 24)) {
454 return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
462 if (lstreq("access-control-allow-origi", name, 26)) {
463 return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
472 void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
474 ent->cnv.name = nv->name->base;
475 ent->cnv.namelen = nv->name->len;
476 ent->cnv.value = nv->value->base;
477 ent->cnv.valuelen = nv->value->len;
478 ent->cnv.flags = nv->flags;
482 nghttp2_rcbuf_incref(ent->nv.name);
483 nghttp2_rcbuf_incref(ent->nv.value);
486 void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
487 nghttp2_rcbuf_decref(ent->nv.value);
488 nghttp2_rcbuf_decref(ent->nv.name);
491 static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
492 return a->name->len == b->namelen &&
493 memeq(a->name->base, b->name, b->namelen);
496 static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
497 return a->value->len == b->valuelen &&
498 memeq(a->value->base, b->value, b->valuelen);
501 static uint32_t name_hash(const nghttp2_nv *nv) {
502 /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
503 uint32_t h = 2166136261u;
506 for (i = 0; i < nv->namelen; ++i) {
508 h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
514 static void hd_map_init(nghttp2_hd_map *map) {
515 memset(map, 0, sizeof(nghttp2_hd_map));
518 static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
519 nghttp2_hd_entry **bucket;
521 bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
523 if (*bucket == NULL) {
528 /* lower index is linked near the root */
533 static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
534 const nghttp2_nv *nv, int32_t token,
535 uint32_t hash, int name_only) {
537 nghttp2_hd_entry *res = NULL;
541 for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
542 if (token != p->nv.token ||
543 (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
552 if (value_eq(&p->nv, nv)) {
562 static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
563 nghttp2_hd_entry **dst;
565 dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
567 for (; *dst; dst = &(*dst)->next) {
578 static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
581 for (size = 1; size < bufsize; size <<= 1)
583 ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
584 if (ringbuf->buffer == NULL) {
585 return NGHTTP2_ERR_NOMEM;
587 ringbuf->mask = size - 1;
593 static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
595 assert(idx < ringbuf->len);
596 return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
599 static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
603 nghttp2_hd_entry **buffer;
605 if (ringbuf->mask + 1 >= bufsize) {
608 for (size = 1; size < bufsize; size <<= 1)
610 buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
611 if (buffer == NULL) {
612 return NGHTTP2_ERR_NOMEM;
614 for (i = 0; i < ringbuf->len; ++i) {
615 buffer[i] = hd_ringbuf_get(ringbuf, i);
617 nghttp2_mem_free(mem, ringbuf->buffer);
618 ringbuf->buffer = buffer;
619 ringbuf->mask = size - 1;
624 static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
626 if (ringbuf == NULL) {
629 for (i = 0; i < ringbuf->len; ++i) {
630 nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
632 nghttp2_hd_entry_free(ent);
633 nghttp2_mem_free(mem, ent);
635 nghttp2_mem_free(mem, ringbuf->buffer);
638 static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
639 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
642 rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
648 ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
654 static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
655 assert(ringbuf->len > 0);
659 static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
663 context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
664 rv = hd_ringbuf_init(&context->hd_table, context->hd_table_bufsize_max /
665 NGHTTP2_HD_ENTRY_OVERHEAD,
671 context->hd_table_bufsize = 0;
672 context->next_seq = 0;
677 static void hd_context_free(nghttp2_hd_context *context) {
678 hd_ringbuf_free(&context->hd_table, context->mem);
681 int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
682 return nghttp2_hd_deflate_init2(
683 deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
686 int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
687 size_t deflate_hd_table_bufsize_max,
690 rv = hd_context_init(&deflater->ctx, mem);
695 hd_map_init(&deflater->map);
697 if (deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
698 deflater->notify_table_size_change = 1;
699 deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max;
701 deflater->notify_table_size_change = 0;
704 deflater->deflate_hd_table_bufsize_max = deflate_hd_table_bufsize_max;
705 deflater->min_hd_table_bufsize_max = UINT32_MAX;
710 int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
713 rv = hd_context_init(&inflater->ctx, mem);
718 inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
719 inflater->min_hd_table_bufsize_max = UINT32_MAX;
721 inflater->nv_name_keep = NULL;
722 inflater->nv_value_keep = NULL;
724 inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
725 inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
727 nghttp2_buf_init(&inflater->namebuf);
728 nghttp2_buf_init(&inflater->valuebuf);
730 inflater->namercbuf = NULL;
731 inflater->valuercbuf = NULL;
733 inflater->huffman_encoded = 0;
737 inflater->index_required = 0;
738 inflater->no_index = 0;
746 static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
747 nghttp2_rcbuf_decref(inflater->nv_value_keep);
748 nghttp2_rcbuf_decref(inflater->nv_name_keep);
750 inflater->nv_value_keep = NULL;
751 inflater->nv_name_keep = NULL;
754 void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
755 hd_context_free(&deflater->ctx);
758 void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
759 hd_inflate_keep_free(inflater);
761 nghttp2_rcbuf_decref(inflater->valuercbuf);
762 nghttp2_rcbuf_decref(inflater->namercbuf);
764 hd_context_free(&inflater->ctx);
767 static size_t entry_room(size_t namelen, size_t valuelen) {
768 return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
771 static int emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
772 DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name->base,
774 /* ent->ref may be 0. This happens if the encoder emits literal
775 block larger than header table capacity with indexing. */
781 static size_t count_encoded_length(size_t n, size_t prefix) {
782 size_t k = (size_t)((1 << prefix) - 1);
792 for (; n >= 128; n >>= 7, ++len)
798 static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
799 size_t k = (size_t)((1 << prefix) - 1);
800 uint8_t *begin = buf;
802 *buf = (uint8_t)(*buf & ~k);
805 *buf = (uint8_t)(*buf | n);
809 *buf = (uint8_t)(*buf | k);
814 for (; n >= 128; n >>= 7) {
815 *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
820 return (size_t)(buf - begin);
824 * Decodes |prefix| prefixed integer stored from |in|. The |last|
825 * represents the 1 beyond the last of the valid contiguous memory
826 * region from |in|. The decoded integer must be less than or equal
829 * If the |initial| is nonzero, it is used as a initial value, this
830 * function assumes the |in| starts with intermediate data.
832 * An entire integer is decoded successfully, decoded, the |*final| is
835 * This function stores the decoded integer in |*res| if it succeed,
836 * including partial decoding (in this case, number of shift to make
837 * in the next call will be stored in |*shift_ptr|) and returns number
838 * of bytes processed, or returns -1, indicating decoding error.
840 static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final,
841 uint32_t initial, size_t shift, const uint8_t *in,
842 const uint8_t *last, size_t prefix) {
843 uint32_t k = (uint8_t)((1 << prefix) - 1);
844 uint32_t n = initial;
845 const uint8_t *start = in;
851 if ((*in & k) != k) {
861 return (ssize_t)(in - start);
865 for (; in != last; ++in, shift += 7) {
866 uint32_t add = *in & 0x7f;
868 if ((UINT32_MAX >> shift) < add) {
869 DEBUGF(fprintf(stderr, "inflate: integer overflow on shift\n"));
875 if (UINT32_MAX - add < n) {
876 DEBUGF(fprintf(stderr, "inflate: integer overflow on addition\n"));
882 if ((*in & (1 << 7)) == 0) {
891 return (ssize_t)(in - start);
896 return (ssize_t)(in + 1 - start);
899 static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
905 DEBUGF(fprintf(stderr, "deflatehd: emit table_size=%zu\n", table_size));
907 blocklen = count_encoded_length(table_size, 5);
909 if (sizeof(sb) < blocklen) {
910 return NGHTTP2_ERR_HEADER_COMP;
917 encode_length(bufp, table_size, 5);
919 rv = nghttp2_bufs_add(bufs, sb, blocklen);
927 static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
933 blocklen = count_encoded_length(idx + 1, 7);
935 DEBUGF(fprintf(stderr, "deflatehd: emit indexed index=%zu, %zu bytes\n", idx,
938 if (sizeof(sb) < blocklen) {
939 return NGHTTP2_ERR_HEADER_COMP;
944 encode_length(bufp, idx + 1, 7);
946 rv = nghttp2_bufs_add(bufs, sb, blocklen);
954 static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
962 enclen = nghttp2_hd_huff_encode_count(str, len);
970 blocklen = count_encoded_length(enclen, 7);
972 DEBUGF(fprintf(stderr, "deflatehd: emit string str="));
973 DEBUGF(fwrite(str, 1, len, stderr));
974 DEBUGF(fprintf(stderr, ", length=%zu, huffman=%d, encoded_length=%zu\n", len,
977 if (sizeof(sb) < blocklen) {
978 return NGHTTP2_ERR_HEADER_COMP;
982 *bufp = huffman ? 1 << 7 : 0;
983 encode_length(bufp, enclen, 7);
985 rv = nghttp2_bufs_add(bufs, sb, blocklen);
991 rv = nghttp2_hd_huff_encode(bufs, str, len);
993 assert(enclen == len);
994 rv = nghttp2_bufs_add(bufs, str, len);
1000 static uint8_t pack_first_byte(int indexing_mode) {
1001 switch (indexing_mode) {
1002 case NGHTTP2_HD_WITH_INDEXING:
1004 case NGHTTP2_HD_WITHOUT_INDEXING:
1006 case NGHTTP2_HD_NEVER_INDEXING:
1011 /* This is required to compile with android NDK r10d +
1016 static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1017 const nghttp2_nv *nv, int indexing_mode) {
1024 if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1030 DEBUGF(fprintf(stderr, "deflatehd: emit indname index=%zu, valuelen=%zu, "
1031 "indexing_mode=%d\n",
1032 idx, nv->valuelen, indexing_mode));
1034 blocklen = count_encoded_length(idx + 1, prefixlen);
1036 if (sizeof(sb) < blocklen) {
1037 return NGHTTP2_ERR_HEADER_COMP;
1042 *bufp = pack_first_byte(indexing_mode);
1044 encode_length(bufp, idx + 1, prefixlen);
1046 rv = nghttp2_bufs_add(bufs, sb, blocklen);
1051 rv = emit_string(bufs, nv->value, nv->valuelen);
1059 static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1060 int indexing_mode) {
1063 DEBUGF(fprintf(stderr, "deflatehd: emit newname namelen=%zu, valuelen=%zu, "
1064 "indexing_mode=%d\n",
1065 nv->namelen, nv->valuelen, indexing_mode));
1067 rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1072 rv = emit_string(bufs, nv->name, nv->namelen);
1077 rv = emit_string(bufs, nv->value, nv->valuelen);
1085 static int add_hd_table_incremental(nghttp2_hd_context *context,
1086 nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1089 nghttp2_hd_entry *new_ent;
1094 room = entry_room(nv->name->len, nv->value->len);
1096 while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1097 context->hd_table.len > 0) {
1099 size_t idx = context->hd_table.len - 1;
1100 nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1102 context->hd_table_bufsize -=
1103 entry_room(ent->nv.name->len, ent->nv.value->len);
1105 DEBUGF(fprintf(stderr, "hpack: remove item from header table: %s: %s\n",
1106 (char *)ent->nv.name->base, (char *)ent->nv.value->base));
1108 hd_ringbuf_pop_back(&context->hd_table);
1110 hd_map_remove(map, ent);
1113 nghttp2_hd_entry_free(ent);
1114 nghttp2_mem_free(mem, ent);
1117 if (room > context->hd_table_bufsize_max) {
1118 /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
1119 immediately evicted. So we don't allocate memory for it. */
1123 new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1124 if (new_ent == NULL) {
1125 return NGHTTP2_ERR_NOMEM;
1128 nghttp2_hd_entry_init(new_ent, nv);
1130 rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1133 nghttp2_hd_entry_free(new_ent);
1134 nghttp2_mem_free(mem, new_ent);
1139 new_ent->seq = context->next_seq++;
1140 new_ent->hash = hash;
1143 hd_map_insert(map, new_ent);
1146 context->hd_table_bufsize += room;
1153 /* Nonzero if both name and value are matched. */
1154 int name_value_match;
1157 static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
1159 search_result res = {token, 0};
1161 nghttp2_hd_static_entry *ent;
1168 i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1170 ent = &static_table[i];
1171 if (ent->value.len == nv->valuelen &&
1172 memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1174 res.name_value_match = 1;
1181 static search_result search_hd_table(nghttp2_hd_context *context,
1182 const nghttp2_nv *nv, int32_t token,
1183 int indexing_mode, nghttp2_hd_map *map,
1185 search_result res = {-1, 0};
1186 nghttp2_hd_entry *ent;
1188 int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1191 ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1193 if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1194 return search_static_table(nv, token, name_only);
1202 (ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH);
1203 res.name_value_match = exact_match;
1208 static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1209 nghttp2_hd_map *map) {
1214 while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1215 context->hd_table.len > 0) {
1216 size_t idx = context->hd_table.len - 1;
1217 nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1218 context->hd_table_bufsize -=
1219 entry_room(ent->nv.name->len, ent->nv.value->len);
1220 hd_ringbuf_pop_back(&context->hd_table);
1222 hd_map_remove(map, ent);
1225 nghttp2_hd_entry_free(ent);
1226 nghttp2_mem_free(mem, ent);
1230 int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
1231 size_t settings_hd_table_bufsize_max) {
1232 size_t next_bufsize = nghttp2_min(settings_hd_table_bufsize_max,
1233 deflater->deflate_hd_table_bufsize_max);
1235 deflater->ctx.hd_table_bufsize_max = next_bufsize;
1237 deflater->min_hd_table_bufsize_max =
1238 nghttp2_min(deflater->min_hd_table_bufsize_max, next_bufsize);
1240 deflater->notify_table_size_change = 1;
1242 hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1246 int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
1247 size_t settings_hd_table_bufsize_max) {
1248 switch (inflater->state) {
1249 case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1250 case NGHTTP2_HD_STATE_INFLATE_START:
1253 return NGHTTP2_ERR_INVALID_STATE;
1256 /* It seems that encoder is not required to send dynamic table size
1257 update if the table size is not changed after applying
1258 SETTINGS_HEADER_TABLE_SIZE. RFC 7541 is ambiguous here, but this
1259 is the intention of the editor. If new maximum table size is
1260 strictly smaller than the current negotiated maximum size,
1261 encoder must send dynamic table size update. In other cases, we
1262 cannot expect it to do so. */
1263 if (inflater->ctx.hd_table_bufsize_max > settings_hd_table_bufsize_max) {
1264 inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
1265 /* Remember minimum value, and validate that encoder sends the
1266 value less than or equal to this. */
1267 inflater->min_hd_table_bufsize_max = settings_hd_table_bufsize_max;
1270 inflater->settings_hd_table_bufsize_max = settings_hd_table_bufsize_max;
1272 inflater->ctx.hd_table_bufsize_max = settings_hd_table_bufsize_max;
1274 hd_context_shrink_table_size(&inflater->ctx, NULL);
1278 #define INDEX_RANGE_VALID(context, idx) \
1279 ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1281 static size_t get_max_index(nghttp2_hd_context *context) {
1282 return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1285 nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1286 assert(INDEX_RANGE_VALID(context, idx));
1287 if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1288 return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1291 nghttp2_hd_static_entry *ent = &static_table[idx];
1292 nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token,
1293 NGHTTP2_NV_FLAG_NONE};
1298 static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
1300 assert(INDEX_RANGE_VALID(context, idx));
1301 if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1302 return &hd_ringbuf_get(&context->hd_table,
1303 idx - NGHTTP2_STATIC_TABLE_LENGTH)->cnv;
1306 return &static_table[idx].cnv;
1309 static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
1310 const nghttp2_nv *nv, int32_t token) {
1311 if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1312 token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1313 token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1314 token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1315 token == NGHTTP2_TOKEN_SET_COOKIE ||
1316 entry_room(nv->namelen, nv->valuelen) >
1317 deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1318 return NGHTTP2_HD_WITHOUT_INDEXING;
1321 return NGHTTP2_HD_WITH_INDEXING;
1324 static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1325 const nghttp2_nv *nv) {
1334 DEBUGF(fprintf(stderr, "deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen,
1335 nv->name, (int)nv->valuelen, nv->value));
1337 mem = deflater->ctx.mem;
1339 token = lookup_token(nv->name, nv->namelen);
1341 hash = name_hash(nv);
1342 } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1343 hash = static_table[token].hash;
1346 /* Don't index authorization header field since it may contain low
1347 entropy secret data (e.g., id/password). Also cookie header
1348 field with less than 20 bytes value is also never indexed. This
1349 is the same criteria used in Firefox codebase. */
1351 token == NGHTTP2_TOKEN_AUTHORIZATION ||
1352 (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1353 (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1354 ? NGHTTP2_HD_NEVER_INDEXING
1355 : hd_deflate_decide_indexing(deflater, nv, token);
1357 res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1358 &deflater->map, hash);
1362 if (res.name_value_match) {
1364 DEBUGF(fprintf(stderr, "deflatehd: name/value match index=%zd\n", idx));
1366 rv = emit_indexed_block(bufs, (size_t)idx);
1374 if (res.index != -1) {
1375 DEBUGF(fprintf(stderr, "deflatehd: name match index=%zd\n", res.index));
1378 if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1379 nghttp2_hd_nv hd_nv;
1381 if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) {
1382 hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1383 nghttp2_rcbuf_incref(hd_nv.name);
1385 rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1391 rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1394 nghttp2_rcbuf_decref(hd_nv.name);
1398 hd_nv.token = token;
1399 hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1401 rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1403 nghttp2_rcbuf_decref(hd_nv.value);
1404 nghttp2_rcbuf_decref(hd_nv.name);
1407 return NGHTTP2_ERR_HEADER_COMP;
1411 rv = emit_newname_block(bufs, nv, indexing_mode);
1413 rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1422 int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1423 nghttp2_bufs *bufs, const nghttp2_nv *nv,
1428 if (deflater->ctx.bad) {
1429 return NGHTTP2_ERR_HEADER_COMP;
1432 if (deflater->notify_table_size_change) {
1433 size_t min_hd_table_bufsize_max;
1435 min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
1437 deflater->notify_table_size_change = 0;
1438 deflater->min_hd_table_bufsize_max = UINT32_MAX;
1440 if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
1442 rv = emit_table_size(bufs, min_hd_table_bufsize_max);
1449 rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
1456 for (i = 0; i < nvlen; ++i) {
1457 rv = deflate_nv(deflater, bufs, &nv[i]);
1464 fprintf(stderr, "deflatehd: all input name/value pairs were deflated\n"));
1468 DEBUGF(fprintf(stderr, "deflatehd: error return %d\n", rv));
1470 deflater->ctx.bad = 1;
1474 ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
1475 size_t buflen, const nghttp2_nv *nv,
1481 mem = deflater->ctx.mem;
1483 rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
1489 rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1491 buflen = nghttp2_bufs_len(&bufs);
1493 nghttp2_bufs_wrap_free(&bufs);
1495 if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1496 return NGHTTP2_ERR_INSUFF_BUFSIZE;
1503 return (ssize_t)buflen;
1506 size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_,
1507 const nghttp2_nv *nva, size_t nvlen) {
1511 /* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
1512 1 using 4 bit prefix requires 6 bytes. We may emit this at most
1516 /* Use Literal Header Field without indexing - New Name, since it is
1517 most space consuming format. Also we choose the less one between
1518 non-huffman and huffman, so using literal byte count is
1519 sufficient for upper bound.
1521 Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes. We
1522 need 2 of this for |nvlen| header fields. */
1525 for (i = 0; i < nvlen; ++i) {
1526 n += nva[i].namelen + nva[i].valuelen;
1532 int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
1533 size_t deflate_hd_table_bufsize_max) {
1534 return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
1538 int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
1539 size_t deflate_hd_table_bufsize_max,
1542 nghttp2_hd_deflater *deflater;
1545 mem = nghttp2_mem_default();
1548 deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
1550 if (deflater == NULL) {
1551 return NGHTTP2_ERR_NOMEM;
1554 rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
1557 nghttp2_mem_free(mem, deflater);
1562 *deflater_ptr = deflater;
1567 void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
1570 mem = deflater->ctx.mem;
1572 nghttp2_hd_deflate_free(deflater);
1574 nghttp2_mem_free(mem, deflater);
1577 static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
1578 const uint8_t *in) {
1579 inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1583 * Decodes the integer from the range [in, last). The result is
1584 * assigned to |inflater->left|. If the |inflater->left| is 0, then
1585 * it performs variable integer decoding from scratch. Otherwise, it
1586 * uses the |inflater->left| as the initial value and continues to
1587 * decode assuming that [in, last) begins with intermediary sequence.
1589 * This function returns the number of bytes read if it succeeds, or
1590 * one of the following negative error codes:
1592 * NGHTTP2_ERR_HEADER_COMP
1593 * Integer decoding failed
1595 static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
1596 const uint8_t *in, const uint8_t *last,
1597 size_t prefix, size_t maxlen) {
1603 rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1604 inflater->shift, in, last, prefix);
1607 DEBUGF(fprintf(stderr, "inflatehd: integer decoding failed\n"));
1608 return NGHTTP2_ERR_HEADER_COMP;
1613 stderr, "inflatehd: integer exceeded the maximum value %zu\n", maxlen));
1614 return NGHTTP2_ERR_HEADER_COMP;
1617 inflater->left = out;
1619 DEBUGF(fprintf(stderr, "inflatehd: decoded integer is %u\n", out));
1625 * Reads |inflater->left| bytes from the range [in, last) and performs
1626 * huffman decoding against them and pushes the result into the
1629 * This function returns the number of bytes read if it succeeds, or
1630 * one of the following negative error codes:
1634 * NGHTTP2_ERR_HEADER_COMP
1635 * Huffman decoding failed
1637 static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
1638 nghttp2_buf *buf, const uint8_t *in,
1639 const uint8_t *last) {
1642 if ((size_t)(last - in) >= inflater->left) {
1643 last = in + inflater->left;
1646 readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1647 (size_t)(last - in), final);
1650 DEBUGF(fprintf(stderr, "inflatehd: huffman decoding failed\n"));
1653 inflater->left -= (size_t)readlen;
1658 * Reads |inflater->left| bytes from the range [in, last) and copies
1659 * them into the |buffer|.
1661 * This function returns the number of bytes read if it succeeds, or
1662 * one of the following negative error codes:
1666 * NGHTTP2_ERR_HEADER_COMP
1667 * Header decompression failed
1669 static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
1670 const uint8_t *in, const uint8_t *last) {
1671 size_t len = nghttp2_min((size_t)(last - in), inflater->left);
1673 buf->last = nghttp2_cpymem(buf->last, in, len);
1675 inflater->left -= len;
1676 return (ssize_t)len;
1680 * Finalize indexed header representation reception. If header is
1681 * emitted, |*nv_out| is filled with that value and 0 is returned. If
1682 * no header is emitted, 1 is returned.
1684 * This function returns either 0 or 1 if it succeeds, or one of the
1685 * following negative error codes:
1690 static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
1691 nghttp2_hd_nv *nv_out) {
1692 nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1694 emit_header(nv_out, &nv);
1700 * Finalize literal header representation - new name- reception. If
1701 * header is emitted, |*nv_out| is filled with that value and 0 is
1704 * This function returns 0 if it succeeds, or one of the following
1705 * negative error codes:
1710 static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
1711 nghttp2_hd_nv *nv_out) {
1715 if (inflater->no_index) {
1716 nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1718 nv.flags = NGHTTP2_NV_FLAG_NONE;
1721 nv.name = inflater->namercbuf;
1722 nv.value = inflater->valuercbuf;
1723 nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1725 if (inflater->index_required) {
1726 rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1733 emit_header(nv_out, &nv);
1735 inflater->nv_name_keep = nv.name;
1736 inflater->nv_value_keep = nv.value;
1738 inflater->namercbuf = NULL;
1739 inflater->valuercbuf = NULL;
1745 * Finalize literal header representation - indexed name-
1746 * reception. If header is emitted, |*nv_out| is filled with that
1747 * value and 0 is returned.
1749 * This function returns 0 if it succeeds, or one of the following
1750 * negative error codes:
1755 static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
1756 nghttp2_hd_nv *nv_out) {
1760 nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1762 if (inflater->no_index) {
1763 nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1765 nv.flags = NGHTTP2_NV_FLAG_NONE;
1768 nghttp2_rcbuf_incref(nv.name);
1770 nv.value = inflater->valuercbuf;
1772 if (inflater->index_required) {
1773 rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1775 nghttp2_rcbuf_decref(nv.name);
1776 return NGHTTP2_ERR_NOMEM;
1780 emit_header(nv_out, &nv);
1782 inflater->nv_name_keep = nv.name;
1783 inflater->nv_value_keep = nv.value;
1785 inflater->valuercbuf = NULL;
1790 ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
1791 int *inflate_flags, uint8_t *in, size_t inlen,
1793 return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
1797 ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
1798 nghttp2_nv *nv_out, int *inflate_flags,
1799 const uint8_t *in, size_t inlen, int in_final) {
1801 nghttp2_hd_nv hd_nv;
1803 rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1810 if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1811 nv_out->name = hd_nv.name->base;
1812 nv_out->namelen = hd_nv.name->len;
1814 nv_out->value = hd_nv.value->base;
1815 nv_out->valuelen = hd_nv.value->len;
1817 nv_out->flags = hd_nv.flags;
1823 ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
1824 nghttp2_hd_nv *nv_out, int *inflate_flags,
1825 const uint8_t *in, size_t inlen,
1828 const uint8_t *first = in;
1829 const uint8_t *last = in + inlen;
1834 mem = inflater->ctx.mem;
1836 if (inflater->ctx.bad) {
1837 return NGHTTP2_ERR_HEADER_COMP;
1840 DEBUGF(fprintf(stderr, "inflatehd: start state=%d\n", inflater->state));
1841 hd_inflate_keep_free(inflater);
1842 *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1843 for (; in != last || busy;) {
1845 switch (inflater->state) {
1846 case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1847 if ((*in & 0xe0u) != 0x20u) {
1848 DEBUGF(fprintf(stderr, "inflatehd: header table size change was "
1849 "expected, but saw 0x%02x as first byte",
1851 rv = NGHTTP2_ERR_HEADER_COMP;
1855 case NGHTTP2_HD_STATE_INFLATE_START:
1856 case NGHTTP2_HD_STATE_OPCODE:
1857 if ((*in & 0xe0u) == 0x20u) {
1858 DEBUGF(fprintf(stderr, "inflatehd: header table size change\n"));
1859 if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1860 DEBUGF(fprintf(stderr, "inflatehd: header table size change must "
1861 "appear at the head of header block\n"));
1862 rv = NGHTTP2_ERR_HEADER_COMP;
1865 inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1866 inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1867 } else if (*in & 0x80u) {
1868 DEBUGF(fprintf(stderr, "inflatehd: indexed repr\n"));
1869 inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1870 inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1872 if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1874 fprintf(stderr, "inflatehd: literal header repr - new name\n"));
1875 inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1876 inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1878 DEBUGF(fprintf(stderr,
1879 "inflatehd: literal header repr - indexed name\n"));
1880 inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1881 inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1883 inflater->index_required = (*in & 0x40) != 0;
1884 inflater->no_index = (*in & 0xf0u) == 0x10u;
1885 DEBUGF(fprintf(stderr, "inflatehd: indexing required=%d, no_index=%d\n",
1886 inflater->index_required, inflater->no_index));
1887 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1892 inflater->shift = 0;
1894 case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1896 rv = hd_inflate_read_len(
1897 inflater, &rfin, in, last, 5,
1898 nghttp2_min(inflater->min_hd_table_bufsize_max,
1899 inflater->settings_hd_table_bufsize_max));
1907 DEBUGF(fprintf(stderr, "inflatehd: table_size=%zu\n", inflater->left));
1908 inflater->min_hd_table_bufsize_max = UINT32_MAX;
1909 inflater->ctx.hd_table_bufsize_max = inflater->left;
1910 hd_context_shrink_table_size(&inflater->ctx, NULL);
1911 inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1913 case NGHTTP2_HD_STATE_READ_INDEX: {
1916 if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1918 } else if (inflater->index_required) {
1925 rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
1926 get_max_index(&inflater->ctx));
1937 if (inflater->left == 0) {
1938 rv = NGHTTP2_ERR_HEADER_COMP;
1942 DEBUGF(fprintf(stderr, "inflatehd: index=%zu\n", inflater->left));
1943 if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1944 inflater->index = inflater->left;
1947 rv = hd_inflate_commit_indexed(inflater, nv_out);
1951 inflater->state = NGHTTP2_HD_STATE_OPCODE;
1952 /* If rv == 1, no header was emitted */
1954 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
1955 return (ssize_t)(in - first);
1958 inflater->index = inflater->left;
1961 inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
1965 case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
1966 hd_inflate_set_huffman_encoded(inflater, in);
1967 inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
1969 inflater->shift = 0;
1970 DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
1971 inflater->huffman_encoded != 0));
1973 case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
1975 rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
1981 DEBUGF(fprintf(stderr,
1982 "inflatehd: integer not fully decoded. current=%zu\n",
1988 if (inflater->huffman_encoded) {
1989 nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
1991 inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
1993 rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
1996 inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
1997 rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2004 nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2005 inflater->namercbuf->len);
2008 case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2009 rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2016 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
2018 if (inflater->left) {
2019 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
2025 *inflater->namebuf.last = '\0';
2026 inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2028 inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2031 case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2032 rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2039 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
2040 if (inflater->left) {
2041 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
2047 *inflater->namebuf.last = '\0';
2048 inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2050 inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2053 case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2054 hd_inflate_set_huffman_encoded(inflater, in);
2055 inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2057 inflater->shift = 0;
2058 DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
2059 inflater->huffman_encoded != 0));
2061 case NGHTTP2_HD_STATE_READ_VALUELEN:
2063 rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2074 DEBUGF(fprintf(stderr, "inflatehd: valuelen=%zu\n", inflater->left));
2076 if (inflater->huffman_encoded) {
2077 nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2079 inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2081 rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
2084 inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2086 rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2093 nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2094 inflater->valuercbuf->len);
2099 case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2100 rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2107 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
2109 if (inflater->left) {
2110 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
2116 *inflater->valuebuf.last = '\0';
2117 inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2119 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2120 rv = hd_inflate_commit_newname(inflater, nv_out);
2122 rv = hd_inflate_commit_indname(inflater, nv_out);
2129 inflater->state = NGHTTP2_HD_STATE_OPCODE;
2130 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2132 return (ssize_t)(in - first);
2133 case NGHTTP2_HD_STATE_READ_VALUE:
2134 rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2136 DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv,
2137 nghttp2_strerror((int)rv)));
2143 DEBUGF(fprintf(stderr, "inflatehd: %zd bytes read\n", rv));
2145 if (inflater->left) {
2146 DEBUGF(fprintf(stderr, "inflatehd: still %zu bytes to go\n",
2151 *inflater->valuebuf.last = '\0';
2152 inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2154 if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2155 rv = hd_inflate_commit_newname(inflater, nv_out);
2157 rv = hd_inflate_commit_indname(inflater, nv_out);
2164 inflater->state = NGHTTP2_HD_STATE_OPCODE;
2165 *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2167 return (ssize_t)(in - first);
2173 DEBUGF(fprintf(stderr, "inflatehd: all input bytes were processed\n"));
2176 DEBUGF(fprintf(stderr, "inflatehd: in_final set\n"));
2178 if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2179 inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2180 DEBUGF(fprintf(stderr, "inflatehd: unacceptable state=%d\n",
2182 rv = NGHTTP2_ERR_HEADER_COMP;
2186 *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2188 return (ssize_t)(in - first);
2192 DEBUGF(fprintf(stderr, "inflatehd: input ended prematurely\n"));
2194 rv = NGHTTP2_ERR_HEADER_COMP;
2198 return (ssize_t)(in - first);
2201 DEBUGF(fprintf(stderr, "inflatehd: error return %zd\n", rv));
2203 inflater->ctx.bad = 1;
2207 int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2208 hd_inflate_keep_free(inflater);
2209 inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2213 int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) {
2214 return nghttp2_hd_inflate_new2(inflater_ptr, NULL);
2217 int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
2220 nghttp2_hd_inflater *inflater;
2223 mem = nghttp2_mem_default();
2226 inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater));
2228 if (inflater == NULL) {
2229 return NGHTTP2_ERR_NOMEM;
2232 rv = nghttp2_hd_inflate_init(inflater, mem);
2235 nghttp2_mem_free(mem, inflater);
2240 *inflater_ptr = inflater;
2245 void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
2248 mem = inflater->ctx.mem;
2249 nghttp2_hd_inflate_free(inflater);
2251 nghttp2_mem_free(mem, inflater);
2254 int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
2255 nghttp2_nv *nv, int indexing_mode) {
2257 return emit_indname_block(bufs, idx, nv, indexing_mode);
2260 int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
2261 int indexing_mode) {
2262 return emit_newname_block(bufs, nv, indexing_mode);
2265 int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
2266 return emit_table_size(bufs, table_size);
2269 ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
2270 uint32_t initial, size_t shift, uint8_t *in,
2271 uint8_t *last, size_t prefix) {
2272 return decode_length(res, shift_ptr, final, initial, shift, in, last, prefix);
2275 static size_t hd_get_num_table_entries(nghttp2_hd_context *context) {
2276 return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
2279 static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
2287 if (!INDEX_RANGE_VALID(context, idx)) {
2291 return nghttp2_hd_table_get2(context, idx);
2294 size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) {
2295 return hd_get_num_table_entries(&deflater->ctx);
2299 nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) {
2300 return hd_get_table_entry(&deflater->ctx, idx);
2304 nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) {
2305 return deflater->ctx.hd_table_bufsize;
2309 nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) {
2310 return deflater->ctx.hd_table_bufsize_max;
2313 size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) {
2314 return hd_get_num_table_entries(&inflater->ctx);
2318 nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) {
2319 return hd_get_table_entry(&inflater->ctx, idx);
2323 nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) {
2324 return inflater->ctx.hd_table_bufsize;
2328 nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) {
2329 return inflater->ctx.hd_table_bufsize_max;