11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * nghttp3
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Copyright (c) 2019 nghttp3 contributors
51cb0ef41Sopenharmony_ci * Copyright (c) 2013 nghttp2 contributors
61cb0ef41Sopenharmony_ci *
71cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
81cb0ef41Sopenharmony_ci * a copy of this software and associated documentation files (the
91cb0ef41Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
101cb0ef41Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
111cb0ef41Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
121cb0ef41Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
131cb0ef41Sopenharmony_ci * the following conditions:
141cb0ef41Sopenharmony_ci *
151cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be
161cb0ef41Sopenharmony_ci * included in all copies or substantial portions of the Software.
171cb0ef41Sopenharmony_ci *
181cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
191cb0ef41Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
201cb0ef41Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
211cb0ef41Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
221cb0ef41Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
231cb0ef41Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
241cb0ef41Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
251cb0ef41Sopenharmony_ci */
261cb0ef41Sopenharmony_ci#include "nghttp3_qpack.h"
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#include <string.h>
291cb0ef41Sopenharmony_ci#include <assert.h>
301cb0ef41Sopenharmony_ci#include <stdio.h>
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#include "nghttp3_str.h"
331cb0ef41Sopenharmony_ci#include "nghttp3_macro.h"
341cb0ef41Sopenharmony_ci#include "nghttp3_debug.h"
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci/* NGHTTP3_QPACK_MAX_QPACK_STREAMS is the maximum number of concurrent
371cb0ef41Sopenharmony_ci   nghttp3_qpack_stream object to handle a client which never cancel
381cb0ef41Sopenharmony_ci   or acknowledge header block.  After this limit, encoder stops using
391cb0ef41Sopenharmony_ci   dynamic table. */
401cb0ef41Sopenharmony_ci#define NGHTTP3_QPACK_MAX_QPACK_STREAMS 2000
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci/* Make scalar initialization form of nghttp3_qpack_static_entry */
431cb0ef41Sopenharmony_ci#define MAKE_STATIC_ENT(I, T, H)                                               \
441cb0ef41Sopenharmony_ci  { I, T, H }
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci/* Generated by mkstatichdtbl.py */
471cb0ef41Sopenharmony_cistatic nghttp3_qpack_static_entry token_stable[] = {
481cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(0, NGHTTP3_QPACK_TOKEN__AUTHORITY, 3153725150u),
491cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(15, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
501cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(16, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
511cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(17, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
521cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(18, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
531cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(19, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
541cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(20, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
551cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(21, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
561cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(1, NGHTTP3_QPACK_TOKEN__PATH, 3292848686u),
571cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(22, NGHTTP3_QPACK_TOKEN__SCHEME, 2510477674u),
581cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(23, NGHTTP3_QPACK_TOKEN__SCHEME, 2510477674u),
591cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(24, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
601cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(25, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
611cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(26, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
621cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(27, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
631cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(28, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
641cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(63, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
651cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(64, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
661cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(65, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
671cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(66, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
681cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(67, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
691cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(68, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
701cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(69, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
711cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(70, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
721cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(71, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
731cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(29, NGHTTP3_QPACK_TOKEN_ACCEPT, 136609321u),
741cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(30, NGHTTP3_QPACK_TOKEN_ACCEPT, 136609321u),
751cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(31, NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING, 3379649177u),
761cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(72, NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE, 1979086614u),
771cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(32, NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES, 1713753958u),
781cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(73, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS,
791cb0ef41Sopenharmony_ci                    901040780u),
801cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(74, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS,
811cb0ef41Sopenharmony_ci                    901040780u),
821cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(33, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
831cb0ef41Sopenharmony_ci                    1524311232u),
841cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(34, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
851cb0ef41Sopenharmony_ci                    1524311232u),
861cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(75, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
871cb0ef41Sopenharmony_ci                    1524311232u),
881cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(76, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
891cb0ef41Sopenharmony_ci                    2175229868u),
901cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(77, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
911cb0ef41Sopenharmony_ci                    2175229868u),
921cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(78, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
931cb0ef41Sopenharmony_ci                    2175229868u),
941cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(35, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN,
951cb0ef41Sopenharmony_ci                    2710797292u),
961cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(79, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS,
971cb0ef41Sopenharmony_ci                    2449824425u),
981cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(80, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS,
991cb0ef41Sopenharmony_ci                    3599549072u),
1001cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(81, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD,
1011cb0ef41Sopenharmony_ci                    2417078055u),
1021cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(82, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD,
1031cb0ef41Sopenharmony_ci                    2417078055u),
1041cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(2, NGHTTP3_QPACK_TOKEN_AGE, 742476188u),
1051cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(83, NGHTTP3_QPACK_TOKEN_ALT_SVC, 2148877059u),
1061cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(84, NGHTTP3_QPACK_TOKEN_AUTHORIZATION, 2436257726u),
1071cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(36, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
1081cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(37, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
1091cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(38, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
1101cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(39, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
1111cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(40, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
1121cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(41, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
1131cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(3, NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION, 3889184348u),
1141cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(42, NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING, 65203592u),
1151cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(43, NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING, 65203592u),
1161cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(4, NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH, 1308181789u),
1171cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(85, NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY,
1181cb0ef41Sopenharmony_ci                    1569039836u),
1191cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(44, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1201cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(45, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1211cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(46, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1221cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(47, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1231cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(48, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1241cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(49, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1251cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(50, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1261cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(51, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1271cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(52, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1281cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(53, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1291cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(54, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
1301cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(5, NGHTTP3_QPACK_TOKEN_COOKIE, 2007449791u),
1311cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(6, NGHTTP3_QPACK_TOKEN_DATE, 3564297305u),
1321cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(86, NGHTTP3_QPACK_TOKEN_EARLY_DATA, 4080895051u),
1331cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(7, NGHTTP3_QPACK_TOKEN_ETAG, 113792960u),
1341cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(87, NGHTTP3_QPACK_TOKEN_EXPECT_CT, 1183214960u),
1351cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(88, NGHTTP3_QPACK_TOKEN_FORWARDED, 1485178027u),
1361cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(8, NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE, 2213050793u),
1371cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(9, NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH, 2536202615u),
1381cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(89, NGHTTP3_QPACK_TOKEN_IF_RANGE, 2340978238u),
1391cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(10, NGHTTP3_QPACK_TOKEN_LAST_MODIFIED, 3226950251u),
1401cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(11, NGHTTP3_QPACK_TOKEN_LINK, 232457833u),
1411cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(12, NGHTTP3_QPACK_TOKEN_LOCATION, 200649126u),
1421cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(90, NGHTTP3_QPACK_TOKEN_ORIGIN, 3649018447u),
1431cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(91, NGHTTP3_QPACK_TOKEN_PURPOSE, 4212263681u),
1441cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(55, NGHTTP3_QPACK_TOKEN_RANGE, 4208725202u),
1451cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(13, NGHTTP3_QPACK_TOKEN_REFERER, 3969579366u),
1461cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(92, NGHTTP3_QPACK_TOKEN_SERVER, 1085029842u),
1471cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(14, NGHTTP3_QPACK_TOKEN_SET_COOKIE, 1848371000u),
1481cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(56, NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY,
1491cb0ef41Sopenharmony_ci                    4138147361u),
1501cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(57, NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY,
1511cb0ef41Sopenharmony_ci                    4138147361u),
1521cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(58, NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY,
1531cb0ef41Sopenharmony_ci                    4138147361u),
1541cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(93, NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN, 2432297564u),
1551cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(94, NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS,
1561cb0ef41Sopenharmony_ci                    2479169413u),
1571cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(95, NGHTTP3_QPACK_TOKEN_USER_AGENT, 606444526u),
1581cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(59, NGHTTP3_QPACK_TOKEN_VARY, 1085005381u),
1591cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(60, NGHTTP3_QPACK_TOKEN_VARY, 1085005381u),
1601cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(61, NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS,
1611cb0ef41Sopenharmony_ci                    3644557769u),
1621cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(96, NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR, 2914187656u),
1631cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(97, NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS, 3993834824u),
1641cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(98, NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS, 3993834824u),
1651cb0ef41Sopenharmony_ci    MAKE_STATIC_ENT(62, NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION, 2501058888u),
1661cb0ef41Sopenharmony_ci};
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci/* Make scalar initialization form of nghttp3_qpack_static_entry */
1691cb0ef41Sopenharmony_ci#define MAKE_STATIC_HD(N, V, T)                                                \
1701cb0ef41Sopenharmony_ci  {                                                                            \
1711cb0ef41Sopenharmony_ci    {NULL, (uint8_t *)(N), sizeof((N)) - 1, -1},                               \
1721cb0ef41Sopenharmony_ci        {NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, T                         \
1731cb0ef41Sopenharmony_ci  }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_cistatic nghttp3_qpack_static_header stable[] = {
1761cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":authority", "", NGHTTP3_QPACK_TOKEN__AUTHORITY),
1771cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":path", "/", NGHTTP3_QPACK_TOKEN__PATH),
1781cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("age", "0", NGHTTP3_QPACK_TOKEN_AGE),
1791cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-disposition", "",
1801cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION),
1811cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-length", "0", NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH),
1821cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cookie", "", NGHTTP3_QPACK_TOKEN_COOKIE),
1831cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("date", "", NGHTTP3_QPACK_TOKEN_DATE),
1841cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("etag", "", NGHTTP3_QPACK_TOKEN_ETAG),
1851cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("if-modified-since", "",
1861cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE),
1871cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("if-none-match", "", NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH),
1881cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("last-modified", "", NGHTTP3_QPACK_TOKEN_LAST_MODIFIED),
1891cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("link", "", NGHTTP3_QPACK_TOKEN_LINK),
1901cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("location", "", NGHTTP3_QPACK_TOKEN_LOCATION),
1911cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("referer", "", NGHTTP3_QPACK_TOKEN_REFERER),
1921cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("set-cookie", "", NGHTTP3_QPACK_TOKEN_SET_COOKIE),
1931cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "CONNECT", NGHTTP3_QPACK_TOKEN__METHOD),
1941cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "DELETE", NGHTTP3_QPACK_TOKEN__METHOD),
1951cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "GET", NGHTTP3_QPACK_TOKEN__METHOD),
1961cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "HEAD", NGHTTP3_QPACK_TOKEN__METHOD),
1971cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "OPTIONS", NGHTTP3_QPACK_TOKEN__METHOD),
1981cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "POST", NGHTTP3_QPACK_TOKEN__METHOD),
1991cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":method", "PUT", NGHTTP3_QPACK_TOKEN__METHOD),
2001cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":scheme", "http", NGHTTP3_QPACK_TOKEN__SCHEME),
2011cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":scheme", "https", NGHTTP3_QPACK_TOKEN__SCHEME),
2021cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "103", NGHTTP3_QPACK_TOKEN__STATUS),
2031cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "200", NGHTTP3_QPACK_TOKEN__STATUS),
2041cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "304", NGHTTP3_QPACK_TOKEN__STATUS),
2051cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "404", NGHTTP3_QPACK_TOKEN__STATUS),
2061cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "503", NGHTTP3_QPACK_TOKEN__STATUS),
2071cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("accept", "*/*", NGHTTP3_QPACK_TOKEN_ACCEPT),
2081cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("accept", "application/dns-message",
2091cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCEPT),
2101cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("accept-encoding", "gzip, deflate, br",
2111cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING),
2121cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("accept-ranges", "bytes", NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES),
2131cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-headers", "cache-control",
2141cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS),
2151cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-headers", "content-type",
2161cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS),
2171cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-origin", "*",
2181cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN),
2191cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cache-control", "max-age=0",
2201cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
2211cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cache-control", "max-age=2592000",
2221cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
2231cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cache-control", "max-age=604800",
2241cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
2251cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cache-control", "no-cache",
2261cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
2271cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cache-control", "no-store",
2281cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
2291cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("cache-control", "public, max-age=31536000",
2301cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
2311cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-encoding", "br",
2321cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING),
2331cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-encoding", "gzip",
2341cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING),
2351cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "application/dns-message",
2361cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2371cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "application/javascript",
2381cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2391cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "application/json",
2401cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2411cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "application/x-www-form-urlencoded",
2421cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2431cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "image/gif",
2441cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2451cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "image/jpeg",
2461cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2471cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "image/png",
2481cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2491cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "text/css",
2501cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2511cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "text/html; charset=utf-8",
2521cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2531cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "text/plain",
2541cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2551cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-type", "text/plain;charset=utf-8",
2561cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
2571cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("range", "bytes=0-", NGHTTP3_QPACK_TOKEN_RANGE),
2581cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("strict-transport-security", "max-age=31536000",
2591cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY),
2601cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("strict-transport-security",
2611cb0ef41Sopenharmony_ci                   "max-age=31536000; includesubdomains",
2621cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY),
2631cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("strict-transport-security",
2641cb0ef41Sopenharmony_ci                   "max-age=31536000; includesubdomains; preload",
2651cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY),
2661cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("vary", "accept-encoding", NGHTTP3_QPACK_TOKEN_VARY),
2671cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("vary", "origin", NGHTTP3_QPACK_TOKEN_VARY),
2681cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("x-content-type-options", "nosniff",
2691cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS),
2701cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("x-xss-protection", "1; mode=block",
2711cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION),
2721cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "100", NGHTTP3_QPACK_TOKEN__STATUS),
2731cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "204", NGHTTP3_QPACK_TOKEN__STATUS),
2741cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "206", NGHTTP3_QPACK_TOKEN__STATUS),
2751cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "302", NGHTTP3_QPACK_TOKEN__STATUS),
2761cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "400", NGHTTP3_QPACK_TOKEN__STATUS),
2771cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "403", NGHTTP3_QPACK_TOKEN__STATUS),
2781cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "421", NGHTTP3_QPACK_TOKEN__STATUS),
2791cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "425", NGHTTP3_QPACK_TOKEN__STATUS),
2801cb0ef41Sopenharmony_ci    MAKE_STATIC_HD(":status", "500", NGHTTP3_QPACK_TOKEN__STATUS),
2811cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("accept-language", "", NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE),
2821cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-credentials", "FALSE",
2831cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS),
2841cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-credentials", "TRUE",
2851cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS),
2861cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-headers", "*",
2871cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS),
2881cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-methods", "get",
2891cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS),
2901cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-methods", "get, post, options",
2911cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS),
2921cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-allow-methods", "options",
2931cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS),
2941cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-expose-headers", "content-length",
2951cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS),
2961cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-request-headers", "content-type",
2971cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS),
2981cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-request-method", "get",
2991cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD),
3001cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("access-control-request-method", "post",
3011cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD),
3021cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("alt-svc", "clear", NGHTTP3_QPACK_TOKEN_ALT_SVC),
3031cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("authorization", "", NGHTTP3_QPACK_TOKEN_AUTHORIZATION),
3041cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("content-security-policy",
3051cb0ef41Sopenharmony_ci                   "script-src 'none'; object-src 'none'; base-uri 'none'",
3061cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY),
3071cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("early-data", "1", NGHTTP3_QPACK_TOKEN_EARLY_DATA),
3081cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("expect-ct", "", NGHTTP3_QPACK_TOKEN_EXPECT_CT),
3091cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("forwarded", "", NGHTTP3_QPACK_TOKEN_FORWARDED),
3101cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("if-range", "", NGHTTP3_QPACK_TOKEN_IF_RANGE),
3111cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("origin", "", NGHTTP3_QPACK_TOKEN_ORIGIN),
3121cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("purpose", "prefetch", NGHTTP3_QPACK_TOKEN_PURPOSE),
3131cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("server", "", NGHTTP3_QPACK_TOKEN_SERVER),
3141cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("timing-allow-origin", "*",
3151cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN),
3161cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("upgrade-insecure-requests", "1",
3171cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS),
3181cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("user-agent", "", NGHTTP3_QPACK_TOKEN_USER_AGENT),
3191cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("x-forwarded-for", "", NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR),
3201cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("x-frame-options", "deny",
3211cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS),
3221cb0ef41Sopenharmony_ci    MAKE_STATIC_HD("x-frame-options", "sameorigin",
3231cb0ef41Sopenharmony_ci                   NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS),
3241cb0ef41Sopenharmony_ci};
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_cistatic int memeq(const void *s1, const void *s2, size_t n) {
3271cb0ef41Sopenharmony_ci  return n == 0 || memcmp(s1, s2, n) == 0;
3281cb0ef41Sopenharmony_ci}
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci/* Generated by genlibtokenlookup.py */
3311cb0ef41Sopenharmony_cistatic int32_t qpack_lookup_token(const uint8_t *name, size_t namelen) {
3321cb0ef41Sopenharmony_ci  switch (namelen) {
3331cb0ef41Sopenharmony_ci  case 2:
3341cb0ef41Sopenharmony_ci    switch (name[1]) {
3351cb0ef41Sopenharmony_ci    case 'e':
3361cb0ef41Sopenharmony_ci      if (memeq("t", name, 1)) {
3371cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_TE;
3381cb0ef41Sopenharmony_ci      }
3391cb0ef41Sopenharmony_ci      break;
3401cb0ef41Sopenharmony_ci    }
3411cb0ef41Sopenharmony_ci    break;
3421cb0ef41Sopenharmony_ci  case 3:
3431cb0ef41Sopenharmony_ci    switch (name[2]) {
3441cb0ef41Sopenharmony_ci    case 'e':
3451cb0ef41Sopenharmony_ci      if (memeq("ag", name, 2)) {
3461cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_AGE;
3471cb0ef41Sopenharmony_ci      }
3481cb0ef41Sopenharmony_ci      break;
3491cb0ef41Sopenharmony_ci    }
3501cb0ef41Sopenharmony_ci    break;
3511cb0ef41Sopenharmony_ci  case 4:
3521cb0ef41Sopenharmony_ci    switch (name[3]) {
3531cb0ef41Sopenharmony_ci    case 'e':
3541cb0ef41Sopenharmony_ci      if (memeq("dat", name, 3)) {
3551cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_DATE;
3561cb0ef41Sopenharmony_ci      }
3571cb0ef41Sopenharmony_ci      break;
3581cb0ef41Sopenharmony_ci    case 'g':
3591cb0ef41Sopenharmony_ci      if (memeq("eta", name, 3)) {
3601cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ETAG;
3611cb0ef41Sopenharmony_ci      }
3621cb0ef41Sopenharmony_ci      break;
3631cb0ef41Sopenharmony_ci    case 'k':
3641cb0ef41Sopenharmony_ci      if (memeq("lin", name, 3)) {
3651cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_LINK;
3661cb0ef41Sopenharmony_ci      }
3671cb0ef41Sopenharmony_ci      break;
3681cb0ef41Sopenharmony_ci    case 't':
3691cb0ef41Sopenharmony_ci      if (memeq("hos", name, 3)) {
3701cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_HOST;
3711cb0ef41Sopenharmony_ci      }
3721cb0ef41Sopenharmony_ci      break;
3731cb0ef41Sopenharmony_ci    case 'y':
3741cb0ef41Sopenharmony_ci      if (memeq("var", name, 3)) {
3751cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_VARY;
3761cb0ef41Sopenharmony_ci      }
3771cb0ef41Sopenharmony_ci      break;
3781cb0ef41Sopenharmony_ci    }
3791cb0ef41Sopenharmony_ci    break;
3801cb0ef41Sopenharmony_ci  case 5:
3811cb0ef41Sopenharmony_ci    switch (name[4]) {
3821cb0ef41Sopenharmony_ci    case 'e':
3831cb0ef41Sopenharmony_ci      if (memeq("rang", name, 4)) {
3841cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_RANGE;
3851cb0ef41Sopenharmony_ci      }
3861cb0ef41Sopenharmony_ci      break;
3871cb0ef41Sopenharmony_ci    case 'h':
3881cb0ef41Sopenharmony_ci      if (memeq(":pat", name, 4)) {
3891cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN__PATH;
3901cb0ef41Sopenharmony_ci      }
3911cb0ef41Sopenharmony_ci      break;
3921cb0ef41Sopenharmony_ci    }
3931cb0ef41Sopenharmony_ci    break;
3941cb0ef41Sopenharmony_ci  case 6:
3951cb0ef41Sopenharmony_ci    switch (name[5]) {
3961cb0ef41Sopenharmony_ci    case 'e':
3971cb0ef41Sopenharmony_ci      if (memeq("cooki", name, 5)) {
3981cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_COOKIE;
3991cb0ef41Sopenharmony_ci      }
4001cb0ef41Sopenharmony_ci      break;
4011cb0ef41Sopenharmony_ci    case 'n':
4021cb0ef41Sopenharmony_ci      if (memeq("origi", name, 5)) {
4031cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ORIGIN;
4041cb0ef41Sopenharmony_ci      }
4051cb0ef41Sopenharmony_ci      break;
4061cb0ef41Sopenharmony_ci    case 'r':
4071cb0ef41Sopenharmony_ci      if (memeq("serve", name, 5)) {
4081cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_SERVER;
4091cb0ef41Sopenharmony_ci      }
4101cb0ef41Sopenharmony_ci      break;
4111cb0ef41Sopenharmony_ci    case 't':
4121cb0ef41Sopenharmony_ci      if (memeq("accep", name, 5)) {
4131cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCEPT;
4141cb0ef41Sopenharmony_ci      }
4151cb0ef41Sopenharmony_ci      break;
4161cb0ef41Sopenharmony_ci    }
4171cb0ef41Sopenharmony_ci    break;
4181cb0ef41Sopenharmony_ci  case 7:
4191cb0ef41Sopenharmony_ci    switch (name[6]) {
4201cb0ef41Sopenharmony_ci    case 'c':
4211cb0ef41Sopenharmony_ci      if (memeq("alt-sv", name, 6)) {
4221cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ALT_SVC;
4231cb0ef41Sopenharmony_ci      }
4241cb0ef41Sopenharmony_ci      break;
4251cb0ef41Sopenharmony_ci    case 'd':
4261cb0ef41Sopenharmony_ci      if (memeq(":metho", name, 6)) {
4271cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN__METHOD;
4281cb0ef41Sopenharmony_ci      }
4291cb0ef41Sopenharmony_ci      break;
4301cb0ef41Sopenharmony_ci    case 'e':
4311cb0ef41Sopenharmony_ci      if (memeq(":schem", name, 6)) {
4321cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN__SCHEME;
4331cb0ef41Sopenharmony_ci      }
4341cb0ef41Sopenharmony_ci      if (memeq("purpos", name, 6)) {
4351cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_PURPOSE;
4361cb0ef41Sopenharmony_ci      }
4371cb0ef41Sopenharmony_ci      if (memeq("upgrad", name, 6)) {
4381cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_UPGRADE;
4391cb0ef41Sopenharmony_ci      }
4401cb0ef41Sopenharmony_ci      break;
4411cb0ef41Sopenharmony_ci    case 'r':
4421cb0ef41Sopenharmony_ci      if (memeq("refere", name, 6)) {
4431cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_REFERER;
4441cb0ef41Sopenharmony_ci      }
4451cb0ef41Sopenharmony_ci      break;
4461cb0ef41Sopenharmony_ci    case 's':
4471cb0ef41Sopenharmony_ci      if (memeq(":statu", name, 6)) {
4481cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN__STATUS;
4491cb0ef41Sopenharmony_ci      }
4501cb0ef41Sopenharmony_ci      break;
4511cb0ef41Sopenharmony_ci    }
4521cb0ef41Sopenharmony_ci    break;
4531cb0ef41Sopenharmony_ci  case 8:
4541cb0ef41Sopenharmony_ci    switch (name[7]) {
4551cb0ef41Sopenharmony_ci    case 'e':
4561cb0ef41Sopenharmony_ci      if (memeq("if-rang", name, 7)) {
4571cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_IF_RANGE;
4581cb0ef41Sopenharmony_ci      }
4591cb0ef41Sopenharmony_ci      break;
4601cb0ef41Sopenharmony_ci    case 'n':
4611cb0ef41Sopenharmony_ci      if (memeq("locatio", name, 7)) {
4621cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_LOCATION;
4631cb0ef41Sopenharmony_ci      }
4641cb0ef41Sopenharmony_ci      break;
4651cb0ef41Sopenharmony_ci    case 'y':
4661cb0ef41Sopenharmony_ci      if (memeq("priorit", name, 7)) {
4671cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_PRIORITY;
4681cb0ef41Sopenharmony_ci      }
4691cb0ef41Sopenharmony_ci      break;
4701cb0ef41Sopenharmony_ci    }
4711cb0ef41Sopenharmony_ci    break;
4721cb0ef41Sopenharmony_ci  case 9:
4731cb0ef41Sopenharmony_ci    switch (name[8]) {
4741cb0ef41Sopenharmony_ci    case 'd':
4751cb0ef41Sopenharmony_ci      if (memeq("forwarde", name, 8)) {
4761cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_FORWARDED;
4771cb0ef41Sopenharmony_ci      }
4781cb0ef41Sopenharmony_ci      break;
4791cb0ef41Sopenharmony_ci    case 'l':
4801cb0ef41Sopenharmony_ci      if (memeq(":protoco", name, 8)) {
4811cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN__PROTOCOL;
4821cb0ef41Sopenharmony_ci      }
4831cb0ef41Sopenharmony_ci      break;
4841cb0ef41Sopenharmony_ci    case 't':
4851cb0ef41Sopenharmony_ci      if (memeq("expect-c", name, 8)) {
4861cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_EXPECT_CT;
4871cb0ef41Sopenharmony_ci      }
4881cb0ef41Sopenharmony_ci      break;
4891cb0ef41Sopenharmony_ci    }
4901cb0ef41Sopenharmony_ci    break;
4911cb0ef41Sopenharmony_ci  case 10:
4921cb0ef41Sopenharmony_ci    switch (name[9]) {
4931cb0ef41Sopenharmony_ci    case 'a':
4941cb0ef41Sopenharmony_ci      if (memeq("early-dat", name, 9)) {
4951cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_EARLY_DATA;
4961cb0ef41Sopenharmony_ci      }
4971cb0ef41Sopenharmony_ci      break;
4981cb0ef41Sopenharmony_ci    case 'e':
4991cb0ef41Sopenharmony_ci      if (memeq("keep-aliv", name, 9)) {
5001cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_KEEP_ALIVE;
5011cb0ef41Sopenharmony_ci      }
5021cb0ef41Sopenharmony_ci      if (memeq("set-cooki", name, 9)) {
5031cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_SET_COOKIE;
5041cb0ef41Sopenharmony_ci      }
5051cb0ef41Sopenharmony_ci      break;
5061cb0ef41Sopenharmony_ci    case 'n':
5071cb0ef41Sopenharmony_ci      if (memeq("connectio", name, 9)) {
5081cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CONNECTION;
5091cb0ef41Sopenharmony_ci      }
5101cb0ef41Sopenharmony_ci      break;
5111cb0ef41Sopenharmony_ci    case 't':
5121cb0ef41Sopenharmony_ci      if (memeq("user-agen", name, 9)) {
5131cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_USER_AGENT;
5141cb0ef41Sopenharmony_ci      }
5151cb0ef41Sopenharmony_ci      break;
5161cb0ef41Sopenharmony_ci    case 'y':
5171cb0ef41Sopenharmony_ci      if (memeq(":authorit", name, 9)) {
5181cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN__AUTHORITY;
5191cb0ef41Sopenharmony_ci      }
5201cb0ef41Sopenharmony_ci      break;
5211cb0ef41Sopenharmony_ci    }
5221cb0ef41Sopenharmony_ci    break;
5231cb0ef41Sopenharmony_ci  case 12:
5241cb0ef41Sopenharmony_ci    switch (name[11]) {
5251cb0ef41Sopenharmony_ci    case 'e':
5261cb0ef41Sopenharmony_ci      if (memeq("content-typ", name, 11)) {
5271cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CONTENT_TYPE;
5281cb0ef41Sopenharmony_ci      }
5291cb0ef41Sopenharmony_ci      break;
5301cb0ef41Sopenharmony_ci    }
5311cb0ef41Sopenharmony_ci    break;
5321cb0ef41Sopenharmony_ci  case 13:
5331cb0ef41Sopenharmony_ci    switch (name[12]) {
5341cb0ef41Sopenharmony_ci    case 'd':
5351cb0ef41Sopenharmony_ci      if (memeq("last-modifie", name, 12)) {
5361cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_LAST_MODIFIED;
5371cb0ef41Sopenharmony_ci      }
5381cb0ef41Sopenharmony_ci      break;
5391cb0ef41Sopenharmony_ci    case 'h':
5401cb0ef41Sopenharmony_ci      if (memeq("if-none-matc", name, 12)) {
5411cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH;
5421cb0ef41Sopenharmony_ci      }
5431cb0ef41Sopenharmony_ci      break;
5441cb0ef41Sopenharmony_ci    case 'l':
5451cb0ef41Sopenharmony_ci      if (memeq("cache-contro", name, 12)) {
5461cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CACHE_CONTROL;
5471cb0ef41Sopenharmony_ci      }
5481cb0ef41Sopenharmony_ci      break;
5491cb0ef41Sopenharmony_ci    case 'n':
5501cb0ef41Sopenharmony_ci      if (memeq("authorizatio", name, 12)) {
5511cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_AUTHORIZATION;
5521cb0ef41Sopenharmony_ci      }
5531cb0ef41Sopenharmony_ci      break;
5541cb0ef41Sopenharmony_ci    case 's':
5551cb0ef41Sopenharmony_ci      if (memeq("accept-range", name, 12)) {
5561cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES;
5571cb0ef41Sopenharmony_ci      }
5581cb0ef41Sopenharmony_ci      break;
5591cb0ef41Sopenharmony_ci    }
5601cb0ef41Sopenharmony_ci    break;
5611cb0ef41Sopenharmony_ci  case 14:
5621cb0ef41Sopenharmony_ci    switch (name[13]) {
5631cb0ef41Sopenharmony_ci    case 'h':
5641cb0ef41Sopenharmony_ci      if (memeq("content-lengt", name, 13)) {
5651cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH;
5661cb0ef41Sopenharmony_ci      }
5671cb0ef41Sopenharmony_ci      break;
5681cb0ef41Sopenharmony_ci    }
5691cb0ef41Sopenharmony_ci    break;
5701cb0ef41Sopenharmony_ci  case 15:
5711cb0ef41Sopenharmony_ci    switch (name[14]) {
5721cb0ef41Sopenharmony_ci    case 'e':
5731cb0ef41Sopenharmony_ci      if (memeq("accept-languag", name, 14)) {
5741cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE;
5751cb0ef41Sopenharmony_ci      }
5761cb0ef41Sopenharmony_ci      break;
5771cb0ef41Sopenharmony_ci    case 'g':
5781cb0ef41Sopenharmony_ci      if (memeq("accept-encodin", name, 14)) {
5791cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING;
5801cb0ef41Sopenharmony_ci      }
5811cb0ef41Sopenharmony_ci      break;
5821cb0ef41Sopenharmony_ci    case 'r':
5831cb0ef41Sopenharmony_ci      if (memeq("x-forwarded-fo", name, 14)) {
5841cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR;
5851cb0ef41Sopenharmony_ci      }
5861cb0ef41Sopenharmony_ci      break;
5871cb0ef41Sopenharmony_ci    case 's':
5881cb0ef41Sopenharmony_ci      if (memeq("x-frame-option", name, 14)) {
5891cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS;
5901cb0ef41Sopenharmony_ci      }
5911cb0ef41Sopenharmony_ci      break;
5921cb0ef41Sopenharmony_ci    }
5931cb0ef41Sopenharmony_ci    break;
5941cb0ef41Sopenharmony_ci  case 16:
5951cb0ef41Sopenharmony_ci    switch (name[15]) {
5961cb0ef41Sopenharmony_ci    case 'g':
5971cb0ef41Sopenharmony_ci      if (memeq("content-encodin", name, 15)) {
5981cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING;
5991cb0ef41Sopenharmony_ci      }
6001cb0ef41Sopenharmony_ci      break;
6011cb0ef41Sopenharmony_ci    case 'n':
6021cb0ef41Sopenharmony_ci      if (memeq("proxy-connectio", name, 15)) {
6031cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION;
6041cb0ef41Sopenharmony_ci      }
6051cb0ef41Sopenharmony_ci      if (memeq("x-xss-protectio", name, 15)) {
6061cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION;
6071cb0ef41Sopenharmony_ci      }
6081cb0ef41Sopenharmony_ci      break;
6091cb0ef41Sopenharmony_ci    }
6101cb0ef41Sopenharmony_ci    break;
6111cb0ef41Sopenharmony_ci  case 17:
6121cb0ef41Sopenharmony_ci    switch (name[16]) {
6131cb0ef41Sopenharmony_ci    case 'e':
6141cb0ef41Sopenharmony_ci      if (memeq("if-modified-sinc", name, 16)) {
6151cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE;
6161cb0ef41Sopenharmony_ci      }
6171cb0ef41Sopenharmony_ci      break;
6181cb0ef41Sopenharmony_ci    case 'g':
6191cb0ef41Sopenharmony_ci      if (memeq("transfer-encodin", name, 16)) {
6201cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING;
6211cb0ef41Sopenharmony_ci      }
6221cb0ef41Sopenharmony_ci      break;
6231cb0ef41Sopenharmony_ci    }
6241cb0ef41Sopenharmony_ci    break;
6251cb0ef41Sopenharmony_ci  case 19:
6261cb0ef41Sopenharmony_ci    switch (name[18]) {
6271cb0ef41Sopenharmony_ci    case 'n':
6281cb0ef41Sopenharmony_ci      if (memeq("content-dispositio", name, 18)) {
6291cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION;
6301cb0ef41Sopenharmony_ci      }
6311cb0ef41Sopenharmony_ci      if (memeq("timing-allow-origi", name, 18)) {
6321cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN;
6331cb0ef41Sopenharmony_ci      }
6341cb0ef41Sopenharmony_ci      break;
6351cb0ef41Sopenharmony_ci    }
6361cb0ef41Sopenharmony_ci    break;
6371cb0ef41Sopenharmony_ci  case 22:
6381cb0ef41Sopenharmony_ci    switch (name[21]) {
6391cb0ef41Sopenharmony_ci    case 's':
6401cb0ef41Sopenharmony_ci      if (memeq("x-content-type-option", name, 21)) {
6411cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS;
6421cb0ef41Sopenharmony_ci      }
6431cb0ef41Sopenharmony_ci      break;
6441cb0ef41Sopenharmony_ci    }
6451cb0ef41Sopenharmony_ci    break;
6461cb0ef41Sopenharmony_ci  case 23:
6471cb0ef41Sopenharmony_ci    switch (name[22]) {
6481cb0ef41Sopenharmony_ci    case 'y':
6491cb0ef41Sopenharmony_ci      if (memeq("content-security-polic", name, 22)) {
6501cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY;
6511cb0ef41Sopenharmony_ci      }
6521cb0ef41Sopenharmony_ci      break;
6531cb0ef41Sopenharmony_ci    }
6541cb0ef41Sopenharmony_ci    break;
6551cb0ef41Sopenharmony_ci  case 25:
6561cb0ef41Sopenharmony_ci    switch (name[24]) {
6571cb0ef41Sopenharmony_ci    case 's':
6581cb0ef41Sopenharmony_ci      if (memeq("upgrade-insecure-request", name, 24)) {
6591cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS;
6601cb0ef41Sopenharmony_ci      }
6611cb0ef41Sopenharmony_ci      break;
6621cb0ef41Sopenharmony_ci    case 'y':
6631cb0ef41Sopenharmony_ci      if (memeq("strict-transport-securit", name, 24)) {
6641cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY;
6651cb0ef41Sopenharmony_ci      }
6661cb0ef41Sopenharmony_ci      break;
6671cb0ef41Sopenharmony_ci    }
6681cb0ef41Sopenharmony_ci    break;
6691cb0ef41Sopenharmony_ci  case 27:
6701cb0ef41Sopenharmony_ci    switch (name[26]) {
6711cb0ef41Sopenharmony_ci    case 'n':
6721cb0ef41Sopenharmony_ci      if (memeq("access-control-allow-origi", name, 26)) {
6731cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
6741cb0ef41Sopenharmony_ci      }
6751cb0ef41Sopenharmony_ci      break;
6761cb0ef41Sopenharmony_ci    }
6771cb0ef41Sopenharmony_ci    break;
6781cb0ef41Sopenharmony_ci  case 28:
6791cb0ef41Sopenharmony_ci    switch (name[27]) {
6801cb0ef41Sopenharmony_ci    case 's':
6811cb0ef41Sopenharmony_ci      if (memeq("access-control-allow-header", name, 27)) {
6821cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS;
6831cb0ef41Sopenharmony_ci      }
6841cb0ef41Sopenharmony_ci      if (memeq("access-control-allow-method", name, 27)) {
6851cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS;
6861cb0ef41Sopenharmony_ci      }
6871cb0ef41Sopenharmony_ci      break;
6881cb0ef41Sopenharmony_ci    }
6891cb0ef41Sopenharmony_ci    break;
6901cb0ef41Sopenharmony_ci  case 29:
6911cb0ef41Sopenharmony_ci    switch (name[28]) {
6921cb0ef41Sopenharmony_ci    case 'd':
6931cb0ef41Sopenharmony_ci      if (memeq("access-control-request-metho", name, 28)) {
6941cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD;
6951cb0ef41Sopenharmony_ci      }
6961cb0ef41Sopenharmony_ci      break;
6971cb0ef41Sopenharmony_ci    case 's':
6981cb0ef41Sopenharmony_ci      if (memeq("access-control-expose-header", name, 28)) {
6991cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS;
7001cb0ef41Sopenharmony_ci      }
7011cb0ef41Sopenharmony_ci      break;
7021cb0ef41Sopenharmony_ci    }
7031cb0ef41Sopenharmony_ci    break;
7041cb0ef41Sopenharmony_ci  case 30:
7051cb0ef41Sopenharmony_ci    switch (name[29]) {
7061cb0ef41Sopenharmony_ci    case 's':
7071cb0ef41Sopenharmony_ci      if (memeq("access-control-request-header", name, 29)) {
7081cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS;
7091cb0ef41Sopenharmony_ci      }
7101cb0ef41Sopenharmony_ci      break;
7111cb0ef41Sopenharmony_ci    }
7121cb0ef41Sopenharmony_ci    break;
7131cb0ef41Sopenharmony_ci  case 32:
7141cb0ef41Sopenharmony_ci    switch (name[31]) {
7151cb0ef41Sopenharmony_ci    case 's':
7161cb0ef41Sopenharmony_ci      if (memeq("access-control-allow-credential", name, 31)) {
7171cb0ef41Sopenharmony_ci        return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS;
7181cb0ef41Sopenharmony_ci      }
7191cb0ef41Sopenharmony_ci      break;
7201cb0ef41Sopenharmony_ci    }
7211cb0ef41Sopenharmony_ci    break;
7221cb0ef41Sopenharmony_ci  }
7231cb0ef41Sopenharmony_ci  return -1;
7241cb0ef41Sopenharmony_ci}
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_cistatic size_t table_space(size_t namelen, size_t valuelen) {
7271cb0ef41Sopenharmony_ci  return NGHTTP3_QPACK_ENTRY_OVERHEAD + namelen + valuelen;
7281cb0ef41Sopenharmony_ci}
7291cb0ef41Sopenharmony_ci
7301cb0ef41Sopenharmony_cistatic int qpack_nv_name_eq(const nghttp3_qpack_nv *a, const nghttp3_nv *b) {
7311cb0ef41Sopenharmony_ci  return a->name->len == b->namelen &&
7321cb0ef41Sopenharmony_ci         memeq(a->name->base, b->name, b->namelen);
7331cb0ef41Sopenharmony_ci}
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_cistatic int qpack_nv_value_eq(const nghttp3_qpack_nv *a, const nghttp3_nv *b) {
7361cb0ef41Sopenharmony_ci  return a->value->len == b->valuelen &&
7371cb0ef41Sopenharmony_ci         memeq(a->value->base, b->value, b->valuelen);
7381cb0ef41Sopenharmony_ci}
7391cb0ef41Sopenharmony_ci
7401cb0ef41Sopenharmony_cistatic void qpack_map_init(nghttp3_qpack_map *map) {
7411cb0ef41Sopenharmony_ci  memset(map, 0, sizeof(nghttp3_qpack_map));
7421cb0ef41Sopenharmony_ci}
7431cb0ef41Sopenharmony_ci
7441cb0ef41Sopenharmony_cistatic void qpack_map_insert(nghttp3_qpack_map *map, nghttp3_qpack_entry *ent) {
7451cb0ef41Sopenharmony_ci  nghttp3_qpack_entry **bucket;
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci  bucket = &map->table[ent->hash & (NGHTTP3_QPACK_MAP_SIZE - 1)];
7481cb0ef41Sopenharmony_ci
7491cb0ef41Sopenharmony_ci  if (*bucket == NULL) {
7501cb0ef41Sopenharmony_ci    *bucket = ent;
7511cb0ef41Sopenharmony_ci    return;
7521cb0ef41Sopenharmony_ci  }
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci  /* larger absidx is linked near the root */
7551cb0ef41Sopenharmony_ci  ent->map_next = *bucket;
7561cb0ef41Sopenharmony_ci  *bucket = ent;
7571cb0ef41Sopenharmony_ci}
7581cb0ef41Sopenharmony_ci
7591cb0ef41Sopenharmony_cistatic void qpack_map_remove(nghttp3_qpack_map *map, nghttp3_qpack_entry *ent) {
7601cb0ef41Sopenharmony_ci  nghttp3_qpack_entry **dst;
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci  dst = &map->table[ent->hash & (NGHTTP3_QPACK_MAP_SIZE - 1)];
7631cb0ef41Sopenharmony_ci
7641cb0ef41Sopenharmony_ci  for (; *dst; dst = &(*dst)->map_next) {
7651cb0ef41Sopenharmony_ci    if (*dst != ent) {
7661cb0ef41Sopenharmony_ci      continue;
7671cb0ef41Sopenharmony_ci    }
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci    *dst = ent->map_next;
7701cb0ef41Sopenharmony_ci    ent->map_next = NULL;
7711cb0ef41Sopenharmony_ci    return;
7721cb0ef41Sopenharmony_ci  }
7731cb0ef41Sopenharmony_ci}
7741cb0ef41Sopenharmony_ci
7751cb0ef41Sopenharmony_ci/*
7761cb0ef41Sopenharmony_ci * qpack_context_can_reference returns nonzero if dynamic table entry
7771cb0ef41Sopenharmony_ci * at |absidx| can be referenced.  In other words, it is within
7781cb0ef41Sopenharmony_ci * ctx->max_dtable_capacity.
7791cb0ef41Sopenharmony_ci */
7801cb0ef41Sopenharmony_cistatic int qpack_context_can_reference(nghttp3_qpack_context *ctx,
7811cb0ef41Sopenharmony_ci                                       uint64_t absidx) {
7821cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent = nghttp3_qpack_context_dtable_get(ctx, absidx);
7831cb0ef41Sopenharmony_ci  return ctx->dtable_sum - ent->sum <= ctx->max_dtable_capacity;
7841cb0ef41Sopenharmony_ci}
7851cb0ef41Sopenharmony_ci
7861cb0ef41Sopenharmony_ci/* |*ppb_match| (post-base match), if it is not NULL, is always exact
7871cb0ef41Sopenharmony_ci     match. */
7881cb0ef41Sopenharmony_cistatic void encoder_qpack_map_find(nghttp3_qpack_encoder *encoder,
7891cb0ef41Sopenharmony_ci                                   int *exact_match,
7901cb0ef41Sopenharmony_ci                                   nghttp3_qpack_entry **pmatch,
7911cb0ef41Sopenharmony_ci                                   nghttp3_qpack_entry **ppb_match,
7921cb0ef41Sopenharmony_ci                                   const nghttp3_nv *nv, int32_t token,
7931cb0ef41Sopenharmony_ci                                   uint32_t hash, uint64_t krcnt,
7941cb0ef41Sopenharmony_ci                                   int allow_blocking, int name_only) {
7951cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *p;
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_ci  *exact_match = 0;
7981cb0ef41Sopenharmony_ci  *pmatch = NULL;
7991cb0ef41Sopenharmony_ci  *ppb_match = NULL;
8001cb0ef41Sopenharmony_ci
8011cb0ef41Sopenharmony_ci  for (p = encoder->dtable_map.table[hash & (NGHTTP3_QPACK_MAP_SIZE - 1)]; p;
8021cb0ef41Sopenharmony_ci       p = p->map_next) {
8031cb0ef41Sopenharmony_ci    if (token != p->nv.token ||
8041cb0ef41Sopenharmony_ci        (token == -1 && (hash != p->hash || !qpack_nv_name_eq(&p->nv, nv))) ||
8051cb0ef41Sopenharmony_ci        !qpack_context_can_reference(&encoder->ctx, p->absidx)) {
8061cb0ef41Sopenharmony_ci      continue;
8071cb0ef41Sopenharmony_ci    }
8081cb0ef41Sopenharmony_ci    if (allow_blocking || p->absidx + 1 <= krcnt) {
8091cb0ef41Sopenharmony_ci      if (!*pmatch) {
8101cb0ef41Sopenharmony_ci        *pmatch = p;
8111cb0ef41Sopenharmony_ci        if (name_only) {
8121cb0ef41Sopenharmony_ci          return;
8131cb0ef41Sopenharmony_ci        }
8141cb0ef41Sopenharmony_ci      }
8151cb0ef41Sopenharmony_ci      if (qpack_nv_value_eq(&p->nv, nv)) {
8161cb0ef41Sopenharmony_ci        *pmatch = p;
8171cb0ef41Sopenharmony_ci        *exact_match = 1;
8181cb0ef41Sopenharmony_ci        return;
8191cb0ef41Sopenharmony_ci      }
8201cb0ef41Sopenharmony_ci    } else if (!*ppb_match && qpack_nv_value_eq(&p->nv, nv)) {
8211cb0ef41Sopenharmony_ci      *ppb_match = p;
8221cb0ef41Sopenharmony_ci    }
8231cb0ef41Sopenharmony_ci  }
8241cb0ef41Sopenharmony_ci}
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci/*
8271cb0ef41Sopenharmony_ci * qpack_context_init initializes |ctx|.  |hard_max_dtable_capacity|
8281cb0ef41Sopenharmony_ci * is the upper bound of the dynamic table capacity.  |mem| is a
8291cb0ef41Sopenharmony_ci * memory allocator.
8301cb0ef41Sopenharmony_ci *
8311cb0ef41Sopenharmony_ci * The maximum dynamic table size is governed by
8321cb0ef41Sopenharmony_ci * ctx->max_dtable_capacity and it is initialized to 0.
8331cb0ef41Sopenharmony_ci * |hard_max_dtable_capacity| is the upper bound of
8341cb0ef41Sopenharmony_ci * ctx->max_dtable_capacity.
8351cb0ef41Sopenharmony_ci *
8361cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
8371cb0ef41Sopenharmony_ci * negative error codes:
8381cb0ef41Sopenharmony_ci *
8391cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM
8401cb0ef41Sopenharmony_ci *     Out of memory.
8411cb0ef41Sopenharmony_ci */
8421cb0ef41Sopenharmony_cistatic int qpack_context_init(nghttp3_qpack_context *ctx,
8431cb0ef41Sopenharmony_ci                              size_t hard_max_dtable_capacity,
8441cb0ef41Sopenharmony_ci                              size_t max_blocked_streams,
8451cb0ef41Sopenharmony_ci                              const nghttp3_mem *mem) {
8461cb0ef41Sopenharmony_ci  int rv;
8471cb0ef41Sopenharmony_ci  size_t len = 4096 / NGHTTP3_QPACK_ENTRY_OVERHEAD;
8481cb0ef41Sopenharmony_ci  size_t len2;
8491cb0ef41Sopenharmony_ci
8501cb0ef41Sopenharmony_ci  for (len2 = 1; len2 < len; len2 <<= 1)
8511cb0ef41Sopenharmony_ci    ;
8521cb0ef41Sopenharmony_ci
8531cb0ef41Sopenharmony_ci  rv = nghttp3_ringbuf_init(&ctx->dtable, len2, sizeof(nghttp3_qpack_entry *),
8541cb0ef41Sopenharmony_ci                            mem);
8551cb0ef41Sopenharmony_ci  if (rv != 0) {
8561cb0ef41Sopenharmony_ci    return rv;
8571cb0ef41Sopenharmony_ci  }
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci  ctx->mem = mem;
8601cb0ef41Sopenharmony_ci  ctx->dtable_size = 0;
8611cb0ef41Sopenharmony_ci  ctx->dtable_sum = 0;
8621cb0ef41Sopenharmony_ci  ctx->hard_max_dtable_capacity = hard_max_dtable_capacity;
8631cb0ef41Sopenharmony_ci  ctx->max_dtable_capacity = 0;
8641cb0ef41Sopenharmony_ci  ctx->max_blocked_streams = max_blocked_streams;
8651cb0ef41Sopenharmony_ci  ctx->next_absidx = 0;
8661cb0ef41Sopenharmony_ci  ctx->bad = 0;
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci  return 0;
8691cb0ef41Sopenharmony_ci}
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_cistatic void qpack_context_free(nghttp3_qpack_context *ctx) {
8721cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
8731cb0ef41Sopenharmony_ci  size_t i, len = nghttp3_ringbuf_len(&ctx->dtable);
8741cb0ef41Sopenharmony_ci
8751cb0ef41Sopenharmony_ci  for (i = 0; i < len; ++i) {
8761cb0ef41Sopenharmony_ci    ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, i);
8771cb0ef41Sopenharmony_ci    nghttp3_qpack_entry_free(ent);
8781cb0ef41Sopenharmony_ci    nghttp3_mem_free(ctx->mem, ent);
8791cb0ef41Sopenharmony_ci  }
8801cb0ef41Sopenharmony_ci  nghttp3_ringbuf_free(&ctx->dtable);
8811cb0ef41Sopenharmony_ci}
8821cb0ef41Sopenharmony_ci
8831cb0ef41Sopenharmony_cistatic int ref_min_cnt_less(const nghttp3_pq_entry *lhsx,
8841cb0ef41Sopenharmony_ci                            const nghttp3_pq_entry *rhsx) {
8851cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *lhs =
8861cb0ef41Sopenharmony_ci      nghttp3_struct_of(lhsx, nghttp3_qpack_header_block_ref, min_cnts_pe);
8871cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *rhs =
8881cb0ef41Sopenharmony_ci      nghttp3_struct_of(rhsx, nghttp3_qpack_header_block_ref, min_cnts_pe);
8891cb0ef41Sopenharmony_ci
8901cb0ef41Sopenharmony_ci  return lhs->min_cnt < rhs->min_cnt;
8911cb0ef41Sopenharmony_ci}
8921cb0ef41Sopenharmony_ci
8931cb0ef41Sopenharmony_citypedef struct nghttp3_blocked_streams_key {
8941cb0ef41Sopenharmony_ci  uint64_t max_cnt;
8951cb0ef41Sopenharmony_ci  uint64_t id;
8961cb0ef41Sopenharmony_ci} nghttp3_blocked_streams_key;
8971cb0ef41Sopenharmony_ci
8981cb0ef41Sopenharmony_cistatic int max_cnt_greater(const nghttp3_ksl_key *lhs,
8991cb0ef41Sopenharmony_ci                           const nghttp3_ksl_key *rhs) {
9001cb0ef41Sopenharmony_ci  const nghttp3_blocked_streams_key *a = lhs;
9011cb0ef41Sopenharmony_ci  const nghttp3_blocked_streams_key *b = rhs;
9021cb0ef41Sopenharmony_ci  return a->max_cnt > b->max_cnt || (a->max_cnt == b->max_cnt && a->id < b->id);
9031cb0ef41Sopenharmony_ci}
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
9061cb0ef41Sopenharmony_ci                               size_t hard_max_dtable_capacity,
9071cb0ef41Sopenharmony_ci                               const nghttp3_mem *mem) {
9081cb0ef41Sopenharmony_ci  int rv;
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci  rv = qpack_context_init(&encoder->ctx, hard_max_dtable_capacity, 0, mem);
9111cb0ef41Sopenharmony_ci  if (rv != 0) {
9121cb0ef41Sopenharmony_ci    return rv;
9131cb0ef41Sopenharmony_ci  }
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_ci  nghttp3_map_init(&encoder->streams, mem);
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ci  nghttp3_ksl_init(&encoder->blocked_streams, max_cnt_greater,
9181cb0ef41Sopenharmony_ci                   sizeof(nghttp3_blocked_streams_key), mem);
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ci  qpack_map_init(&encoder->dtable_map);
9211cb0ef41Sopenharmony_ci  nghttp3_pq_init(&encoder->min_cnts, ref_min_cnt_less, mem);
9221cb0ef41Sopenharmony_ci
9231cb0ef41Sopenharmony_ci  encoder->krcnt = 0;
9241cb0ef41Sopenharmony_ci  encoder->state = NGHTTP3_QPACK_DS_STATE_OPCODE;
9251cb0ef41Sopenharmony_ci  encoder->opcode = 0;
9261cb0ef41Sopenharmony_ci  encoder->min_dtable_update = SIZE_MAX;
9271cb0ef41Sopenharmony_ci  encoder->last_max_dtable_update = 0;
9281cb0ef41Sopenharmony_ci  encoder->flags = NGHTTP3_QPACK_ENCODER_FLAG_NONE;
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state_reset(&encoder->rstate);
9311cb0ef41Sopenharmony_ci
9321cb0ef41Sopenharmony_ci  return 0;
9331cb0ef41Sopenharmony_ci}
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_cistatic int map_stream_free(void *data, void *ptr) {
9361cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = ptr;
9371cb0ef41Sopenharmony_ci  nghttp3_qpack_stream *stream = data;
9381cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_del(stream, mem);
9391cb0ef41Sopenharmony_ci  return 0;
9401cb0ef41Sopenharmony_ci}
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_free(nghttp3_qpack_encoder *encoder) {
9431cb0ef41Sopenharmony_ci  nghttp3_pq_free(&encoder->min_cnts);
9441cb0ef41Sopenharmony_ci  nghttp3_ksl_free(&encoder->blocked_streams);
9451cb0ef41Sopenharmony_ci  nghttp3_map_each_free(&encoder->streams, map_stream_free,
9461cb0ef41Sopenharmony_ci                        (void *)encoder->ctx.mem);
9471cb0ef41Sopenharmony_ci  nghttp3_map_free(&encoder->streams);
9481cb0ef41Sopenharmony_ci  qpack_context_free(&encoder->ctx);
9491cb0ef41Sopenharmony_ci}
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_set_max_dtable_capacity(
9521cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder *encoder, size_t max_dtable_capacity) {
9531cb0ef41Sopenharmony_ci  max_dtable_capacity =
9541cb0ef41Sopenharmony_ci      nghttp3_min(max_dtable_capacity, encoder->ctx.hard_max_dtable_capacity);
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci  if (encoder->ctx.max_dtable_capacity == max_dtable_capacity) {
9571cb0ef41Sopenharmony_ci    return;
9581cb0ef41Sopenharmony_ci  }
9591cb0ef41Sopenharmony_ci
9601cb0ef41Sopenharmony_ci  encoder->flags |= NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP;
9611cb0ef41Sopenharmony_ci
9621cb0ef41Sopenharmony_ci  if (encoder->min_dtable_update > max_dtable_capacity) {
9631cb0ef41Sopenharmony_ci    encoder->min_dtable_update = max_dtable_capacity;
9641cb0ef41Sopenharmony_ci    encoder->ctx.max_dtable_capacity = max_dtable_capacity;
9651cb0ef41Sopenharmony_ci  }
9661cb0ef41Sopenharmony_ci  encoder->last_max_dtable_update = max_dtable_capacity;
9671cb0ef41Sopenharmony_ci}
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_set_max_blocked_streams(
9701cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder *encoder, size_t max_blocked_streams) {
9711cb0ef41Sopenharmony_ci  encoder->ctx.max_blocked_streams = max_blocked_streams;
9721cb0ef41Sopenharmony_ci}
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ciuint64_t nghttp3_qpack_encoder_get_min_cnt(nghttp3_qpack_encoder *encoder) {
9751cb0ef41Sopenharmony_ci  assert(!nghttp3_pq_empty(&encoder->min_cnts));
9761cb0ef41Sopenharmony_ci
9771cb0ef41Sopenharmony_ci  return nghttp3_struct_of(nghttp3_pq_top(&encoder->min_cnts),
9781cb0ef41Sopenharmony_ci                           nghttp3_qpack_header_block_ref, min_cnts_pe)
9791cb0ef41Sopenharmony_ci      ->min_cnt;
9801cb0ef41Sopenharmony_ci}
9811cb0ef41Sopenharmony_ci
9821cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_shrink_dtable(nghttp3_qpack_encoder *encoder) {
9831cb0ef41Sopenharmony_ci  nghttp3_ringbuf *dtable = &encoder->ctx.dtable;
9841cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
9851cb0ef41Sopenharmony_ci  uint64_t min_cnt = UINT64_MAX;
9861cb0ef41Sopenharmony_ci  size_t len;
9871cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
9881cb0ef41Sopenharmony_ci
9891cb0ef41Sopenharmony_ci  if (encoder->ctx.dtable_size <= encoder->ctx.max_dtable_capacity) {
9901cb0ef41Sopenharmony_ci    return;
9911cb0ef41Sopenharmony_ci  }
9921cb0ef41Sopenharmony_ci
9931cb0ef41Sopenharmony_ci  if (!nghttp3_pq_empty(&encoder->min_cnts)) {
9941cb0ef41Sopenharmony_ci    min_cnt = nghttp3_qpack_encoder_get_min_cnt(encoder);
9951cb0ef41Sopenharmony_ci  }
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci  for (; encoder->ctx.dtable_size > encoder->ctx.max_dtable_capacity;) {
9981cb0ef41Sopenharmony_ci    len = nghttp3_ringbuf_len(dtable);
9991cb0ef41Sopenharmony_ci    ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(dtable, len - 1);
10001cb0ef41Sopenharmony_ci    if (ent->absidx + 1 == min_cnt) {
10011cb0ef41Sopenharmony_ci      return;
10021cb0ef41Sopenharmony_ci    }
10031cb0ef41Sopenharmony_ci
10041cb0ef41Sopenharmony_ci    encoder->ctx.dtable_size -=
10051cb0ef41Sopenharmony_ci        table_space(ent->nv.name->len, ent->nv.value->len);
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_ci    nghttp3_ringbuf_pop_back(dtable);
10081cb0ef41Sopenharmony_ci    qpack_map_remove(&encoder->dtable_map, ent);
10091cb0ef41Sopenharmony_ci
10101cb0ef41Sopenharmony_ci    nghttp3_qpack_entry_free(ent);
10111cb0ef41Sopenharmony_ci    nghttp3_mem_free(mem, ent);
10121cb0ef41Sopenharmony_ci  }
10131cb0ef41Sopenharmony_ci}
10141cb0ef41Sopenharmony_ci
10151cb0ef41Sopenharmony_ci/*
10161cb0ef41Sopenharmony_ci * qpack_encoder_add_stream_ref adds another dynamic table reference
10171cb0ef41Sopenharmony_ci * to a stream denoted by |stream_id|.  |stream| must be NULL if no
10181cb0ef41Sopenharmony_ci * stream object is not found for the given stream ID.  |max_cnt| and
10191cb0ef41Sopenharmony_ci * |min_cnt| is the maximum and minimum insert count it references
10201cb0ef41Sopenharmony_ci * respectively.
10211cb0ef41Sopenharmony_ci *
10221cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
10231cb0ef41Sopenharmony_ci * negative error codes:
10241cb0ef41Sopenharmony_ci *
10251cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM
10261cb0ef41Sopenharmony_ci *     Out of memory.
10271cb0ef41Sopenharmony_ci */
10281cb0ef41Sopenharmony_cistatic int qpack_encoder_add_stream_ref(nghttp3_qpack_encoder *encoder,
10291cb0ef41Sopenharmony_ci                                        int64_t stream_id,
10301cb0ef41Sopenharmony_ci                                        nghttp3_qpack_stream *stream,
10311cb0ef41Sopenharmony_ci                                        uint64_t max_cnt, uint64_t min_cnt) {
10321cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref;
10331cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
10341cb0ef41Sopenharmony_ci  uint64_t prev_max_cnt = 0;
10351cb0ef41Sopenharmony_ci  int rv;
10361cb0ef41Sopenharmony_ci
10371cb0ef41Sopenharmony_ci  if (stream == NULL) {
10381cb0ef41Sopenharmony_ci    rv = nghttp3_qpack_stream_new(&stream, stream_id, mem);
10391cb0ef41Sopenharmony_ci    if (rv != 0) {
10401cb0ef41Sopenharmony_ci      assert(rv == NGHTTP3_ERR_NOMEM);
10411cb0ef41Sopenharmony_ci      return rv;
10421cb0ef41Sopenharmony_ci    }
10431cb0ef41Sopenharmony_ci    rv = nghttp3_map_insert(&encoder->streams,
10441cb0ef41Sopenharmony_ci                            (nghttp3_map_key_type)stream->stream_id, stream);
10451cb0ef41Sopenharmony_ci    if (rv != 0) {
10461cb0ef41Sopenharmony_ci      assert(rv == NGHTTP3_ERR_NOMEM);
10471cb0ef41Sopenharmony_ci      nghttp3_qpack_stream_del(stream, mem);
10481cb0ef41Sopenharmony_ci      return rv;
10491cb0ef41Sopenharmony_ci    }
10501cb0ef41Sopenharmony_ci  } else {
10511cb0ef41Sopenharmony_ci    prev_max_cnt = nghttp3_qpack_stream_get_max_cnt(stream);
10521cb0ef41Sopenharmony_ci    if (nghttp3_qpack_encoder_stream_is_blocked(encoder, stream) &&
10531cb0ef41Sopenharmony_ci        max_cnt > prev_max_cnt) {
10541cb0ef41Sopenharmony_ci      nghttp3_qpack_encoder_unblock_stream(encoder, stream);
10551cb0ef41Sopenharmony_ci    }
10561cb0ef41Sopenharmony_ci  }
10571cb0ef41Sopenharmony_ci
10581cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_header_block_ref_new(&ref, max_cnt, min_cnt, mem);
10591cb0ef41Sopenharmony_ci  if (rv != 0) {
10601cb0ef41Sopenharmony_ci    return rv;
10611cb0ef41Sopenharmony_ci  }
10621cb0ef41Sopenharmony_ci
10631cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_stream_add_ref(stream, ref);
10641cb0ef41Sopenharmony_ci  if (rv != 0) {
10651cb0ef41Sopenharmony_ci    nghttp3_qpack_header_block_ref_del(ref, mem);
10661cb0ef41Sopenharmony_ci    return rv;
10671cb0ef41Sopenharmony_ci  }
10681cb0ef41Sopenharmony_ci
10691cb0ef41Sopenharmony_ci  if (max_cnt > prev_max_cnt &&
10701cb0ef41Sopenharmony_ci      nghttp3_qpack_encoder_stream_is_blocked(encoder, stream)) {
10711cb0ef41Sopenharmony_ci    rv = nghttp3_qpack_encoder_block_stream(encoder, stream);
10721cb0ef41Sopenharmony_ci    if (rv != 0) {
10731cb0ef41Sopenharmony_ci      return rv;
10741cb0ef41Sopenharmony_ci    }
10751cb0ef41Sopenharmony_ci  }
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_ci  return nghttp3_pq_push(&encoder->min_cnts, &ref->min_cnts_pe);
10781cb0ef41Sopenharmony_ci}
10791cb0ef41Sopenharmony_ci
10801cb0ef41Sopenharmony_cistatic void qpack_encoder_remove_stream(nghttp3_qpack_encoder *encoder,
10811cb0ef41Sopenharmony_ci                                        nghttp3_qpack_stream *stream) {
10821cb0ef41Sopenharmony_ci  size_t i, len;
10831cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref;
10841cb0ef41Sopenharmony_ci
10851cb0ef41Sopenharmony_ci  nghttp3_map_remove(&encoder->streams,
10861cb0ef41Sopenharmony_ci                     (nghttp3_map_key_type)stream->stream_id);
10871cb0ef41Sopenharmony_ci
10881cb0ef41Sopenharmony_ci  len = nghttp3_ringbuf_len(&stream->refs);
10891cb0ef41Sopenharmony_ci  for (i = 0; i < len; ++i) {
10901cb0ef41Sopenharmony_ci    ref = *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs,
10911cb0ef41Sopenharmony_ci                                                                  i);
10921cb0ef41Sopenharmony_ci
10931cb0ef41Sopenharmony_ci    assert(ref->min_cnts_pe.index != NGHTTP3_PQ_BAD_INDEX);
10941cb0ef41Sopenharmony_ci
10951cb0ef41Sopenharmony_ci    nghttp3_pq_remove(&encoder->min_cnts, &ref->min_cnts_pe);
10961cb0ef41Sopenharmony_ci  }
10971cb0ef41Sopenharmony_ci}
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci/*
11001cb0ef41Sopenharmony_ci * reserve_buf_internal ensures that |buf| contains at least
11011cb0ef41Sopenharmony_ci * |extra_size| of free space.  In other words, if this function
11021cb0ef41Sopenharmony_ci * succeeds, nghttp2_buf_left(buf) >= extra_size holds.  |min_size| is
11031cb0ef41Sopenharmony_ci * the minimum size of buffer.  The allocated buffer has at least
11041cb0ef41Sopenharmony_ci * |min_size| bytes.
11051cb0ef41Sopenharmony_ci *
11061cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
11071cb0ef41Sopenharmony_ci * negative error codes:
11081cb0ef41Sopenharmony_ci *
11091cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM
11101cb0ef41Sopenharmony_ci *     Out of memory.
11111cb0ef41Sopenharmony_ci */
11121cb0ef41Sopenharmony_cistatic int reserve_buf_internal(nghttp3_buf *buf, size_t extra_size,
11131cb0ef41Sopenharmony_ci                                size_t min_size, const nghttp3_mem *mem) {
11141cb0ef41Sopenharmony_ci  size_t left = nghttp3_buf_left(buf);
11151cb0ef41Sopenharmony_ci  size_t n = min_size, need;
11161cb0ef41Sopenharmony_ci
11171cb0ef41Sopenharmony_ci  if (left >= extra_size) {
11181cb0ef41Sopenharmony_ci    return 0;
11191cb0ef41Sopenharmony_ci  }
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_ci  need = nghttp3_buf_cap(buf) + extra_size - left;
11221cb0ef41Sopenharmony_ci
11231cb0ef41Sopenharmony_ci  for (; n < need; n *= 2)
11241cb0ef41Sopenharmony_ci    ;
11251cb0ef41Sopenharmony_ci
11261cb0ef41Sopenharmony_ci  return nghttp3_buf_reserve(buf, n, mem);
11271cb0ef41Sopenharmony_ci}
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_cistatic int reserve_buf_small(nghttp3_buf *buf, size_t extra_size,
11301cb0ef41Sopenharmony_ci                             const nghttp3_mem *mem) {
11311cb0ef41Sopenharmony_ci  return reserve_buf_internal(buf, extra_size, 32, mem);
11321cb0ef41Sopenharmony_ci}
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_cistatic int reserve_buf(nghttp3_buf *buf, size_t extra_size,
11351cb0ef41Sopenharmony_ci                       const nghttp3_mem *mem) {
11361cb0ef41Sopenharmony_ci  return reserve_buf_internal(buf, extra_size, 32, mem);
11371cb0ef41Sopenharmony_ci}
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_encode(nghttp3_qpack_encoder *encoder,
11401cb0ef41Sopenharmony_ci                                 nghttp3_buf *pbuf, nghttp3_buf *rbuf,
11411cb0ef41Sopenharmony_ci                                 nghttp3_buf *ebuf, int64_t stream_id,
11421cb0ef41Sopenharmony_ci                                 const nghttp3_nv *nva, size_t nvlen) {
11431cb0ef41Sopenharmony_ci  size_t i;
11441cb0ef41Sopenharmony_ci  uint64_t max_cnt = 0, min_cnt = UINT64_MAX;
11451cb0ef41Sopenharmony_ci  uint64_t base;
11461cb0ef41Sopenharmony_ci  int rv = 0;
11471cb0ef41Sopenharmony_ci  int allow_blocking;
11481cb0ef41Sopenharmony_ci  int blocked_stream;
11491cb0ef41Sopenharmony_ci  nghttp3_qpack_stream *stream;
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci  if (encoder->ctx.bad) {
11521cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
11531cb0ef41Sopenharmony_ci  }
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_encoder_process_dtable_update(encoder, ebuf);
11561cb0ef41Sopenharmony_ci  if (rv != 0) {
11571cb0ef41Sopenharmony_ci    goto fail;
11581cb0ef41Sopenharmony_ci  }
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci  base = encoder->ctx.next_absidx;
11611cb0ef41Sopenharmony_ci
11621cb0ef41Sopenharmony_ci  stream = nghttp3_qpack_encoder_find_stream(encoder, stream_id);
11631cb0ef41Sopenharmony_ci  blocked_stream =
11641cb0ef41Sopenharmony_ci      stream && nghttp3_qpack_encoder_stream_is_blocked(encoder, stream);
11651cb0ef41Sopenharmony_ci  allow_blocking =
11661cb0ef41Sopenharmony_ci      blocked_stream || encoder->ctx.max_blocked_streams >
11671cb0ef41Sopenharmony_ci                            nghttp3_ksl_len(&encoder->blocked_streams);
11681cb0ef41Sopenharmony_ci
11691cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: stream %ld blocked=%d allow_blocking=%d\n", stream_id,
11701cb0ef41Sopenharmony_ci         blocked_stream, allow_blocking);
11711cb0ef41Sopenharmony_ci
11721cb0ef41Sopenharmony_ci  for (i = 0; i < nvlen; ++i) {
11731cb0ef41Sopenharmony_ci    rv = nghttp3_qpack_encoder_encode_nv(encoder, &max_cnt, &min_cnt, rbuf,
11741cb0ef41Sopenharmony_ci                                         ebuf, &nva[i], base, allow_blocking);
11751cb0ef41Sopenharmony_ci    if (rv != 0) {
11761cb0ef41Sopenharmony_ci      goto fail;
11771cb0ef41Sopenharmony_ci    }
11781cb0ef41Sopenharmony_ci  }
11791cb0ef41Sopenharmony_ci
11801cb0ef41Sopenharmony_ci  nghttp3_qpack_encoder_write_field_section_prefix(encoder, pbuf, max_cnt,
11811cb0ef41Sopenharmony_ci                                                   base);
11821cb0ef41Sopenharmony_ci
11831cb0ef41Sopenharmony_ci  /* TODO If max_cnt == 0, no reference is made to dtable. */
11841cb0ef41Sopenharmony_ci  if (!max_cnt) {
11851cb0ef41Sopenharmony_ci    return 0;
11861cb0ef41Sopenharmony_ci  }
11871cb0ef41Sopenharmony_ci
11881cb0ef41Sopenharmony_ci  rv = qpack_encoder_add_stream_ref(encoder, stream_id, stream, max_cnt,
11891cb0ef41Sopenharmony_ci                                    min_cnt);
11901cb0ef41Sopenharmony_ci  if (rv != 0) {
11911cb0ef41Sopenharmony_ci    goto fail;
11921cb0ef41Sopenharmony_ci  }
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ci  return 0;
11951cb0ef41Sopenharmony_ci
11961cb0ef41Sopenharmony_cifail:
11971cb0ef41Sopenharmony_ci  encoder->ctx.bad = 1;
11981cb0ef41Sopenharmony_ci  return rv;
11991cb0ef41Sopenharmony_ci}
12001cb0ef41Sopenharmony_ci
12011cb0ef41Sopenharmony_ci/*
12021cb0ef41Sopenharmony_ci * qpack_write_number writes variable integer to |rbuf|.  |num| is an
12031cb0ef41Sopenharmony_ci * integer to write.  |prefix| is a prefix of variable integer
12041cb0ef41Sopenharmony_ci * encoding.
12051cb0ef41Sopenharmony_ci *
12061cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
12071cb0ef41Sopenharmony_ci * negative error codes:
12081cb0ef41Sopenharmony_ci *
12091cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM
12101cb0ef41Sopenharmony_ci *     Out of memory.
12111cb0ef41Sopenharmony_ci */
12121cb0ef41Sopenharmony_cistatic int qpack_write_number(nghttp3_buf *rbuf, uint8_t fb, uint64_t num,
12131cb0ef41Sopenharmony_ci                              size_t prefix, const nghttp3_mem *mem) {
12141cb0ef41Sopenharmony_ci  int rv;
12151cb0ef41Sopenharmony_ci  size_t len = nghttp3_qpack_put_varint_len(num, prefix);
12161cb0ef41Sopenharmony_ci  uint8_t *p;
12171cb0ef41Sopenharmony_ci
12181cb0ef41Sopenharmony_ci  rv = reserve_buf(rbuf, len, mem);
12191cb0ef41Sopenharmony_ci  if (rv != 0) {
12201cb0ef41Sopenharmony_ci    return rv;
12211cb0ef41Sopenharmony_ci  }
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  p = rbuf->last;
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci  *p = fb;
12261cb0ef41Sopenharmony_ci  p = nghttp3_qpack_put_varint(p, num, prefix);
12271cb0ef41Sopenharmony_ci
12281cb0ef41Sopenharmony_ci  assert((size_t)(p - rbuf->last) == len);
12291cb0ef41Sopenharmony_ci
12301cb0ef41Sopenharmony_ci  rbuf->last = p;
12311cb0ef41Sopenharmony_ci
12321cb0ef41Sopenharmony_ci  return 0;
12331cb0ef41Sopenharmony_ci}
12341cb0ef41Sopenharmony_ci
12351cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_process_dtable_update(nghttp3_qpack_encoder *encoder,
12361cb0ef41Sopenharmony_ci                                                nghttp3_buf *ebuf) {
12371cb0ef41Sopenharmony_ci  int rv;
12381cb0ef41Sopenharmony_ci
12391cb0ef41Sopenharmony_ci  nghttp3_qpack_encoder_shrink_dtable(encoder);
12401cb0ef41Sopenharmony_ci
12411cb0ef41Sopenharmony_ci  if (encoder->ctx.max_dtable_capacity < encoder->ctx.dtable_size ||
12421cb0ef41Sopenharmony_ci      !(encoder->flags & NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP)) {
12431cb0ef41Sopenharmony_ci    return 0;
12441cb0ef41Sopenharmony_ci  }
12451cb0ef41Sopenharmony_ci
12461cb0ef41Sopenharmony_ci  if (encoder->min_dtable_update < encoder->last_max_dtable_update) {
12471cb0ef41Sopenharmony_ci    rv = nghttp3_qpack_encoder_write_set_dtable_cap(encoder, ebuf,
12481cb0ef41Sopenharmony_ci                                                    encoder->min_dtable_update);
12491cb0ef41Sopenharmony_ci    if (rv != 0) {
12501cb0ef41Sopenharmony_ci      return rv;
12511cb0ef41Sopenharmony_ci    }
12521cb0ef41Sopenharmony_ci  }
12531cb0ef41Sopenharmony_ci
12541cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_encoder_write_set_dtable_cap(
12551cb0ef41Sopenharmony_ci      encoder, ebuf, encoder->last_max_dtable_update);
12561cb0ef41Sopenharmony_ci  if (rv != 0) {
12571cb0ef41Sopenharmony_ci    return rv;
12581cb0ef41Sopenharmony_ci  }
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_ci  encoder->flags &= (uint8_t)~NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP;
12611cb0ef41Sopenharmony_ci  encoder->min_dtable_update = SIZE_MAX;
12621cb0ef41Sopenharmony_ci  encoder->ctx.max_dtable_capacity = encoder->last_max_dtable_update;
12631cb0ef41Sopenharmony_ci
12641cb0ef41Sopenharmony_ci  return 0;
12651cb0ef41Sopenharmony_ci}
12661cb0ef41Sopenharmony_ci
12671cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_set_dtable_cap(nghttp3_qpack_encoder *encoder,
12681cb0ef41Sopenharmony_ci                                               nghttp3_buf *ebuf, size_t cap) {
12691cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Set Dynamic Table Capacity capacity=%zu\n", cap);
12701cb0ef41Sopenharmony_ci  return qpack_write_number(ebuf, 0x20, cap, 5, encoder->ctx.mem);
12711cb0ef41Sopenharmony_ci}
12721cb0ef41Sopenharmony_ci
12731cb0ef41Sopenharmony_cinghttp3_qpack_stream *
12741cb0ef41Sopenharmony_cinghttp3_qpack_encoder_find_stream(nghttp3_qpack_encoder *encoder,
12751cb0ef41Sopenharmony_ci                                  int64_t stream_id) {
12761cb0ef41Sopenharmony_ci  return nghttp3_map_find(&encoder->streams, (nghttp3_map_key_type)stream_id);
12771cb0ef41Sopenharmony_ci}
12781cb0ef41Sopenharmony_ci
12791cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_stream_is_blocked(nghttp3_qpack_encoder *encoder,
12801cb0ef41Sopenharmony_ci                                            nghttp3_qpack_stream *stream) {
12811cb0ef41Sopenharmony_ci  return stream && encoder->krcnt < nghttp3_qpack_stream_get_max_cnt(stream);
12821cb0ef41Sopenharmony_ci}
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ci/*
12851cb0ef41Sopenharmony_ci * qpack_encoder_decide_indexing_mode determines and returns indexing
12861cb0ef41Sopenharmony_ci * mode for header field |nv|.  |token| is a token of header field
12871cb0ef41Sopenharmony_ci * name.
12881cb0ef41Sopenharmony_ci */
12891cb0ef41Sopenharmony_cistatic nghttp3_qpack_indexing_mode
12901cb0ef41Sopenharmony_ciqpack_encoder_decide_indexing_mode(nghttp3_qpack_encoder *encoder,
12911cb0ef41Sopenharmony_ci                                   const nghttp3_nv *nv, int32_t token) {
12921cb0ef41Sopenharmony_ci  if (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) {
12931cb0ef41Sopenharmony_ci    return NGHTTP3_QPACK_INDEXING_MODE_NEVER;
12941cb0ef41Sopenharmony_ci  }
12951cb0ef41Sopenharmony_ci
12961cb0ef41Sopenharmony_ci  switch (token) {
12971cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_AUTHORIZATION:
12981cb0ef41Sopenharmony_ci    return NGHTTP3_QPACK_INDEXING_MODE_NEVER;
12991cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_COOKIE:
13001cb0ef41Sopenharmony_ci    if (nv->valuelen < 20) {
13011cb0ef41Sopenharmony_ci      return NGHTTP3_QPACK_INDEXING_MODE_NEVER;
13021cb0ef41Sopenharmony_ci    }
13031cb0ef41Sopenharmony_ci    break;
13041cb0ef41Sopenharmony_ci  case -1:
13051cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN__PATH:
13061cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_AGE:
13071cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH:
13081cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_ETAG:
13091cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE:
13101cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH:
13111cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_LOCATION:
13121cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_SET_COOKIE:
13131cb0ef41Sopenharmony_ci    return NGHTTP3_QPACK_INDEXING_MODE_LITERAL;
13141cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_HOST:
13151cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_TE:
13161cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN__PROTOCOL:
13171cb0ef41Sopenharmony_ci  case NGHTTP3_QPACK_TOKEN_PRIORITY:
13181cb0ef41Sopenharmony_ci    break;
13191cb0ef41Sopenharmony_ci  default:
13201cb0ef41Sopenharmony_ci    if (token >= 1000) {
13211cb0ef41Sopenharmony_ci      return NGHTTP3_QPACK_INDEXING_MODE_LITERAL;
13221cb0ef41Sopenharmony_ci    }
13231cb0ef41Sopenharmony_ci  }
13241cb0ef41Sopenharmony_ci
13251cb0ef41Sopenharmony_ci  if (table_space(nv->namelen, nv->valuelen) >
13261cb0ef41Sopenharmony_ci      encoder->ctx.max_dtable_capacity * 3 / 4) {
13271cb0ef41Sopenharmony_ci    return NGHTTP3_QPACK_INDEXING_MODE_LITERAL;
13281cb0ef41Sopenharmony_ci  }
13291cb0ef41Sopenharmony_ci
13301cb0ef41Sopenharmony_ci  return NGHTTP3_QPACK_INDEXING_MODE_STORE;
13311cb0ef41Sopenharmony_ci}
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ci/*
13341cb0ef41Sopenharmony_ci * qpack_encoder_can_index returns nonzero if an entry which occupies
13351cb0ef41Sopenharmony_ci * |need| bytes can be inserted into dynamic table.  |min_cnt| is the
13361cb0ef41Sopenharmony_ci * minimum insert count which blocked stream requires.
13371cb0ef41Sopenharmony_ci */
13381cb0ef41Sopenharmony_cistatic int qpack_encoder_can_index(nghttp3_qpack_encoder *encoder, size_t need,
13391cb0ef41Sopenharmony_ci                                   uint64_t min_cnt) {
13401cb0ef41Sopenharmony_ci  size_t avail = 0;
13411cb0ef41Sopenharmony_ci  size_t len;
13421cb0ef41Sopenharmony_ci  uint64_t gmin_cnt;
13431cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *min_ent, *last_ent;
13441cb0ef41Sopenharmony_ci  nghttp3_ringbuf *dtable = &encoder->ctx.dtable;
13451cb0ef41Sopenharmony_ci
13461cb0ef41Sopenharmony_ci  if (encoder->ctx.max_dtable_capacity > encoder->ctx.dtable_size) {
13471cb0ef41Sopenharmony_ci    avail = encoder->ctx.max_dtable_capacity - encoder->ctx.dtable_size;
13481cb0ef41Sopenharmony_ci    if (need <= avail) {
13491cb0ef41Sopenharmony_ci      return 1;
13501cb0ef41Sopenharmony_ci    }
13511cb0ef41Sopenharmony_ci  }
13521cb0ef41Sopenharmony_ci
13531cb0ef41Sopenharmony_ci  if (!nghttp3_pq_empty(&encoder->min_cnts)) {
13541cb0ef41Sopenharmony_ci    gmin_cnt = nghttp3_qpack_encoder_get_min_cnt(encoder);
13551cb0ef41Sopenharmony_ci    min_cnt = nghttp3_min(min_cnt, gmin_cnt);
13561cb0ef41Sopenharmony_ci  }
13571cb0ef41Sopenharmony_ci
13581cb0ef41Sopenharmony_ci  if (min_cnt == UINT64_MAX) {
13591cb0ef41Sopenharmony_ci    return encoder->ctx.max_dtable_capacity >= need;
13601cb0ef41Sopenharmony_ci  }
13611cb0ef41Sopenharmony_ci
13621cb0ef41Sopenharmony_ci  min_ent = nghttp3_qpack_context_dtable_get(&encoder->ctx, min_cnt - 1);
13631cb0ef41Sopenharmony_ci
13641cb0ef41Sopenharmony_ci  len = nghttp3_ringbuf_len(&encoder->ctx.dtable);
13651cb0ef41Sopenharmony_ci  assert(len);
13661cb0ef41Sopenharmony_ci  last_ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(dtable, len - 1);
13671cb0ef41Sopenharmony_ci
13681cb0ef41Sopenharmony_ci  if (min_ent == last_ent) {
13691cb0ef41Sopenharmony_ci    return 0;
13701cb0ef41Sopenharmony_ci  }
13711cb0ef41Sopenharmony_ci
13721cb0ef41Sopenharmony_ci  return avail + min_ent->sum - last_ent->sum >= need;
13731cb0ef41Sopenharmony_ci}
13741cb0ef41Sopenharmony_ci
13751cb0ef41Sopenharmony_ci/*
13761cb0ef41Sopenharmony_ci * qpack_encoder_can_index_nv returns nonzero if header field |nv| can
13771cb0ef41Sopenharmony_ci * be inserted into dynamic table.  |min_cnt| is the minimum insert
13781cb0ef41Sopenharmony_ci * count which blocked stream requires.
13791cb0ef41Sopenharmony_ci */
13801cb0ef41Sopenharmony_cistatic int qpack_encoder_can_index_nv(nghttp3_qpack_encoder *encoder,
13811cb0ef41Sopenharmony_ci                                      const nghttp3_nv *nv, uint64_t min_cnt) {
13821cb0ef41Sopenharmony_ci  return qpack_encoder_can_index(
13831cb0ef41Sopenharmony_ci      encoder, table_space(nv->namelen, nv->valuelen), min_cnt);
13841cb0ef41Sopenharmony_ci}
13851cb0ef41Sopenharmony_ci
13861cb0ef41Sopenharmony_ci/*
13871cb0ef41Sopenharmony_ci * qpack_encoder_can_index_duplicate returns nonzero if an entry at
13881cb0ef41Sopenharmony_ci * |absidx| in dynamic table can be inserted to dynamic table as
13891cb0ef41Sopenharmony_ci * duplicate.  |min_cnt| is the minimum insert count which blocked
13901cb0ef41Sopenharmony_ci * stream requires.
13911cb0ef41Sopenharmony_ci */
13921cb0ef41Sopenharmony_cistatic int qpack_encoder_can_index_duplicate(nghttp3_qpack_encoder *encoder,
13931cb0ef41Sopenharmony_ci                                             uint64_t absidx,
13941cb0ef41Sopenharmony_ci                                             uint64_t min_cnt) {
13951cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent =
13961cb0ef41Sopenharmony_ci      nghttp3_qpack_context_dtable_get(&encoder->ctx, absidx);
13971cb0ef41Sopenharmony_ci
13981cb0ef41Sopenharmony_ci  return qpack_encoder_can_index(
13991cb0ef41Sopenharmony_ci      encoder, table_space(ent->nv.name->len, ent->nv.value->len), min_cnt);
14001cb0ef41Sopenharmony_ci}
14011cb0ef41Sopenharmony_ci
14021cb0ef41Sopenharmony_ci/*
14031cb0ef41Sopenharmony_ci * qpack_context_check_draining returns nonzero if an entry at
14041cb0ef41Sopenharmony_ci * |absidx| in dynamic table is one of draining entries.
14051cb0ef41Sopenharmony_ci */
14061cb0ef41Sopenharmony_cistatic int qpack_context_check_draining(nghttp3_qpack_context *ctx,
14071cb0ef41Sopenharmony_ci                                        uint64_t absidx) {
14081cb0ef41Sopenharmony_ci  const size_t safe = ctx->max_dtable_capacity -
14091cb0ef41Sopenharmony_ci                      nghttp3_min(512, ctx->max_dtable_capacity * 1 / 8);
14101cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent = nghttp3_qpack_context_dtable_get(ctx, absidx);
14111cb0ef41Sopenharmony_ci
14121cb0ef41Sopenharmony_ci  return ctx->dtable_sum - ent->sum > safe;
14131cb0ef41Sopenharmony_ci}
14141cb0ef41Sopenharmony_ci
14151cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
14161cb0ef41Sopenharmony_ci                                    uint64_t *pmax_cnt, uint64_t *pmin_cnt,
14171cb0ef41Sopenharmony_ci                                    nghttp3_buf *rbuf, nghttp3_buf *ebuf,
14181cb0ef41Sopenharmony_ci                                    const nghttp3_nv *nv, uint64_t base,
14191cb0ef41Sopenharmony_ci                                    int allow_blocking) {
14201cb0ef41Sopenharmony_ci  uint32_t hash = 0;
14211cb0ef41Sopenharmony_ci  int32_t token;
14221cb0ef41Sopenharmony_ci  nghttp3_qpack_indexing_mode indexing_mode;
14231cb0ef41Sopenharmony_ci  nghttp3_qpack_lookup_result sres = {-1, 0, -1}, dres = {-1, 0, -1};
14241cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *new_ent = NULL;
14251cb0ef41Sopenharmony_ci  int static_entry;
14261cb0ef41Sopenharmony_ci  int just_index = 0;
14271cb0ef41Sopenharmony_ci  int rv;
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_ci  token = qpack_lookup_token(nv->name, nv->namelen);
14301cb0ef41Sopenharmony_ci  static_entry = token != -1 && (size_t)token < nghttp3_arraylen(token_stable);
14311cb0ef41Sopenharmony_ci  if (static_entry) {
14321cb0ef41Sopenharmony_ci    hash = token_stable[token].hash;
14331cb0ef41Sopenharmony_ci  } else {
14341cb0ef41Sopenharmony_ci    switch (token) {
14351cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_TOKEN_HOST:
14361cb0ef41Sopenharmony_ci      hash = 2952701295u;
14371cb0ef41Sopenharmony_ci      break;
14381cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_TOKEN_TE:
14391cb0ef41Sopenharmony_ci      hash = 1011170994u;
14401cb0ef41Sopenharmony_ci      break;
14411cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_TOKEN__PROTOCOL:
14421cb0ef41Sopenharmony_ci      hash = 1128642621u;
14431cb0ef41Sopenharmony_ci      break;
14441cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_TOKEN_PRIORITY:
14451cb0ef41Sopenharmony_ci      hash = 2498028297u;
14461cb0ef41Sopenharmony_ci      break;
14471cb0ef41Sopenharmony_ci    }
14481cb0ef41Sopenharmony_ci  }
14491cb0ef41Sopenharmony_ci
14501cb0ef41Sopenharmony_ci  indexing_mode = qpack_encoder_decide_indexing_mode(encoder, nv, token);
14511cb0ef41Sopenharmony_ci
14521cb0ef41Sopenharmony_ci  if (static_entry) {
14531cb0ef41Sopenharmony_ci    sres = nghttp3_qpack_lookup_stable(nv, token, indexing_mode);
14541cb0ef41Sopenharmony_ci    if (sres.index != -1 && sres.name_value_match) {
14551cb0ef41Sopenharmony_ci      return nghttp3_qpack_encoder_write_static_indexed(encoder, rbuf,
14561cb0ef41Sopenharmony_ci                                                        (size_t)sres.index);
14571cb0ef41Sopenharmony_ci    }
14581cb0ef41Sopenharmony_ci  }
14591cb0ef41Sopenharmony_ci
14601cb0ef41Sopenharmony_ci  if (hash &&
14611cb0ef41Sopenharmony_ci      nghttp3_map_size(&encoder->streams) < NGHTTP3_QPACK_MAX_QPACK_STREAMS) {
14621cb0ef41Sopenharmony_ci    dres = nghttp3_qpack_encoder_lookup_dtable(encoder, nv, token, hash,
14631cb0ef41Sopenharmony_ci                                               indexing_mode, encoder->krcnt,
14641cb0ef41Sopenharmony_ci                                               allow_blocking);
14651cb0ef41Sopenharmony_ci    just_index = indexing_mode == NGHTTP3_QPACK_INDEXING_MODE_STORE &&
14661cb0ef41Sopenharmony_ci                 dres.pb_index == -1;
14671cb0ef41Sopenharmony_ci  }
14681cb0ef41Sopenharmony_ci
14691cb0ef41Sopenharmony_ci  if (dres.index != -1 && dres.name_value_match) {
14701cb0ef41Sopenharmony_ci    if (allow_blocking &&
14711cb0ef41Sopenharmony_ci        qpack_context_check_draining(&encoder->ctx, (size_t)dres.index) &&
14721cb0ef41Sopenharmony_ci        qpack_encoder_can_index_duplicate(encoder, (size_t)dres.index,
14731cb0ef41Sopenharmony_ci                                          *pmin_cnt)) {
14741cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_encoder_write_duplicate_insert(encoder, ebuf,
14751cb0ef41Sopenharmony_ci                                                        (size_t)dres.index);
14761cb0ef41Sopenharmony_ci      if (rv != 0) {
14771cb0ef41Sopenharmony_ci        return rv;
14781cb0ef41Sopenharmony_ci      }
14791cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_encoder_dtable_duplicate_add(encoder,
14801cb0ef41Sopenharmony_ci                                                      (size_t)dres.index);
14811cb0ef41Sopenharmony_ci      if (rv != 0) {
14821cb0ef41Sopenharmony_ci        return rv;
14831cb0ef41Sopenharmony_ci      }
14841cb0ef41Sopenharmony_ci
14851cb0ef41Sopenharmony_ci      new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
14861cb0ef41Sopenharmony_ci      dres.index = (nghttp3_ssize)new_ent->absidx;
14871cb0ef41Sopenharmony_ci    }
14881cb0ef41Sopenharmony_ci    *pmax_cnt = nghttp3_max(*pmax_cnt, (size_t)(dres.index + 1));
14891cb0ef41Sopenharmony_ci    *pmin_cnt = nghttp3_min(*pmin_cnt, (size_t)(dres.index + 1));
14901cb0ef41Sopenharmony_ci
14911cb0ef41Sopenharmony_ci    return nghttp3_qpack_encoder_write_dynamic_indexed(
14921cb0ef41Sopenharmony_ci        encoder, rbuf, (size_t)dres.index, base);
14931cb0ef41Sopenharmony_ci  }
14941cb0ef41Sopenharmony_ci
14951cb0ef41Sopenharmony_ci  if (sres.index != -1) {
14961cb0ef41Sopenharmony_ci    if (just_index && qpack_encoder_can_index_nv(encoder, nv, *pmin_cnt)) {
14971cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_encoder_write_static_insert(encoder, ebuf,
14981cb0ef41Sopenharmony_ci                                                     (size_t)sres.index, nv);
14991cb0ef41Sopenharmony_ci      if (rv != 0) {
15001cb0ef41Sopenharmony_ci        return rv;
15011cb0ef41Sopenharmony_ci      }
15021cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_encoder_dtable_static_add(encoder, (size_t)sres.index,
15031cb0ef41Sopenharmony_ci                                                   nv, hash);
15041cb0ef41Sopenharmony_ci      if (rv != 0) {
15051cb0ef41Sopenharmony_ci        return rv;
15061cb0ef41Sopenharmony_ci      }
15071cb0ef41Sopenharmony_ci      if (allow_blocking) {
15081cb0ef41Sopenharmony_ci        new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
15091cb0ef41Sopenharmony_ci        *pmax_cnt = nghttp3_max(*pmax_cnt, new_ent->absidx + 1);
15101cb0ef41Sopenharmony_ci        *pmin_cnt = nghttp3_min(*pmin_cnt, new_ent->absidx + 1);
15111cb0ef41Sopenharmony_ci
15121cb0ef41Sopenharmony_ci        return nghttp3_qpack_encoder_write_dynamic_indexed(
15131cb0ef41Sopenharmony_ci            encoder, rbuf, new_ent->absidx, base);
15141cb0ef41Sopenharmony_ci      }
15151cb0ef41Sopenharmony_ci    }
15161cb0ef41Sopenharmony_ci
15171cb0ef41Sopenharmony_ci    return nghttp3_qpack_encoder_write_static_indexed_name(
15181cb0ef41Sopenharmony_ci        encoder, rbuf, (size_t)sres.index, nv);
15191cb0ef41Sopenharmony_ci  }
15201cb0ef41Sopenharmony_ci
15211cb0ef41Sopenharmony_ci  if (dres.index != -1) {
15221cb0ef41Sopenharmony_ci    if (just_index &&
15231cb0ef41Sopenharmony_ci        qpack_encoder_can_index_nv(
15241cb0ef41Sopenharmony_ci            encoder, nv,
15251cb0ef41Sopenharmony_ci            allow_blocking ? *pmin_cnt
15261cb0ef41Sopenharmony_ci                           : nghttp3_min((size_t)dres.index + 1, *pmin_cnt))) {
15271cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_encoder_write_dynamic_insert(encoder, ebuf,
15281cb0ef41Sopenharmony_ci                                                      (size_t)dres.index, nv);
15291cb0ef41Sopenharmony_ci      if (rv != 0) {
15301cb0ef41Sopenharmony_ci        return rv;
15311cb0ef41Sopenharmony_ci      }
15321cb0ef41Sopenharmony_ci
15331cb0ef41Sopenharmony_ci      if (!allow_blocking) {
15341cb0ef41Sopenharmony_ci        *pmin_cnt = nghttp3_min(*pmin_cnt, (size_t)dres.index + 1);
15351cb0ef41Sopenharmony_ci      }
15361cb0ef41Sopenharmony_ci
15371cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_encoder_dtable_dynamic_add(encoder, (size_t)dres.index,
15381cb0ef41Sopenharmony_ci                                                    nv, hash);
15391cb0ef41Sopenharmony_ci      if (rv != 0) {
15401cb0ef41Sopenharmony_ci        return rv;
15411cb0ef41Sopenharmony_ci      }
15421cb0ef41Sopenharmony_ci
15431cb0ef41Sopenharmony_ci      if (allow_blocking) {
15441cb0ef41Sopenharmony_ci        new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
15451cb0ef41Sopenharmony_ci        *pmax_cnt = nghttp3_max(*pmax_cnt, new_ent->absidx + 1);
15461cb0ef41Sopenharmony_ci        *pmin_cnt = nghttp3_min(*pmin_cnt, new_ent->absidx + 1);
15471cb0ef41Sopenharmony_ci
15481cb0ef41Sopenharmony_ci        return nghttp3_qpack_encoder_write_dynamic_indexed(
15491cb0ef41Sopenharmony_ci            encoder, rbuf, new_ent->absidx, base);
15501cb0ef41Sopenharmony_ci      }
15511cb0ef41Sopenharmony_ci    }
15521cb0ef41Sopenharmony_ci
15531cb0ef41Sopenharmony_ci    *pmax_cnt = nghttp3_max(*pmax_cnt, (size_t)(dres.index + 1));
15541cb0ef41Sopenharmony_ci    *pmin_cnt = nghttp3_min(*pmin_cnt, (size_t)(dres.index + 1));
15551cb0ef41Sopenharmony_ci
15561cb0ef41Sopenharmony_ci    return nghttp3_qpack_encoder_write_dynamic_indexed_name(
15571cb0ef41Sopenharmony_ci        encoder, rbuf, (size_t)dres.index, base, nv);
15581cb0ef41Sopenharmony_ci  }
15591cb0ef41Sopenharmony_ci
15601cb0ef41Sopenharmony_ci  if (just_index && qpack_encoder_can_index_nv(encoder, nv, *pmin_cnt)) {
15611cb0ef41Sopenharmony_ci    rv = nghttp3_qpack_encoder_dtable_literal_add(encoder, nv, token, hash);
15621cb0ef41Sopenharmony_ci    if (rv != 0) {
15631cb0ef41Sopenharmony_ci      return rv;
15641cb0ef41Sopenharmony_ci    }
15651cb0ef41Sopenharmony_ci    rv = nghttp3_qpack_encoder_write_literal_insert(encoder, ebuf, nv);
15661cb0ef41Sopenharmony_ci    if (rv != 0) {
15671cb0ef41Sopenharmony_ci      return rv;
15681cb0ef41Sopenharmony_ci    }
15691cb0ef41Sopenharmony_ci    if (allow_blocking) {
15701cb0ef41Sopenharmony_ci      new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
15711cb0ef41Sopenharmony_ci      *pmax_cnt = nghttp3_max(*pmax_cnt, new_ent->absidx + 1);
15721cb0ef41Sopenharmony_ci      *pmin_cnt = nghttp3_min(*pmin_cnt, new_ent->absidx + 1);
15731cb0ef41Sopenharmony_ci
15741cb0ef41Sopenharmony_ci      return nghttp3_qpack_encoder_write_dynamic_indexed(encoder, rbuf,
15751cb0ef41Sopenharmony_ci                                                         new_ent->absidx, base);
15761cb0ef41Sopenharmony_ci    }
15771cb0ef41Sopenharmony_ci  }
15781cb0ef41Sopenharmony_ci
15791cb0ef41Sopenharmony_ci  return nghttp3_qpack_encoder_write_literal(encoder, rbuf, nv);
15801cb0ef41Sopenharmony_ci}
15811cb0ef41Sopenharmony_ci
15821cb0ef41Sopenharmony_cinghttp3_qpack_lookup_result
15831cb0ef41Sopenharmony_cinghttp3_qpack_lookup_stable(const nghttp3_nv *nv, int32_t token,
15841cb0ef41Sopenharmony_ci                            nghttp3_qpack_indexing_mode indexing_mode) {
15851cb0ef41Sopenharmony_ci  nghttp3_qpack_lookup_result res = {(nghttp3_ssize)token_stable[token].absidx,
15861cb0ef41Sopenharmony_ci                                     0, -1};
15871cb0ef41Sopenharmony_ci  nghttp3_qpack_static_entry *ent;
15881cb0ef41Sopenharmony_ci  nghttp3_qpack_static_header *hdr;
15891cb0ef41Sopenharmony_ci  size_t i;
15901cb0ef41Sopenharmony_ci
15911cb0ef41Sopenharmony_ci  assert(token >= 0);
15921cb0ef41Sopenharmony_ci
15931cb0ef41Sopenharmony_ci  if (indexing_mode == NGHTTP3_QPACK_INDEXING_MODE_NEVER) {
15941cb0ef41Sopenharmony_ci    return res;
15951cb0ef41Sopenharmony_ci  }
15961cb0ef41Sopenharmony_ci
15971cb0ef41Sopenharmony_ci  for (i = (size_t)token;
15981cb0ef41Sopenharmony_ci       i < nghttp3_arraylen(token_stable) && token_stable[i].token == token;
15991cb0ef41Sopenharmony_ci       ++i) {
16001cb0ef41Sopenharmony_ci    ent = &token_stable[i];
16011cb0ef41Sopenharmony_ci    hdr = &stable[ent->absidx];
16021cb0ef41Sopenharmony_ci    if (hdr->value.len == nv->valuelen &&
16031cb0ef41Sopenharmony_ci        memeq(hdr->value.base, nv->value, nv->valuelen)) {
16041cb0ef41Sopenharmony_ci      res.index = (nghttp3_ssize)ent->absidx;
16051cb0ef41Sopenharmony_ci      res.name_value_match = 1;
16061cb0ef41Sopenharmony_ci      return res;
16071cb0ef41Sopenharmony_ci    }
16081cb0ef41Sopenharmony_ci  }
16091cb0ef41Sopenharmony_ci  return res;
16101cb0ef41Sopenharmony_ci}
16111cb0ef41Sopenharmony_ci
16121cb0ef41Sopenharmony_cinghttp3_qpack_lookup_result nghttp3_qpack_encoder_lookup_dtable(
16131cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder *encoder, const nghttp3_nv *nv, int32_t token,
16141cb0ef41Sopenharmony_ci    uint32_t hash, nghttp3_qpack_indexing_mode indexing_mode, uint64_t krcnt,
16151cb0ef41Sopenharmony_ci    int allow_blocking) {
16161cb0ef41Sopenharmony_ci  nghttp3_qpack_lookup_result res = {-1, 0, -1};
16171cb0ef41Sopenharmony_ci  int exact_match = 0;
16181cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *match, *pb_match;
16191cb0ef41Sopenharmony_ci
16201cb0ef41Sopenharmony_ci  encoder_qpack_map_find(encoder, &exact_match, &match, &pb_match, nv, token,
16211cb0ef41Sopenharmony_ci                         hash, krcnt, allow_blocking,
16221cb0ef41Sopenharmony_ci                         indexing_mode == NGHTTP3_QPACK_INDEXING_MODE_NEVER);
16231cb0ef41Sopenharmony_ci  if (match) {
16241cb0ef41Sopenharmony_ci    res.index = (nghttp3_ssize)match->absidx;
16251cb0ef41Sopenharmony_ci    res.name_value_match = exact_match;
16261cb0ef41Sopenharmony_ci  }
16271cb0ef41Sopenharmony_ci  if (pb_match) {
16281cb0ef41Sopenharmony_ci    res.pb_index = (nghttp3_ssize)pb_match->absidx;
16291cb0ef41Sopenharmony_ci  }
16301cb0ef41Sopenharmony_ci
16311cb0ef41Sopenharmony_ci  return res;
16321cb0ef41Sopenharmony_ci}
16331cb0ef41Sopenharmony_ci
16341cb0ef41Sopenharmony_ciint nghttp3_qpack_header_block_ref_new(nghttp3_qpack_header_block_ref **pref,
16351cb0ef41Sopenharmony_ci                                       uint64_t max_cnt, uint64_t min_cnt,
16361cb0ef41Sopenharmony_ci                                       const nghttp3_mem *mem) {
16371cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref =
16381cb0ef41Sopenharmony_ci      nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_header_block_ref));
16391cb0ef41Sopenharmony_ci
16401cb0ef41Sopenharmony_ci  if (ref == NULL) {
16411cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_NOMEM;
16421cb0ef41Sopenharmony_ci  }
16431cb0ef41Sopenharmony_ci
16441cb0ef41Sopenharmony_ci  ref->max_cnts_pe.index = NGHTTP3_PQ_BAD_INDEX;
16451cb0ef41Sopenharmony_ci  ref->min_cnts_pe.index = NGHTTP3_PQ_BAD_INDEX;
16461cb0ef41Sopenharmony_ci  ref->max_cnt = max_cnt;
16471cb0ef41Sopenharmony_ci  ref->min_cnt = min_cnt;
16481cb0ef41Sopenharmony_ci
16491cb0ef41Sopenharmony_ci  *pref = ref;
16501cb0ef41Sopenharmony_ci
16511cb0ef41Sopenharmony_ci  return 0;
16521cb0ef41Sopenharmony_ci}
16531cb0ef41Sopenharmony_ci
16541cb0ef41Sopenharmony_civoid nghttp3_qpack_header_block_ref_del(nghttp3_qpack_header_block_ref *ref,
16551cb0ef41Sopenharmony_ci                                        const nghttp3_mem *mem) {
16561cb0ef41Sopenharmony_ci  nghttp3_mem_free(mem, ref);
16571cb0ef41Sopenharmony_ci}
16581cb0ef41Sopenharmony_ci
16591cb0ef41Sopenharmony_cistatic int ref_max_cnt_greater(const nghttp3_pq_entry *lhsx,
16601cb0ef41Sopenharmony_ci                               const nghttp3_pq_entry *rhsx) {
16611cb0ef41Sopenharmony_ci  const nghttp3_qpack_header_block_ref *lhs =
16621cb0ef41Sopenharmony_ci      nghttp3_struct_of(lhsx, nghttp3_qpack_header_block_ref, max_cnts_pe);
16631cb0ef41Sopenharmony_ci  const nghttp3_qpack_header_block_ref *rhs =
16641cb0ef41Sopenharmony_ci      nghttp3_struct_of(rhsx, nghttp3_qpack_header_block_ref, max_cnts_pe);
16651cb0ef41Sopenharmony_ci
16661cb0ef41Sopenharmony_ci  return lhs->max_cnt > rhs->max_cnt;
16671cb0ef41Sopenharmony_ci}
16681cb0ef41Sopenharmony_ci
16691cb0ef41Sopenharmony_ciint nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
16701cb0ef41Sopenharmony_ci                             const nghttp3_mem *mem) {
16711cb0ef41Sopenharmony_ci  int rv;
16721cb0ef41Sopenharmony_ci  nghttp3_qpack_stream *stream;
16731cb0ef41Sopenharmony_ci
16741cb0ef41Sopenharmony_ci  stream = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream));
16751cb0ef41Sopenharmony_ci  if (stream == NULL) {
16761cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_NOMEM;
16771cb0ef41Sopenharmony_ci  }
16781cb0ef41Sopenharmony_ci
16791cb0ef41Sopenharmony_ci  rv = nghttp3_ringbuf_init(&stream->refs, 4,
16801cb0ef41Sopenharmony_ci                            sizeof(nghttp3_qpack_header_block_ref *), mem);
16811cb0ef41Sopenharmony_ci  if (rv != 0) {
16821cb0ef41Sopenharmony_ci    nghttp3_mem_free(mem, stream);
16831cb0ef41Sopenharmony_ci    return rv;
16841cb0ef41Sopenharmony_ci  }
16851cb0ef41Sopenharmony_ci
16861cb0ef41Sopenharmony_ci  nghttp3_pq_init(&stream->max_cnts, ref_max_cnt_greater, mem);
16871cb0ef41Sopenharmony_ci
16881cb0ef41Sopenharmony_ci  stream->stream_id = stream_id;
16891cb0ef41Sopenharmony_ci
16901cb0ef41Sopenharmony_ci  *pstream = stream;
16911cb0ef41Sopenharmony_ci
16921cb0ef41Sopenharmony_ci  return 0;
16931cb0ef41Sopenharmony_ci}
16941cb0ef41Sopenharmony_ci
16951cb0ef41Sopenharmony_civoid nghttp3_qpack_stream_del(nghttp3_qpack_stream *stream,
16961cb0ef41Sopenharmony_ci                              const nghttp3_mem *mem) {
16971cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref;
16981cb0ef41Sopenharmony_ci  size_t i, len;
16991cb0ef41Sopenharmony_ci
17001cb0ef41Sopenharmony_ci  if (stream == NULL) {
17011cb0ef41Sopenharmony_ci    return;
17021cb0ef41Sopenharmony_ci  }
17031cb0ef41Sopenharmony_ci
17041cb0ef41Sopenharmony_ci  nghttp3_pq_free(&stream->max_cnts);
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_ci  len = nghttp3_ringbuf_len(&stream->refs);
17071cb0ef41Sopenharmony_ci  for (i = 0; i < len; ++i) {
17081cb0ef41Sopenharmony_ci    ref = *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs,
17091cb0ef41Sopenharmony_ci                                                                  i);
17101cb0ef41Sopenharmony_ci    nghttp3_qpack_header_block_ref_del(ref, mem);
17111cb0ef41Sopenharmony_ci  }
17121cb0ef41Sopenharmony_ci
17131cb0ef41Sopenharmony_ci  nghttp3_ringbuf_free(&stream->refs);
17141cb0ef41Sopenharmony_ci
17151cb0ef41Sopenharmony_ci  nghttp3_mem_free(mem, stream);
17161cb0ef41Sopenharmony_ci}
17171cb0ef41Sopenharmony_ci
17181cb0ef41Sopenharmony_ciuint64_t nghttp3_qpack_stream_get_max_cnt(const nghttp3_qpack_stream *stream) {
17191cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref;
17201cb0ef41Sopenharmony_ci
17211cb0ef41Sopenharmony_ci  if (nghttp3_pq_empty(&stream->max_cnts)) {
17221cb0ef41Sopenharmony_ci    return 0;
17231cb0ef41Sopenharmony_ci  }
17241cb0ef41Sopenharmony_ci
17251cb0ef41Sopenharmony_ci  ref = nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
17261cb0ef41Sopenharmony_ci                          nghttp3_qpack_header_block_ref, max_cnts_pe);
17271cb0ef41Sopenharmony_ci  return ref->max_cnt;
17281cb0ef41Sopenharmony_ci}
17291cb0ef41Sopenharmony_ci
17301cb0ef41Sopenharmony_ciint nghttp3_qpack_stream_add_ref(nghttp3_qpack_stream *stream,
17311cb0ef41Sopenharmony_ci                                 nghttp3_qpack_header_block_ref *ref) {
17321cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref **dest;
17331cb0ef41Sopenharmony_ci  int rv;
17341cb0ef41Sopenharmony_ci
17351cb0ef41Sopenharmony_ci  if (nghttp3_ringbuf_full(&stream->refs)) {
17361cb0ef41Sopenharmony_ci    rv = nghttp3_ringbuf_reserve(&stream->refs,
17371cb0ef41Sopenharmony_ci                                 nghttp3_ringbuf_len(&stream->refs) * 2);
17381cb0ef41Sopenharmony_ci    if (rv != 0) {
17391cb0ef41Sopenharmony_ci      return rv;
17401cb0ef41Sopenharmony_ci    }
17411cb0ef41Sopenharmony_ci  }
17421cb0ef41Sopenharmony_ci
17431cb0ef41Sopenharmony_ci  dest = nghttp3_ringbuf_push_back(&stream->refs);
17441cb0ef41Sopenharmony_ci  *dest = ref;
17451cb0ef41Sopenharmony_ci
17461cb0ef41Sopenharmony_ci  return nghttp3_pq_push(&stream->max_cnts, &ref->max_cnts_pe);
17471cb0ef41Sopenharmony_ci}
17481cb0ef41Sopenharmony_ci
17491cb0ef41Sopenharmony_civoid nghttp3_qpack_stream_pop_ref(nghttp3_qpack_stream *stream) {
17501cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref;
17511cb0ef41Sopenharmony_ci
17521cb0ef41Sopenharmony_ci  assert(nghttp3_ringbuf_len(&stream->refs));
17531cb0ef41Sopenharmony_ci
17541cb0ef41Sopenharmony_ci  ref =
17551cb0ef41Sopenharmony_ci      *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs, 0);
17561cb0ef41Sopenharmony_ci
17571cb0ef41Sopenharmony_ci  assert(ref->max_cnts_pe.index != NGHTTP3_PQ_BAD_INDEX);
17581cb0ef41Sopenharmony_ci
17591cb0ef41Sopenharmony_ci  nghttp3_pq_remove(&stream->max_cnts, &ref->max_cnts_pe);
17601cb0ef41Sopenharmony_ci
17611cb0ef41Sopenharmony_ci  nghttp3_ringbuf_pop_front(&stream->refs);
17621cb0ef41Sopenharmony_ci}
17631cb0ef41Sopenharmony_ci
17641cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_static_indexed(nghttp3_qpack_encoder *encoder,
17651cb0ef41Sopenharmony_ci                                               nghttp3_buf *rbuf,
17661cb0ef41Sopenharmony_ci                                               uint64_t absidx) {
17671cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Indexed Field Line (static) absidx=%" PRIu64 "\n",
17681cb0ef41Sopenharmony_ci         absidx);
17691cb0ef41Sopenharmony_ci  return qpack_write_number(rbuf, 0xc0, absidx, 6, encoder->ctx.mem);
17701cb0ef41Sopenharmony_ci}
17711cb0ef41Sopenharmony_ci
17721cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_dynamic_indexed(nghttp3_qpack_encoder *encoder,
17731cb0ef41Sopenharmony_ci                                                nghttp3_buf *rbuf,
17741cb0ef41Sopenharmony_ci                                                uint64_t absidx,
17751cb0ef41Sopenharmony_ci                                                uint64_t base) {
17761cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Indexed Field Line (dynamic) absidx=%" PRIu64
17771cb0ef41Sopenharmony_ci         " base=%" PRIu64 "\n",
17781cb0ef41Sopenharmony_ci         absidx, base);
17791cb0ef41Sopenharmony_ci
17801cb0ef41Sopenharmony_ci  if (absidx < base) {
17811cb0ef41Sopenharmony_ci    return qpack_write_number(rbuf, 0x80, base - absidx - 1, 6,
17821cb0ef41Sopenharmony_ci                              encoder->ctx.mem);
17831cb0ef41Sopenharmony_ci  }
17841cb0ef41Sopenharmony_ci
17851cb0ef41Sopenharmony_ci  return qpack_write_number(rbuf, 0x10, absidx - base, 4, encoder->ctx.mem);
17861cb0ef41Sopenharmony_ci}
17871cb0ef41Sopenharmony_ci
17881cb0ef41Sopenharmony_ci/*
17891cb0ef41Sopenharmony_ci * qpack_encoder_write_indexed_name writes generic indexed name.  |fb|
17901cb0ef41Sopenharmony_ci * is the first byte.  |nameidx| is an index of referenced name.
17911cb0ef41Sopenharmony_ci * |prefix| is a prefix of variable integer encoding.  |nv| is a
17921cb0ef41Sopenharmony_ci * header field to encode.
17931cb0ef41Sopenharmony_ci *
17941cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
17951cb0ef41Sopenharmony_ci * negative error codes:
17961cb0ef41Sopenharmony_ci *
17971cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM
17981cb0ef41Sopenharmony_ci *     Out of memory.
17991cb0ef41Sopenharmony_ci */
18001cb0ef41Sopenharmony_cistatic int qpack_encoder_write_indexed_name(nghttp3_qpack_encoder *encoder,
18011cb0ef41Sopenharmony_ci                                            nghttp3_buf *buf, uint8_t fb,
18021cb0ef41Sopenharmony_ci                                            uint64_t nameidx, size_t prefix,
18031cb0ef41Sopenharmony_ci                                            const nghttp3_nv *nv) {
18041cb0ef41Sopenharmony_ci  int rv;
18051cb0ef41Sopenharmony_ci  size_t len = nghttp3_qpack_put_varint_len(nameidx, prefix);
18061cb0ef41Sopenharmony_ci  uint8_t *p;
18071cb0ef41Sopenharmony_ci  size_t hlen;
18081cb0ef41Sopenharmony_ci  int h = 0;
18091cb0ef41Sopenharmony_ci
18101cb0ef41Sopenharmony_ci  hlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
18111cb0ef41Sopenharmony_ci  if (hlen < nv->valuelen) {
18121cb0ef41Sopenharmony_ci    h = 1;
18131cb0ef41Sopenharmony_ci    len += nghttp3_qpack_put_varint_len(hlen, 7) + hlen;
18141cb0ef41Sopenharmony_ci  } else {
18151cb0ef41Sopenharmony_ci    len += nghttp3_qpack_put_varint_len(nv->valuelen, 7) + nv->valuelen;
18161cb0ef41Sopenharmony_ci  }
18171cb0ef41Sopenharmony_ci
18181cb0ef41Sopenharmony_ci  rv = reserve_buf(buf, len, encoder->ctx.mem);
18191cb0ef41Sopenharmony_ci  if (rv != 0) {
18201cb0ef41Sopenharmony_ci    return rv;
18211cb0ef41Sopenharmony_ci  }
18221cb0ef41Sopenharmony_ci
18231cb0ef41Sopenharmony_ci  p = buf->last;
18241cb0ef41Sopenharmony_ci
18251cb0ef41Sopenharmony_ci  *p = fb;
18261cb0ef41Sopenharmony_ci  p = nghttp3_qpack_put_varint(p, nameidx, prefix);
18271cb0ef41Sopenharmony_ci
18281cb0ef41Sopenharmony_ci  if (h) {
18291cb0ef41Sopenharmony_ci    *p = 0x80;
18301cb0ef41Sopenharmony_ci    p = nghttp3_qpack_put_varint(p, hlen, 7);
18311cb0ef41Sopenharmony_ci    p = nghttp3_qpack_huffman_encode(p, nv->value, nv->valuelen);
18321cb0ef41Sopenharmony_ci  } else {
18331cb0ef41Sopenharmony_ci    *p = 0;
18341cb0ef41Sopenharmony_ci    p = nghttp3_qpack_put_varint(p, nv->valuelen, 7);
18351cb0ef41Sopenharmony_ci    if (nv->valuelen) {
18361cb0ef41Sopenharmony_ci      p = nghttp3_cpymem(p, nv->value, nv->valuelen);
18371cb0ef41Sopenharmony_ci    }
18381cb0ef41Sopenharmony_ci  }
18391cb0ef41Sopenharmony_ci
18401cb0ef41Sopenharmony_ci  assert((size_t)(p - buf->last) == len);
18411cb0ef41Sopenharmony_ci
18421cb0ef41Sopenharmony_ci  buf->last = p;
18431cb0ef41Sopenharmony_ci
18441cb0ef41Sopenharmony_ci  return 0;
18451cb0ef41Sopenharmony_ci}
18461cb0ef41Sopenharmony_ci
18471cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_static_indexed_name(
18481cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder *encoder, nghttp3_buf *rbuf, uint64_t absidx,
18491cb0ef41Sopenharmony_ci    const nghttp3_nv *nv) {
18501cb0ef41Sopenharmony_ci  uint8_t fb =
18511cb0ef41Sopenharmony_ci      (uint8_t)(0x50 | ((nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x20 : 0));
18521cb0ef41Sopenharmony_ci
18531cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Literal Field Line With Name Reference (static) "
18541cb0ef41Sopenharmony_ci         "absidx=%" PRIu64 " never=%d\n",
18551cb0ef41Sopenharmony_ci         absidx, (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) != 0);
18561cb0ef41Sopenharmony_ci  return qpack_encoder_write_indexed_name(encoder, rbuf, fb, absidx, 4, nv);
18571cb0ef41Sopenharmony_ci}
18581cb0ef41Sopenharmony_ci
18591cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_dynamic_indexed_name(
18601cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder *encoder, nghttp3_buf *rbuf, uint64_t absidx,
18611cb0ef41Sopenharmony_ci    uint64_t base, const nghttp3_nv *nv) {
18621cb0ef41Sopenharmony_ci  uint8_t fb;
18631cb0ef41Sopenharmony_ci
18641cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Literal Field Line With Name Reference (dynamic) "
18651cb0ef41Sopenharmony_ci         "absidx=%" PRIu64 " base=%" PRIu64 " never=%d\n",
18661cb0ef41Sopenharmony_ci         absidx, base, (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) != 0);
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ci  if (absidx < base) {
18691cb0ef41Sopenharmony_ci    fb = (uint8_t)(0x40 |
18701cb0ef41Sopenharmony_ci                   ((nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x20 : 0));
18711cb0ef41Sopenharmony_ci    return qpack_encoder_write_indexed_name(encoder, rbuf, fb,
18721cb0ef41Sopenharmony_ci                                            base - absidx - 1, 4, nv);
18731cb0ef41Sopenharmony_ci  }
18741cb0ef41Sopenharmony_ci
18751cb0ef41Sopenharmony_ci  fb = (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x08 : 0;
18761cb0ef41Sopenharmony_ci  return qpack_encoder_write_indexed_name(encoder, rbuf, fb, absidx - base, 3,
18771cb0ef41Sopenharmony_ci                                          nv);
18781cb0ef41Sopenharmony_ci}
18791cb0ef41Sopenharmony_ci
18801cb0ef41Sopenharmony_ci/*
18811cb0ef41Sopenharmony_ci * qpack_encoder_write_literal writes generic literal header field
18821cb0ef41Sopenharmony_ci * representation.  |fb| is a first byte.  |prefix| is a prefix of
18831cb0ef41Sopenharmony_ci * variable integer encoding for name length.  |nv| is a header field
18841cb0ef41Sopenharmony_ci * to encode.
18851cb0ef41Sopenharmony_ci *
18861cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
18871cb0ef41Sopenharmony_ci * negative error codes:
18881cb0ef41Sopenharmony_ci *
18891cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM
18901cb0ef41Sopenharmony_ci *     Out of memory.
18911cb0ef41Sopenharmony_ci */
18921cb0ef41Sopenharmony_cistatic int qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
18931cb0ef41Sopenharmony_ci                                       nghttp3_buf *buf, uint8_t fb,
18941cb0ef41Sopenharmony_ci                                       size_t prefix, const nghttp3_nv *nv) {
18951cb0ef41Sopenharmony_ci  int rv;
18961cb0ef41Sopenharmony_ci  size_t len;
18971cb0ef41Sopenharmony_ci  uint8_t *p;
18981cb0ef41Sopenharmony_ci  size_t nhlen, vhlen;
18991cb0ef41Sopenharmony_ci  int nh = 0, vh = 0;
19001cb0ef41Sopenharmony_ci
19011cb0ef41Sopenharmony_ci  nhlen = nghttp3_qpack_huffman_encode_count(nv->name, nv->namelen);
19021cb0ef41Sopenharmony_ci  if (nhlen < nv->namelen) {
19031cb0ef41Sopenharmony_ci    nh = 1;
19041cb0ef41Sopenharmony_ci    len = nghttp3_qpack_put_varint_len(nhlen, prefix) + nhlen;
19051cb0ef41Sopenharmony_ci  } else {
19061cb0ef41Sopenharmony_ci    len = nghttp3_qpack_put_varint_len(nv->namelen, prefix) + nv->namelen;
19071cb0ef41Sopenharmony_ci  }
19081cb0ef41Sopenharmony_ci
19091cb0ef41Sopenharmony_ci  vhlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
19101cb0ef41Sopenharmony_ci  if (vhlen < nv->valuelen) {
19111cb0ef41Sopenharmony_ci    vh = 1;
19121cb0ef41Sopenharmony_ci    len += nghttp3_qpack_put_varint_len(vhlen, 7) + vhlen;
19131cb0ef41Sopenharmony_ci  } else {
19141cb0ef41Sopenharmony_ci    len += nghttp3_qpack_put_varint_len(nv->valuelen, 7) + nv->valuelen;
19151cb0ef41Sopenharmony_ci  }
19161cb0ef41Sopenharmony_ci
19171cb0ef41Sopenharmony_ci  rv = reserve_buf(buf, len, encoder->ctx.mem);
19181cb0ef41Sopenharmony_ci  if (rv != 0) {
19191cb0ef41Sopenharmony_ci    return rv;
19201cb0ef41Sopenharmony_ci  }
19211cb0ef41Sopenharmony_ci
19221cb0ef41Sopenharmony_ci  p = buf->last;
19231cb0ef41Sopenharmony_ci
19241cb0ef41Sopenharmony_ci  *p = fb;
19251cb0ef41Sopenharmony_ci  if (nh) {
19261cb0ef41Sopenharmony_ci    *p |= (uint8_t)(1 << prefix);
19271cb0ef41Sopenharmony_ci    p = nghttp3_qpack_put_varint(p, nhlen, prefix);
19281cb0ef41Sopenharmony_ci    p = nghttp3_qpack_huffman_encode(p, nv->name, nv->namelen);
19291cb0ef41Sopenharmony_ci  } else {
19301cb0ef41Sopenharmony_ci    p = nghttp3_qpack_put_varint(p, nv->namelen, prefix);
19311cb0ef41Sopenharmony_ci    if (nv->namelen) {
19321cb0ef41Sopenharmony_ci      p = nghttp3_cpymem(p, nv->name, nv->namelen);
19331cb0ef41Sopenharmony_ci    }
19341cb0ef41Sopenharmony_ci  }
19351cb0ef41Sopenharmony_ci
19361cb0ef41Sopenharmony_ci  *p = 0;
19371cb0ef41Sopenharmony_ci
19381cb0ef41Sopenharmony_ci  if (vh) {
19391cb0ef41Sopenharmony_ci    *p |= 0x80;
19401cb0ef41Sopenharmony_ci    p = nghttp3_qpack_put_varint(p, vhlen, 7);
19411cb0ef41Sopenharmony_ci    p = nghttp3_qpack_huffman_encode(p, nv->value, nv->valuelen);
19421cb0ef41Sopenharmony_ci  } else {
19431cb0ef41Sopenharmony_ci    p = nghttp3_qpack_put_varint(p, nv->valuelen, 7);
19441cb0ef41Sopenharmony_ci    if (nv->valuelen) {
19451cb0ef41Sopenharmony_ci      p = nghttp3_cpymem(p, nv->value, nv->valuelen);
19461cb0ef41Sopenharmony_ci    }
19471cb0ef41Sopenharmony_ci  }
19481cb0ef41Sopenharmony_ci
19491cb0ef41Sopenharmony_ci  assert((size_t)(p - buf->last) == len);
19501cb0ef41Sopenharmony_ci
19511cb0ef41Sopenharmony_ci  buf->last = p;
19521cb0ef41Sopenharmony_ci
19531cb0ef41Sopenharmony_ci  return 0;
19541cb0ef41Sopenharmony_ci}
19551cb0ef41Sopenharmony_ci
19561cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
19571cb0ef41Sopenharmony_ci                                        nghttp3_buf *rbuf,
19581cb0ef41Sopenharmony_ci                                        const nghttp3_nv *nv) {
19591cb0ef41Sopenharmony_ci  uint8_t fb =
19601cb0ef41Sopenharmony_ci      (uint8_t)(0x20 | ((nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x10 : 0));
19611cb0ef41Sopenharmony_ci
19621cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Literal Field Line With Literal Name\n");
19631cb0ef41Sopenharmony_ci  return qpack_encoder_write_literal(encoder, rbuf, fb, 3, nv);
19641cb0ef41Sopenharmony_ci}
19651cb0ef41Sopenharmony_ci
19661cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_static_insert(nghttp3_qpack_encoder *encoder,
19671cb0ef41Sopenharmony_ci                                              nghttp3_buf *ebuf,
19681cb0ef41Sopenharmony_ci                                              uint64_t absidx,
19691cb0ef41Sopenharmony_ci                                              const nghttp3_nv *nv) {
19701cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Insert With Name Reference (static) absidx=%" PRIu64
19711cb0ef41Sopenharmony_ci         "\n",
19721cb0ef41Sopenharmony_ci         absidx);
19731cb0ef41Sopenharmony_ci  return qpack_encoder_write_indexed_name(encoder, ebuf, 0xc0, absidx, 6, nv);
19741cb0ef41Sopenharmony_ci}
19751cb0ef41Sopenharmony_ci
19761cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_dynamic_insert(nghttp3_qpack_encoder *encoder,
19771cb0ef41Sopenharmony_ci                                               nghttp3_buf *ebuf,
19781cb0ef41Sopenharmony_ci                                               uint64_t absidx,
19791cb0ef41Sopenharmony_ci                                               const nghttp3_nv *nv) {
19801cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Insert With Name Reference (dynamic) absidx=%" PRIu64
19811cb0ef41Sopenharmony_ci         "\n",
19821cb0ef41Sopenharmony_ci         absidx);
19831cb0ef41Sopenharmony_ci  return qpack_encoder_write_indexed_name(
19841cb0ef41Sopenharmony_ci      encoder, ebuf, 0x80, encoder->ctx.next_absidx - absidx - 1, 6, nv);
19851cb0ef41Sopenharmony_ci}
19861cb0ef41Sopenharmony_ci
19871cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_duplicate_insert(nghttp3_qpack_encoder *encoder,
19881cb0ef41Sopenharmony_ci                                                 nghttp3_buf *ebuf,
19891cb0ef41Sopenharmony_ci                                                 uint64_t absidx) {
19901cb0ef41Sopenharmony_ci  uint64_t idx = encoder->ctx.next_absidx - absidx - 1;
19911cb0ef41Sopenharmony_ci  size_t len = nghttp3_qpack_put_varint_len(idx, 5);
19921cb0ef41Sopenharmony_ci  uint8_t *p;
19931cb0ef41Sopenharmony_ci  int rv;
19941cb0ef41Sopenharmony_ci
19951cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Insert duplicate absidx=%" PRIu64 "\n", absidx);
19961cb0ef41Sopenharmony_ci
19971cb0ef41Sopenharmony_ci  rv = reserve_buf(ebuf, len, encoder->ctx.mem);
19981cb0ef41Sopenharmony_ci  if (rv != 0) {
19991cb0ef41Sopenharmony_ci    return rv;
20001cb0ef41Sopenharmony_ci  }
20011cb0ef41Sopenharmony_ci
20021cb0ef41Sopenharmony_ci  p = ebuf->last;
20031cb0ef41Sopenharmony_ci
20041cb0ef41Sopenharmony_ci  *p = 0;
20051cb0ef41Sopenharmony_ci  p = nghttp3_qpack_put_varint(p, idx, 5);
20061cb0ef41Sopenharmony_ci
20071cb0ef41Sopenharmony_ci  assert((size_t)(p - ebuf->last) == len);
20081cb0ef41Sopenharmony_ci
20091cb0ef41Sopenharmony_ci  ebuf->last = p;
20101cb0ef41Sopenharmony_ci
20111cb0ef41Sopenharmony_ci  return 0;
20121cb0ef41Sopenharmony_ci}
20131cb0ef41Sopenharmony_ci
20141cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_literal_insert(nghttp3_qpack_encoder *encoder,
20151cb0ef41Sopenharmony_ci                                               nghttp3_buf *ebuf,
20161cb0ef41Sopenharmony_ci                                               const nghttp3_nv *nv) {
20171cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: Insert With Literal Name\n");
20181cb0ef41Sopenharmony_ci  return qpack_encoder_write_literal(encoder, ebuf, 0x40, 5, nv);
20191cb0ef41Sopenharmony_ci}
20201cb0ef41Sopenharmony_ci
20211cb0ef41Sopenharmony_ciint nghttp3_qpack_context_dtable_add(nghttp3_qpack_context *ctx,
20221cb0ef41Sopenharmony_ci                                     nghttp3_qpack_nv *qnv,
20231cb0ef41Sopenharmony_ci                                     nghttp3_qpack_map *dtable_map,
20241cb0ef41Sopenharmony_ci                                     uint32_t hash) {
20251cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *new_ent, **p, *ent;
20261cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = ctx->mem;
20271cb0ef41Sopenharmony_ci  size_t space;
20281cb0ef41Sopenharmony_ci  size_t i;
20291cb0ef41Sopenharmony_ci  int rv;
20301cb0ef41Sopenharmony_ci
20311cb0ef41Sopenharmony_ci  space = table_space(qnv->name->len, qnv->value->len);
20321cb0ef41Sopenharmony_ci
20331cb0ef41Sopenharmony_ci  assert(space <= ctx->max_dtable_capacity);
20341cb0ef41Sopenharmony_ci
20351cb0ef41Sopenharmony_ci  while (ctx->dtable_size + space > ctx->max_dtable_capacity) {
20361cb0ef41Sopenharmony_ci    i = nghttp3_ringbuf_len(&ctx->dtable);
20371cb0ef41Sopenharmony_ci    assert(i);
20381cb0ef41Sopenharmony_ci    ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, i - 1);
20391cb0ef41Sopenharmony_ci
20401cb0ef41Sopenharmony_ci    ctx->dtable_size -= table_space(ent->nv.name->len, ent->nv.value->len);
20411cb0ef41Sopenharmony_ci
20421cb0ef41Sopenharmony_ci    nghttp3_ringbuf_pop_back(&ctx->dtable);
20431cb0ef41Sopenharmony_ci    if (dtable_map) {
20441cb0ef41Sopenharmony_ci      qpack_map_remove(dtable_map, ent);
20451cb0ef41Sopenharmony_ci    }
20461cb0ef41Sopenharmony_ci
20471cb0ef41Sopenharmony_ci    nghttp3_qpack_entry_free(ent);
20481cb0ef41Sopenharmony_ci    nghttp3_mem_free(mem, ent);
20491cb0ef41Sopenharmony_ci  }
20501cb0ef41Sopenharmony_ci
20511cb0ef41Sopenharmony_ci  new_ent = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_entry));
20521cb0ef41Sopenharmony_ci  if (new_ent == NULL) {
20531cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_NOMEM;
20541cb0ef41Sopenharmony_ci  }
20551cb0ef41Sopenharmony_ci
20561cb0ef41Sopenharmony_ci  nghttp3_qpack_entry_init(new_ent, qnv, ctx->dtable_sum, ctx->next_absidx++,
20571cb0ef41Sopenharmony_ci                           hash);
20581cb0ef41Sopenharmony_ci
20591cb0ef41Sopenharmony_ci  if (nghttp3_ringbuf_full(&ctx->dtable)) {
20601cb0ef41Sopenharmony_ci    rv = nghttp3_ringbuf_reserve(&ctx->dtable,
20611cb0ef41Sopenharmony_ci                                 nghttp3_ringbuf_len(&ctx->dtable) * 2);
20621cb0ef41Sopenharmony_ci    if (rv != 0) {
20631cb0ef41Sopenharmony_ci      goto fail;
20641cb0ef41Sopenharmony_ci    }
20651cb0ef41Sopenharmony_ci  }
20661cb0ef41Sopenharmony_ci
20671cb0ef41Sopenharmony_ci  p = nghttp3_ringbuf_push_front(&ctx->dtable);
20681cb0ef41Sopenharmony_ci  *p = new_ent;
20691cb0ef41Sopenharmony_ci
20701cb0ef41Sopenharmony_ci  if (dtable_map) {
20711cb0ef41Sopenharmony_ci    qpack_map_insert(dtable_map, new_ent);
20721cb0ef41Sopenharmony_ci  }
20731cb0ef41Sopenharmony_ci
20741cb0ef41Sopenharmony_ci  ctx->dtable_size += space;
20751cb0ef41Sopenharmony_ci  ctx->dtable_sum += space;
20761cb0ef41Sopenharmony_ci
20771cb0ef41Sopenharmony_ci  return 0;
20781cb0ef41Sopenharmony_ci
20791cb0ef41Sopenharmony_cifail:
20801cb0ef41Sopenharmony_ci  nghttp3_qpack_entry_free(new_ent);
20811cb0ef41Sopenharmony_ci  nghttp3_mem_free(mem, new_ent);
20821cb0ef41Sopenharmony_ci
20831cb0ef41Sopenharmony_ci  return rv;
20841cb0ef41Sopenharmony_ci}
20851cb0ef41Sopenharmony_ci
20861cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_dtable_static_add(nghttp3_qpack_encoder *encoder,
20871cb0ef41Sopenharmony_ci                                            uint64_t absidx,
20881cb0ef41Sopenharmony_ci                                            const nghttp3_nv *nv,
20891cb0ef41Sopenharmony_ci                                            uint32_t hash) {
20901cb0ef41Sopenharmony_ci  const nghttp3_qpack_static_header *shd;
20911cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
20921cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
20931cb0ef41Sopenharmony_ci  int rv;
20941cb0ef41Sopenharmony_ci
20951cb0ef41Sopenharmony_ci  rv = nghttp3_rcbuf_new2(&qnv.value, nv->value, nv->valuelen, mem);
20961cb0ef41Sopenharmony_ci  if (rv != 0) {
20971cb0ef41Sopenharmony_ci    return rv;
20981cb0ef41Sopenharmony_ci  }
20991cb0ef41Sopenharmony_ci
21001cb0ef41Sopenharmony_ci  assert(nghttp3_arraylen(stable) > absidx);
21011cb0ef41Sopenharmony_ci
21021cb0ef41Sopenharmony_ci  shd = &stable[absidx];
21031cb0ef41Sopenharmony_ci
21041cb0ef41Sopenharmony_ci  qnv.name = (nghttp3_rcbuf *)&shd->name;
21051cb0ef41Sopenharmony_ci  qnv.token = shd->token;
21061cb0ef41Sopenharmony_ci  qnv.flags = NGHTTP3_NV_FLAG_NONE;
21071cb0ef41Sopenharmony_ci
21081cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
21091cb0ef41Sopenharmony_ci                                        &encoder->dtable_map, hash);
21101cb0ef41Sopenharmony_ci
21111cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
21121cb0ef41Sopenharmony_ci
21131cb0ef41Sopenharmony_ci  return rv;
21141cb0ef41Sopenharmony_ci}
21151cb0ef41Sopenharmony_ci
21161cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_dtable_dynamic_add(nghttp3_qpack_encoder *encoder,
21171cb0ef41Sopenharmony_ci                                             uint64_t absidx,
21181cb0ef41Sopenharmony_ci                                             const nghttp3_nv *nv,
21191cb0ef41Sopenharmony_ci                                             uint32_t hash) {
21201cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
21211cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
21221cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
21231cb0ef41Sopenharmony_ci  int rv;
21241cb0ef41Sopenharmony_ci
21251cb0ef41Sopenharmony_ci  rv = nghttp3_rcbuf_new2(&qnv.value, nv->value, nv->valuelen, mem);
21261cb0ef41Sopenharmony_ci  if (rv != 0) {
21271cb0ef41Sopenharmony_ci    return rv;
21281cb0ef41Sopenharmony_ci  }
21291cb0ef41Sopenharmony_ci
21301cb0ef41Sopenharmony_ci  ent = nghttp3_qpack_context_dtable_get(&encoder->ctx, absidx);
21311cb0ef41Sopenharmony_ci
21321cb0ef41Sopenharmony_ci  qnv.name = ent->nv.name;
21331cb0ef41Sopenharmony_ci  qnv.token = ent->nv.token;
21341cb0ef41Sopenharmony_ci  qnv.flags = NGHTTP3_NV_FLAG_NONE;
21351cb0ef41Sopenharmony_ci
21361cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(qnv.name);
21371cb0ef41Sopenharmony_ci
21381cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
21391cb0ef41Sopenharmony_ci                                        &encoder->dtable_map, hash);
21401cb0ef41Sopenharmony_ci
21411cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
21421cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.name);
21431cb0ef41Sopenharmony_ci
21441cb0ef41Sopenharmony_ci  return rv;
21451cb0ef41Sopenharmony_ci}
21461cb0ef41Sopenharmony_ci
21471cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_dtable_duplicate_add(nghttp3_qpack_encoder *encoder,
21481cb0ef41Sopenharmony_ci                                               uint64_t absidx) {
21491cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
21501cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
21511cb0ef41Sopenharmony_ci  int rv;
21521cb0ef41Sopenharmony_ci
21531cb0ef41Sopenharmony_ci  ent = nghttp3_qpack_context_dtable_get(&encoder->ctx, absidx);
21541cb0ef41Sopenharmony_ci
21551cb0ef41Sopenharmony_ci  qnv = ent->nv;
21561cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(qnv.name);
21571cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(qnv.value);
21581cb0ef41Sopenharmony_ci
21591cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
21601cb0ef41Sopenharmony_ci                                        &encoder->dtable_map, ent->hash);
21611cb0ef41Sopenharmony_ci
21621cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.name);
21631cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
21641cb0ef41Sopenharmony_ci
21651cb0ef41Sopenharmony_ci  return rv;
21661cb0ef41Sopenharmony_ci}
21671cb0ef41Sopenharmony_ci
21681cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_dtable_literal_add(nghttp3_qpack_encoder *encoder,
21691cb0ef41Sopenharmony_ci                                             const nghttp3_nv *nv,
21701cb0ef41Sopenharmony_ci                                             int32_t token, uint32_t hash) {
21711cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
21721cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
21731cb0ef41Sopenharmony_ci  int rv;
21741cb0ef41Sopenharmony_ci
21751cb0ef41Sopenharmony_ci  rv = nghttp3_rcbuf_new2(&qnv.name, nv->name, nv->namelen, mem);
21761cb0ef41Sopenharmony_ci  if (rv != 0) {
21771cb0ef41Sopenharmony_ci    return rv;
21781cb0ef41Sopenharmony_ci  }
21791cb0ef41Sopenharmony_ci
21801cb0ef41Sopenharmony_ci  rv = nghttp3_rcbuf_new2(&qnv.value, nv->value, nv->valuelen, mem);
21811cb0ef41Sopenharmony_ci  if (rv != 0) {
21821cb0ef41Sopenharmony_ci    nghttp3_rcbuf_decref(qnv.name);
21831cb0ef41Sopenharmony_ci    return rv;
21841cb0ef41Sopenharmony_ci  }
21851cb0ef41Sopenharmony_ci
21861cb0ef41Sopenharmony_ci  qnv.token = token;
21871cb0ef41Sopenharmony_ci  qnv.flags = NGHTTP3_NV_FLAG_NONE;
21881cb0ef41Sopenharmony_ci
21891cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
21901cb0ef41Sopenharmony_ci                                        &encoder->dtable_map, hash);
21911cb0ef41Sopenharmony_ci
21921cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
21931cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.name);
21941cb0ef41Sopenharmony_ci
21951cb0ef41Sopenharmony_ci  return rv;
21961cb0ef41Sopenharmony_ci}
21971cb0ef41Sopenharmony_ci
21981cb0ef41Sopenharmony_cinghttp3_qpack_entry *
21991cb0ef41Sopenharmony_cinghttp3_qpack_context_dtable_get(nghttp3_qpack_context *ctx, uint64_t absidx) {
22001cb0ef41Sopenharmony_ci  size_t relidx;
22011cb0ef41Sopenharmony_ci
22021cb0ef41Sopenharmony_ci  assert(ctx->next_absidx > absidx);
22031cb0ef41Sopenharmony_ci  assert(ctx->next_absidx - absidx - 1 < nghttp3_ringbuf_len(&ctx->dtable));
22041cb0ef41Sopenharmony_ci
22051cb0ef41Sopenharmony_ci  relidx = (size_t)(ctx->next_absidx - absidx - 1);
22061cb0ef41Sopenharmony_ci
22071cb0ef41Sopenharmony_ci  return *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, relidx);
22081cb0ef41Sopenharmony_ci}
22091cb0ef41Sopenharmony_ci
22101cb0ef41Sopenharmony_cinghttp3_qpack_entry *
22111cb0ef41Sopenharmony_cinghttp3_qpack_context_dtable_top(nghttp3_qpack_context *ctx) {
22121cb0ef41Sopenharmony_ci  assert(nghttp3_ringbuf_len(&ctx->dtable));
22131cb0ef41Sopenharmony_ci  return *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, 0);
22141cb0ef41Sopenharmony_ci}
22151cb0ef41Sopenharmony_ci
22161cb0ef41Sopenharmony_civoid nghttp3_qpack_entry_init(nghttp3_qpack_entry *ent, nghttp3_qpack_nv *qnv,
22171cb0ef41Sopenharmony_ci                              size_t sum, uint64_t absidx, uint32_t hash) {
22181cb0ef41Sopenharmony_ci  ent->nv = *qnv;
22191cb0ef41Sopenharmony_ci  ent->map_next = NULL;
22201cb0ef41Sopenharmony_ci  ent->sum = sum;
22211cb0ef41Sopenharmony_ci  ent->absidx = absidx;
22221cb0ef41Sopenharmony_ci  ent->hash = hash;
22231cb0ef41Sopenharmony_ci
22241cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(ent->nv.name);
22251cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(ent->nv.value);
22261cb0ef41Sopenharmony_ci}
22271cb0ef41Sopenharmony_ci
22281cb0ef41Sopenharmony_civoid nghttp3_qpack_entry_free(nghttp3_qpack_entry *ent) {
22291cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(ent->nv.value);
22301cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(ent->nv.name);
22311cb0ef41Sopenharmony_ci}
22321cb0ef41Sopenharmony_ci
22331cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
22341cb0ef41Sopenharmony_ci                                       nghttp3_qpack_stream *stream) {
22351cb0ef41Sopenharmony_ci  nghttp3_blocked_streams_key bsk = {
22361cb0ef41Sopenharmony_ci      nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
22371cb0ef41Sopenharmony_ci                        nghttp3_qpack_header_block_ref, max_cnts_pe)
22381cb0ef41Sopenharmony_ci          ->max_cnt,
22391cb0ef41Sopenharmony_ci      (uint64_t)stream->stream_id};
22401cb0ef41Sopenharmony_ci
22411cb0ef41Sopenharmony_ci  return nghttp3_ksl_insert(&encoder->blocked_streams, NULL, &bsk, stream);
22421cb0ef41Sopenharmony_ci}
22431cb0ef41Sopenharmony_ci
22441cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
22451cb0ef41Sopenharmony_ci                                          nghttp3_qpack_stream *stream) {
22461cb0ef41Sopenharmony_ci  nghttp3_blocked_streams_key bsk = {
22471cb0ef41Sopenharmony_ci      nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
22481cb0ef41Sopenharmony_ci                        nghttp3_qpack_header_block_ref, max_cnts_pe)
22491cb0ef41Sopenharmony_ci          ->max_cnt,
22501cb0ef41Sopenharmony_ci      (uint64_t)stream->stream_id};
22511cb0ef41Sopenharmony_ci  nghttp3_ksl_it it;
22521cb0ef41Sopenharmony_ci
22531cb0ef41Sopenharmony_ci  /* This is purely debugging purpose only */
22541cb0ef41Sopenharmony_ci  it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
22551cb0ef41Sopenharmony_ci
22561cb0ef41Sopenharmony_ci  assert(!nghttp3_ksl_it_end(&it));
22571cb0ef41Sopenharmony_ci  assert(nghttp3_ksl_it_get(&it) == stream);
22581cb0ef41Sopenharmony_ci
22591cb0ef41Sopenharmony_ci  nghttp3_ksl_remove_hint(&encoder->blocked_streams, NULL, &it, &bsk);
22601cb0ef41Sopenharmony_ci}
22611cb0ef41Sopenharmony_ci
22621cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_unblock(nghttp3_qpack_encoder *encoder,
22631cb0ef41Sopenharmony_ci                                   uint64_t max_cnt) {
22641cb0ef41Sopenharmony_ci  nghttp3_blocked_streams_key bsk = {max_cnt, 0};
22651cb0ef41Sopenharmony_ci  nghttp3_ksl_it it;
22661cb0ef41Sopenharmony_ci
22671cb0ef41Sopenharmony_ci  it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
22681cb0ef41Sopenharmony_ci
22691cb0ef41Sopenharmony_ci  for (; !nghttp3_ksl_it_end(&it);) {
22701cb0ef41Sopenharmony_ci    bsk = *(nghttp3_blocked_streams_key *)nghttp3_ksl_it_key(&it);
22711cb0ef41Sopenharmony_ci    nghttp3_ksl_remove_hint(&encoder->blocked_streams, &it, &it, &bsk);
22721cb0ef41Sopenharmony_ci  }
22731cb0ef41Sopenharmony_ci}
22741cb0ef41Sopenharmony_ci
22751cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_ack_header(nghttp3_qpack_encoder *encoder,
22761cb0ef41Sopenharmony_ci                                     int64_t stream_id) {
22771cb0ef41Sopenharmony_ci  nghttp3_qpack_stream *stream =
22781cb0ef41Sopenharmony_ci      nghttp3_qpack_encoder_find_stream(encoder, stream_id);
22791cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
22801cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref *ref;
22811cb0ef41Sopenharmony_ci
22821cb0ef41Sopenharmony_ci  if (stream == NULL) {
22831cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR;
22841cb0ef41Sopenharmony_ci  }
22851cb0ef41Sopenharmony_ci
22861cb0ef41Sopenharmony_ci  assert(nghttp3_ringbuf_len(&stream->refs));
22871cb0ef41Sopenharmony_ci
22881cb0ef41Sopenharmony_ci  ref =
22891cb0ef41Sopenharmony_ci      *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs, 0);
22901cb0ef41Sopenharmony_ci
22911cb0ef41Sopenharmony_ci  DEBUGF("qpack::encoder: Header acknowledgement stream=%ld ricnt=%" PRIu64
22921cb0ef41Sopenharmony_ci         " krcnt=%" PRIu64 "\n",
22931cb0ef41Sopenharmony_ci         stream_id, ref->max_cnt, encoder->krcnt);
22941cb0ef41Sopenharmony_ci
22951cb0ef41Sopenharmony_ci  if (encoder->krcnt < ref->max_cnt) {
22961cb0ef41Sopenharmony_ci    encoder->krcnt = ref->max_cnt;
22971cb0ef41Sopenharmony_ci
22981cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder_unblock(encoder, ref->max_cnt);
22991cb0ef41Sopenharmony_ci  }
23001cb0ef41Sopenharmony_ci
23011cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_pop_ref(stream);
23021cb0ef41Sopenharmony_ci
23031cb0ef41Sopenharmony_ci  assert(ref->min_cnts_pe.index != NGHTTP3_PQ_BAD_INDEX);
23041cb0ef41Sopenharmony_ci
23051cb0ef41Sopenharmony_ci  nghttp3_pq_remove(&encoder->min_cnts, &ref->min_cnts_pe);
23061cb0ef41Sopenharmony_ci
23071cb0ef41Sopenharmony_ci  nghttp3_qpack_header_block_ref_del(ref, mem);
23081cb0ef41Sopenharmony_ci
23091cb0ef41Sopenharmony_ci  if (nghttp3_ringbuf_len(&stream->refs)) {
23101cb0ef41Sopenharmony_ci    return 0;
23111cb0ef41Sopenharmony_ci  }
23121cb0ef41Sopenharmony_ci
23131cb0ef41Sopenharmony_ci  qpack_encoder_remove_stream(encoder, stream);
23141cb0ef41Sopenharmony_ci
23151cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_del(stream, mem);
23161cb0ef41Sopenharmony_ci
23171cb0ef41Sopenharmony_ci  return 0;
23181cb0ef41Sopenharmony_ci}
23191cb0ef41Sopenharmony_ci
23201cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_add_icnt(nghttp3_qpack_encoder *encoder, uint64_t n) {
23211cb0ef41Sopenharmony_ci  if (n == 0 || encoder->ctx.next_absidx - encoder->krcnt < n) {
23221cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR;
23231cb0ef41Sopenharmony_ci  }
23241cb0ef41Sopenharmony_ci  encoder->krcnt += n;
23251cb0ef41Sopenharmony_ci
23261cb0ef41Sopenharmony_ci  nghttp3_qpack_encoder_unblock(encoder, encoder->krcnt);
23271cb0ef41Sopenharmony_ci
23281cb0ef41Sopenharmony_ci  return 0;
23291cb0ef41Sopenharmony_ci}
23301cb0ef41Sopenharmony_ci
23311cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_ack_everything(nghttp3_qpack_encoder *encoder) {
23321cb0ef41Sopenharmony_ci  encoder->krcnt = encoder->ctx.next_absidx;
23331cb0ef41Sopenharmony_ci
23341cb0ef41Sopenharmony_ci  nghttp3_ksl_clear(&encoder->blocked_streams);
23351cb0ef41Sopenharmony_ci  nghttp3_pq_clear(&encoder->min_cnts);
23361cb0ef41Sopenharmony_ci  nghttp3_map_each_free(&encoder->streams, map_stream_free,
23371cb0ef41Sopenharmony_ci                        (void *)encoder->ctx.mem);
23381cb0ef41Sopenharmony_ci  nghttp3_map_clear(&encoder->streams);
23391cb0ef41Sopenharmony_ci}
23401cb0ef41Sopenharmony_ci
23411cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_cancel_stream(nghttp3_qpack_encoder *encoder,
23421cb0ef41Sopenharmony_ci                                         int64_t stream_id) {
23431cb0ef41Sopenharmony_ci  nghttp3_qpack_stream *stream =
23441cb0ef41Sopenharmony_ci      nghttp3_qpack_encoder_find_stream(encoder, stream_id);
23451cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = encoder->ctx.mem;
23461cb0ef41Sopenharmony_ci
23471cb0ef41Sopenharmony_ci  if (stream == NULL) {
23481cb0ef41Sopenharmony_ci    return;
23491cb0ef41Sopenharmony_ci  }
23501cb0ef41Sopenharmony_ci
23511cb0ef41Sopenharmony_ci  if (nghttp3_qpack_encoder_stream_is_blocked(encoder, stream)) {
23521cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder_unblock_stream(encoder, stream);
23531cb0ef41Sopenharmony_ci  }
23541cb0ef41Sopenharmony_ci
23551cb0ef41Sopenharmony_ci  qpack_encoder_remove_stream(encoder, stream);
23561cb0ef41Sopenharmony_ci
23571cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_del(stream, mem);
23581cb0ef41Sopenharmony_ci}
23591cb0ef41Sopenharmony_ci
23601cb0ef41Sopenharmony_cisize_t
23611cb0ef41Sopenharmony_cinghttp3_qpack_encoder_get_num_blocked_streams(nghttp3_qpack_encoder *encoder) {
23621cb0ef41Sopenharmony_ci  return nghttp3_ksl_len(&encoder->blocked_streams);
23631cb0ef41Sopenharmony_ci}
23641cb0ef41Sopenharmony_ci
23651cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_write_field_section_prefix(
23661cb0ef41Sopenharmony_ci    nghttp3_qpack_encoder *encoder, nghttp3_buf *pbuf, uint64_t ricnt,
23671cb0ef41Sopenharmony_ci    uint64_t base) {
23681cb0ef41Sopenharmony_ci  size_t max_ents =
23691cb0ef41Sopenharmony_ci      encoder->ctx.hard_max_dtable_capacity / NGHTTP3_QPACK_ENTRY_OVERHEAD;
23701cb0ef41Sopenharmony_ci  uint64_t encricnt = ricnt == 0 ? 0 : (ricnt % (2 * max_ents)) + 1;
23711cb0ef41Sopenharmony_ci  int sign = base < ricnt;
23721cb0ef41Sopenharmony_ci  uint64_t delta_base = sign ? ricnt - base - 1 : base - ricnt;
23731cb0ef41Sopenharmony_ci  size_t len = nghttp3_qpack_put_varint_len(encricnt, 8) +
23741cb0ef41Sopenharmony_ci               nghttp3_qpack_put_varint_len(delta_base, 7);
23751cb0ef41Sopenharmony_ci  uint8_t *p;
23761cb0ef41Sopenharmony_ci  int rv;
23771cb0ef41Sopenharmony_ci
23781cb0ef41Sopenharmony_ci  DEBUGF("qpack::encode: ricnt=%" PRIu64 " base=%" PRIu64 " icnt=%" PRIu64 "\n",
23791cb0ef41Sopenharmony_ci         ricnt, base, encoder->ctx.next_absidx);
23801cb0ef41Sopenharmony_ci
23811cb0ef41Sopenharmony_ci  rv = reserve_buf(pbuf, len, encoder->ctx.mem);
23821cb0ef41Sopenharmony_ci  if (rv != 0) {
23831cb0ef41Sopenharmony_ci    return rv;
23841cb0ef41Sopenharmony_ci  }
23851cb0ef41Sopenharmony_ci
23861cb0ef41Sopenharmony_ci  p = pbuf->last;
23871cb0ef41Sopenharmony_ci
23881cb0ef41Sopenharmony_ci  p = nghttp3_qpack_put_varint(p, encricnt, 8);
23891cb0ef41Sopenharmony_ci  if (sign) {
23901cb0ef41Sopenharmony_ci    *p = 0x80;
23911cb0ef41Sopenharmony_ci  } else {
23921cb0ef41Sopenharmony_ci    *p = 0;
23931cb0ef41Sopenharmony_ci  }
23941cb0ef41Sopenharmony_ci  p = nghttp3_qpack_put_varint(p, delta_base, 7);
23951cb0ef41Sopenharmony_ci
23961cb0ef41Sopenharmony_ci  assert((size_t)(p - pbuf->last) == len);
23971cb0ef41Sopenharmony_ci
23981cb0ef41Sopenharmony_ci  pbuf->last = p;
23991cb0ef41Sopenharmony_ci
24001cb0ef41Sopenharmony_ci  return 0;
24011cb0ef41Sopenharmony_ci}
24021cb0ef41Sopenharmony_ci
24031cb0ef41Sopenharmony_ci/*
24041cb0ef41Sopenharmony_ci * qpack_read_varint reads |rstate->prefix| prefixed integer stored
24051cb0ef41Sopenharmony_ci * from |begin|.  The |end| represents the 1 beyond the last of the
24061cb0ef41Sopenharmony_ci * valid contiguous memory region from |begin|.  The decoded integer
24071cb0ef41Sopenharmony_ci * must be less than or equal to NGHTTP3_QPACK_INT_MAX.
24081cb0ef41Sopenharmony_ci *
24091cb0ef41Sopenharmony_ci * If the |rstate->left| is nonzero, it is used as an initial value,
24101cb0ef41Sopenharmony_ci * and this function assumes the |begin| starts with intermediate
24111cb0ef41Sopenharmony_ci * data.  |rstate->shift| is used as initial integer shift.
24121cb0ef41Sopenharmony_ci *
24131cb0ef41Sopenharmony_ci * If an entire integer is decoded successfully, the |*fin| is set to
24141cb0ef41Sopenharmony_ci * nonzero.
24151cb0ef41Sopenharmony_ci *
24161cb0ef41Sopenharmony_ci * This function stores the decoded integer in |rstate->left| if it
24171cb0ef41Sopenharmony_ci * succeeds, including partial decoding (in this case, number of shift
24181cb0ef41Sopenharmony_ci * to make in the next call will be stored in |rstate->shift|) and
24191cb0ef41Sopenharmony_ci * returns number of bytes processed, or returns negative error code
24201cb0ef41Sopenharmony_ci * NGHTTP3_ERR_QPACK_FATAL, indicating decoding error.
24211cb0ef41Sopenharmony_ci */
24221cb0ef41Sopenharmony_cistatic nghttp3_ssize qpack_read_varint(int *fin,
24231cb0ef41Sopenharmony_ci                                       nghttp3_qpack_read_state *rstate,
24241cb0ef41Sopenharmony_ci                                       const uint8_t *begin,
24251cb0ef41Sopenharmony_ci                                       const uint8_t *end) {
24261cb0ef41Sopenharmony_ci  uint64_t k = (uint8_t)((1 << rstate->prefix) - 1);
24271cb0ef41Sopenharmony_ci  uint64_t n = rstate->left;
24281cb0ef41Sopenharmony_ci  uint64_t add;
24291cb0ef41Sopenharmony_ci  const uint8_t *p = begin;
24301cb0ef41Sopenharmony_ci  size_t shift = rstate->shift;
24311cb0ef41Sopenharmony_ci
24321cb0ef41Sopenharmony_ci  rstate->shift = 0;
24331cb0ef41Sopenharmony_ci  *fin = 0;
24341cb0ef41Sopenharmony_ci
24351cb0ef41Sopenharmony_ci  if (n == 0) {
24361cb0ef41Sopenharmony_ci    if (((*p) & k) != k) {
24371cb0ef41Sopenharmony_ci      rstate->left = (*p) & k;
24381cb0ef41Sopenharmony_ci      *fin = 1;
24391cb0ef41Sopenharmony_ci      return 1;
24401cb0ef41Sopenharmony_ci    }
24411cb0ef41Sopenharmony_ci
24421cb0ef41Sopenharmony_ci    n = k;
24431cb0ef41Sopenharmony_ci
24441cb0ef41Sopenharmony_ci    if (++p == end) {
24451cb0ef41Sopenharmony_ci      rstate->left = n;
24461cb0ef41Sopenharmony_ci      return (nghttp3_ssize)(p - begin);
24471cb0ef41Sopenharmony_ci    }
24481cb0ef41Sopenharmony_ci  }
24491cb0ef41Sopenharmony_ci
24501cb0ef41Sopenharmony_ci  for (; p != end; ++p, shift += 7) {
24511cb0ef41Sopenharmony_ci    add = (*p) & 0x7f;
24521cb0ef41Sopenharmony_ci
24531cb0ef41Sopenharmony_ci    if (shift > 62) {
24541cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_FATAL;
24551cb0ef41Sopenharmony_ci    }
24561cb0ef41Sopenharmony_ci
24571cb0ef41Sopenharmony_ci    if ((NGHTTP3_QPACK_INT_MAX >> shift) < add) {
24581cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_FATAL;
24591cb0ef41Sopenharmony_ci    }
24601cb0ef41Sopenharmony_ci
24611cb0ef41Sopenharmony_ci    add <<= shift;
24621cb0ef41Sopenharmony_ci
24631cb0ef41Sopenharmony_ci    if (NGHTTP3_QPACK_INT_MAX - add < n) {
24641cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_FATAL;
24651cb0ef41Sopenharmony_ci    }
24661cb0ef41Sopenharmony_ci
24671cb0ef41Sopenharmony_ci    n += add;
24681cb0ef41Sopenharmony_ci
24691cb0ef41Sopenharmony_ci    if (((*p) & (1 << 7)) == 0) {
24701cb0ef41Sopenharmony_ci      break;
24711cb0ef41Sopenharmony_ci    }
24721cb0ef41Sopenharmony_ci  }
24731cb0ef41Sopenharmony_ci
24741cb0ef41Sopenharmony_ci  rstate->shift = shift;
24751cb0ef41Sopenharmony_ci
24761cb0ef41Sopenharmony_ci  if (p == end) {
24771cb0ef41Sopenharmony_ci    rstate->left = n;
24781cb0ef41Sopenharmony_ci    return (nghttp3_ssize)(p - begin);
24791cb0ef41Sopenharmony_ci  }
24801cb0ef41Sopenharmony_ci
24811cb0ef41Sopenharmony_ci  rstate->left = n;
24821cb0ef41Sopenharmony_ci  *fin = 1;
24831cb0ef41Sopenharmony_ci  return (nghttp3_ssize)(p + 1 - begin);
24841cb0ef41Sopenharmony_ci}
24851cb0ef41Sopenharmony_ci
24861cb0ef41Sopenharmony_cinghttp3_ssize nghttp3_qpack_encoder_read_decoder(nghttp3_qpack_encoder *encoder,
24871cb0ef41Sopenharmony_ci                                                 const uint8_t *src,
24881cb0ef41Sopenharmony_ci                                                 size_t srclen) {
24891cb0ef41Sopenharmony_ci  const uint8_t *p = src, *end;
24901cb0ef41Sopenharmony_ci  int rv;
24911cb0ef41Sopenharmony_ci  nghttp3_ssize nread;
24921cb0ef41Sopenharmony_ci  int rfin;
24931cb0ef41Sopenharmony_ci
24941cb0ef41Sopenharmony_ci  if (encoder->ctx.bad) {
24951cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
24961cb0ef41Sopenharmony_ci  }
24971cb0ef41Sopenharmony_ci
24981cb0ef41Sopenharmony_ci  if (srclen == 0) {
24991cb0ef41Sopenharmony_ci    return 0;
25001cb0ef41Sopenharmony_ci  }
25011cb0ef41Sopenharmony_ci
25021cb0ef41Sopenharmony_ci  end = src + srclen;
25031cb0ef41Sopenharmony_ci
25041cb0ef41Sopenharmony_ci  for (; p != end;) {
25051cb0ef41Sopenharmony_ci    switch (encoder->state) {
25061cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_DS_STATE_OPCODE:
25071cb0ef41Sopenharmony_ci      if ((*p) & 0x80) {
25081cb0ef41Sopenharmony_ci        DEBUGF("qpack::encode: OPCODE_SECTION_ACK\n");
25091cb0ef41Sopenharmony_ci        encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK;
25101cb0ef41Sopenharmony_ci        encoder->rstate.prefix = 7;
25111cb0ef41Sopenharmony_ci      } else if ((*p) & 0x40) {
25121cb0ef41Sopenharmony_ci        DEBUGF("qpack::encode: OPCODE_STREAM_CANCEL\n");
25131cb0ef41Sopenharmony_ci        encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_STREAM_CANCEL;
25141cb0ef41Sopenharmony_ci        encoder->rstate.prefix = 6;
25151cb0ef41Sopenharmony_ci      } else {
25161cb0ef41Sopenharmony_ci        DEBUGF("qpack::encode: OPCODE_ICNT_INCREMENT\n");
25171cb0ef41Sopenharmony_ci        encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT;
25181cb0ef41Sopenharmony_ci        encoder->rstate.prefix = 6;
25191cb0ef41Sopenharmony_ci      }
25201cb0ef41Sopenharmony_ci      encoder->state = NGHTTP3_QPACK_DS_STATE_READ_NUMBER;
25211cb0ef41Sopenharmony_ci      /* fall through */
25221cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_DS_STATE_READ_NUMBER:
25231cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &encoder->rstate, p, end);
25241cb0ef41Sopenharmony_ci      if (nread < 0) {
25251cb0ef41Sopenharmony_ci        assert(nread == NGHTTP3_ERR_QPACK_FATAL);
25261cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR;
25271cb0ef41Sopenharmony_ci        goto fail;
25281cb0ef41Sopenharmony_ci      }
25291cb0ef41Sopenharmony_ci
25301cb0ef41Sopenharmony_ci      p += nread;
25311cb0ef41Sopenharmony_ci
25321cb0ef41Sopenharmony_ci      if (!rfin) {
25331cb0ef41Sopenharmony_ci        return p - src;
25341cb0ef41Sopenharmony_ci      }
25351cb0ef41Sopenharmony_ci
25361cb0ef41Sopenharmony_ci      switch (encoder->opcode) {
25371cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT:
25381cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_encoder_add_icnt(encoder, encoder->rstate.left);
25391cb0ef41Sopenharmony_ci        if (rv != 0) {
25401cb0ef41Sopenharmony_ci          goto fail;
25411cb0ef41Sopenharmony_ci        }
25421cb0ef41Sopenharmony_ci        break;
25431cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK:
25441cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_encoder_ack_header(encoder,
25451cb0ef41Sopenharmony_ci                                              (int64_t)encoder->rstate.left);
25461cb0ef41Sopenharmony_ci        if (rv != 0) {
25471cb0ef41Sopenharmony_ci          goto fail;
25481cb0ef41Sopenharmony_ci        }
25491cb0ef41Sopenharmony_ci        break;
25501cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_DS_OPCODE_STREAM_CANCEL:
25511cb0ef41Sopenharmony_ci        nghttp3_qpack_encoder_cancel_stream(encoder,
25521cb0ef41Sopenharmony_ci                                            (int64_t)encoder->rstate.left);
25531cb0ef41Sopenharmony_ci        break;
25541cb0ef41Sopenharmony_ci      default:
25551cb0ef41Sopenharmony_ci        /* unreachable */
25561cb0ef41Sopenharmony_ci        assert(0);
25571cb0ef41Sopenharmony_ci        break;
25581cb0ef41Sopenharmony_ci      }
25591cb0ef41Sopenharmony_ci
25601cb0ef41Sopenharmony_ci      encoder->state = NGHTTP3_QPACK_DS_STATE_OPCODE;
25611cb0ef41Sopenharmony_ci      nghttp3_qpack_read_state_reset(&encoder->rstate);
25621cb0ef41Sopenharmony_ci      break;
25631cb0ef41Sopenharmony_ci    default:
25641cb0ef41Sopenharmony_ci      /* unreachable */
25651cb0ef41Sopenharmony_ci      assert(0);
25661cb0ef41Sopenharmony_ci      break;
25671cb0ef41Sopenharmony_ci    }
25681cb0ef41Sopenharmony_ci  }
25691cb0ef41Sopenharmony_ci
25701cb0ef41Sopenharmony_ci  return p - src;
25711cb0ef41Sopenharmony_ci
25721cb0ef41Sopenharmony_cifail:
25731cb0ef41Sopenharmony_ci  encoder->ctx.bad = 1;
25741cb0ef41Sopenharmony_ci  return rv;
25751cb0ef41Sopenharmony_ci}
25761cb0ef41Sopenharmony_ci
25771cb0ef41Sopenharmony_cisize_t nghttp3_qpack_put_varint_len(uint64_t n, size_t prefix) {
25781cb0ef41Sopenharmony_ci  size_t k = (size_t)((1 << prefix) - 1);
25791cb0ef41Sopenharmony_ci  size_t len = 0;
25801cb0ef41Sopenharmony_ci
25811cb0ef41Sopenharmony_ci  if (n < k) {
25821cb0ef41Sopenharmony_ci    return 1;
25831cb0ef41Sopenharmony_ci  }
25841cb0ef41Sopenharmony_ci
25851cb0ef41Sopenharmony_ci  n -= k;
25861cb0ef41Sopenharmony_ci  ++len;
25871cb0ef41Sopenharmony_ci
25881cb0ef41Sopenharmony_ci  for (; n >= 128; n >>= 7, ++len)
25891cb0ef41Sopenharmony_ci    ;
25901cb0ef41Sopenharmony_ci
25911cb0ef41Sopenharmony_ci  return len + 1;
25921cb0ef41Sopenharmony_ci}
25931cb0ef41Sopenharmony_ci
25941cb0ef41Sopenharmony_ciuint8_t *nghttp3_qpack_put_varint(uint8_t *buf, uint64_t n, size_t prefix) {
25951cb0ef41Sopenharmony_ci  size_t k = (size_t)((1 << prefix) - 1);
25961cb0ef41Sopenharmony_ci
25971cb0ef41Sopenharmony_ci  *buf = (uint8_t)(*buf & ~k);
25981cb0ef41Sopenharmony_ci
25991cb0ef41Sopenharmony_ci  if (n < k) {
26001cb0ef41Sopenharmony_ci    *buf = (uint8_t)(*buf | n);
26011cb0ef41Sopenharmony_ci    return buf + 1;
26021cb0ef41Sopenharmony_ci  }
26031cb0ef41Sopenharmony_ci
26041cb0ef41Sopenharmony_ci  *buf = (uint8_t)(*buf | k);
26051cb0ef41Sopenharmony_ci  ++buf;
26061cb0ef41Sopenharmony_ci
26071cb0ef41Sopenharmony_ci  n -= k;
26081cb0ef41Sopenharmony_ci
26091cb0ef41Sopenharmony_ci  for (; n >= 128; n >>= 7) {
26101cb0ef41Sopenharmony_ci    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
26111cb0ef41Sopenharmony_ci  }
26121cb0ef41Sopenharmony_ci
26131cb0ef41Sopenharmony_ci  *buf++ = (uint8_t)n;
26141cb0ef41Sopenharmony_ci
26151cb0ef41Sopenharmony_ci  return buf;
26161cb0ef41Sopenharmony_ci}
26171cb0ef41Sopenharmony_ci
26181cb0ef41Sopenharmony_civoid nghttp3_qpack_read_state_free(nghttp3_qpack_read_state *rstate) {
26191cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(rstate->value);
26201cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(rstate->name);
26211cb0ef41Sopenharmony_ci}
26221cb0ef41Sopenharmony_ci
26231cb0ef41Sopenharmony_civoid nghttp3_qpack_read_state_reset(nghttp3_qpack_read_state *rstate) {
26241cb0ef41Sopenharmony_ci  rstate->name = NULL;
26251cb0ef41Sopenharmony_ci  rstate->value = NULL;
26261cb0ef41Sopenharmony_ci  nghttp3_buf_init(&rstate->namebuf);
26271cb0ef41Sopenharmony_ci  nghttp3_buf_init(&rstate->valuebuf);
26281cb0ef41Sopenharmony_ci  rstate->left = 0;
26291cb0ef41Sopenharmony_ci  rstate->prefix = 0;
26301cb0ef41Sopenharmony_ci  rstate->shift = 0;
26311cb0ef41Sopenharmony_ci  rstate->absidx = 0;
26321cb0ef41Sopenharmony_ci  rstate->never = 0;
26331cb0ef41Sopenharmony_ci  rstate->dynamic = 0;
26341cb0ef41Sopenharmony_ci  rstate->huffman_encoded = 0;
26351cb0ef41Sopenharmony_ci}
26361cb0ef41Sopenharmony_ci
26371cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
26381cb0ef41Sopenharmony_ci                               size_t hard_max_dtable_capacity,
26391cb0ef41Sopenharmony_ci                               size_t max_blocked_streams,
26401cb0ef41Sopenharmony_ci                               const nghttp3_mem *mem) {
26411cb0ef41Sopenharmony_ci  int rv;
26421cb0ef41Sopenharmony_ci
26431cb0ef41Sopenharmony_ci  rv = qpack_context_init(&decoder->ctx, hard_max_dtable_capacity,
26441cb0ef41Sopenharmony_ci                          max_blocked_streams, mem);
26451cb0ef41Sopenharmony_ci  if (rv != 0) {
26461cb0ef41Sopenharmony_ci    return rv;
26471cb0ef41Sopenharmony_ci  }
26481cb0ef41Sopenharmony_ci
26491cb0ef41Sopenharmony_ci  decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
26501cb0ef41Sopenharmony_ci  decoder->opcode = 0;
26511cb0ef41Sopenharmony_ci  decoder->written_icnt = 0;
26521cb0ef41Sopenharmony_ci  decoder->max_concurrent_streams = 0;
26531cb0ef41Sopenharmony_ci
26541cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state_reset(&decoder->rstate);
26551cb0ef41Sopenharmony_ci  nghttp3_buf_init(&decoder->dbuf);
26561cb0ef41Sopenharmony_ci
26571cb0ef41Sopenharmony_ci  return 0;
26581cb0ef41Sopenharmony_ci}
26591cb0ef41Sopenharmony_ci
26601cb0ef41Sopenharmony_civoid nghttp3_qpack_decoder_free(nghttp3_qpack_decoder *decoder) {
26611cb0ef41Sopenharmony_ci  nghttp3_buf_free(&decoder->dbuf, decoder->ctx.mem);
26621cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state_free(&decoder->rstate);
26631cb0ef41Sopenharmony_ci  qpack_context_free(&decoder->ctx);
26641cb0ef41Sopenharmony_ci}
26651cb0ef41Sopenharmony_ci
26661cb0ef41Sopenharmony_ci/*
26671cb0ef41Sopenharmony_ci * qpack_read_huffman_string decodes huffman string in buffer [begin,
26681cb0ef41Sopenharmony_ci * end) and writes the decoded string to |dest|.  This function
26691cb0ef41Sopenharmony_ci * assumes the buffer pointed by |dest| has enough space.
26701cb0ef41Sopenharmony_ci *
26711cb0ef41Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
26721cb0ef41Sopenharmony_ci * negative error codes:
26731cb0ef41Sopenharmony_ci *
26741cb0ef41Sopenharmony_ci * NGHTTP3_ERR_QPACK_FATAL
26751cb0ef41Sopenharmony_ci *     Could not decode huffman string.
26761cb0ef41Sopenharmony_ci */
26771cb0ef41Sopenharmony_cistatic nghttp3_ssize qpack_read_huffman_string(nghttp3_qpack_read_state *rstate,
26781cb0ef41Sopenharmony_ci                                               nghttp3_buf *dest,
26791cb0ef41Sopenharmony_ci                                               const uint8_t *begin,
26801cb0ef41Sopenharmony_ci                                               const uint8_t *end) {
26811cb0ef41Sopenharmony_ci  nghttp3_ssize nwrite;
26821cb0ef41Sopenharmony_ci  size_t len = (size_t)(end - begin);
26831cb0ef41Sopenharmony_ci  int fin = 0;
26841cb0ef41Sopenharmony_ci
26851cb0ef41Sopenharmony_ci  if (len >= rstate->left) {
26861cb0ef41Sopenharmony_ci    len = (size_t)rstate->left;
26871cb0ef41Sopenharmony_ci    fin = 1;
26881cb0ef41Sopenharmony_ci  }
26891cb0ef41Sopenharmony_ci
26901cb0ef41Sopenharmony_ci  nwrite = nghttp3_qpack_huffman_decode(&rstate->huffman_ctx, dest->last, begin,
26911cb0ef41Sopenharmony_ci                                        len, fin);
26921cb0ef41Sopenharmony_ci  if (nwrite < 0) {
26931cb0ef41Sopenharmony_ci    return nwrite;
26941cb0ef41Sopenharmony_ci  }
26951cb0ef41Sopenharmony_ci
26961cb0ef41Sopenharmony_ci  if (nghttp3_qpack_huffman_decode_failure_state(&rstate->huffman_ctx)) {
26971cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
26981cb0ef41Sopenharmony_ci  }
26991cb0ef41Sopenharmony_ci
27001cb0ef41Sopenharmony_ci  dest->last += nwrite;
27011cb0ef41Sopenharmony_ci  rstate->left -= len;
27021cb0ef41Sopenharmony_ci  return (nghttp3_ssize)len;
27031cb0ef41Sopenharmony_ci}
27041cb0ef41Sopenharmony_ci
27051cb0ef41Sopenharmony_cistatic nghttp3_ssize qpack_read_string(nghttp3_qpack_read_state *rstate,
27061cb0ef41Sopenharmony_ci                                       nghttp3_buf *dest, const uint8_t *begin,
27071cb0ef41Sopenharmony_ci                                       const uint8_t *end) {
27081cb0ef41Sopenharmony_ci  size_t len = (size_t)(end - begin);
27091cb0ef41Sopenharmony_ci  size_t n = (size_t)nghttp3_min((uint64_t)len, rstate->left);
27101cb0ef41Sopenharmony_ci
27111cb0ef41Sopenharmony_ci  dest->last = nghttp3_cpymem(dest->last, begin, n);
27121cb0ef41Sopenharmony_ci
27131cb0ef41Sopenharmony_ci  rstate->left -= n;
27141cb0ef41Sopenharmony_ci  return (nghttp3_ssize)n;
27151cb0ef41Sopenharmony_ci}
27161cb0ef41Sopenharmony_ci
27171cb0ef41Sopenharmony_ci/*
27181cb0ef41Sopenharmony_ci * qpack_decoder_validate_index checks rstate->absidx is acceptable.
27191cb0ef41Sopenharmony_ci *
27201cb0ef41Sopenharmony_ci * It returns 0 if it succeeds, or one of the following negative error
27211cb0ef41Sopenharmony_ci * codes:
27221cb0ef41Sopenharmony_ci *
27231cb0ef41Sopenharmony_ci * NGHTTP3_ERR_QPACK_FATAL
27241cb0ef41Sopenharmony_ci *     rstate->absidx is invalid.
27251cb0ef41Sopenharmony_ci */
27261cb0ef41Sopenharmony_cistatic int qpack_decoder_validate_index(nghttp3_qpack_decoder *decoder,
27271cb0ef41Sopenharmony_ci                                        nghttp3_qpack_read_state *rstate) {
27281cb0ef41Sopenharmony_ci  if (rstate->dynamic) {
27291cb0ef41Sopenharmony_ci    return rstate->absidx < decoder->ctx.next_absidx &&
27301cb0ef41Sopenharmony_ci                   decoder->ctx.next_absidx - rstate->absidx - 1 <
27311cb0ef41Sopenharmony_ci                       nghttp3_ringbuf_len(&decoder->ctx.dtable)
27321cb0ef41Sopenharmony_ci               ? 0
27331cb0ef41Sopenharmony_ci               : NGHTTP3_ERR_QPACK_FATAL;
27341cb0ef41Sopenharmony_ci  }
27351cb0ef41Sopenharmony_ci  return rstate->absidx < nghttp3_arraylen(stable) ? 0
27361cb0ef41Sopenharmony_ci                                                   : NGHTTP3_ERR_QPACK_FATAL;
27371cb0ef41Sopenharmony_ci}
27381cb0ef41Sopenharmony_ci
27391cb0ef41Sopenharmony_cistatic void qpack_read_state_check_huffman(nghttp3_qpack_read_state *rstate,
27401cb0ef41Sopenharmony_ci                                           const uint8_t b) {
27411cb0ef41Sopenharmony_ci  rstate->huffman_encoded = (b & (1 << rstate->prefix)) != 0;
27421cb0ef41Sopenharmony_ci}
27431cb0ef41Sopenharmony_ci
27441cb0ef41Sopenharmony_cistatic void qpack_read_state_terminate_name(nghttp3_qpack_read_state *rstate) {
27451cb0ef41Sopenharmony_ci  *rstate->namebuf.last = '\0';
27461cb0ef41Sopenharmony_ci  rstate->name->len = nghttp3_buf_len(&rstate->namebuf);
27471cb0ef41Sopenharmony_ci}
27481cb0ef41Sopenharmony_ci
27491cb0ef41Sopenharmony_cistatic void qpack_read_state_terminate_value(nghttp3_qpack_read_state *rstate) {
27501cb0ef41Sopenharmony_ci  *rstate->valuebuf.last = '\0';
27511cb0ef41Sopenharmony_ci  rstate->value->len = nghttp3_buf_len(&rstate->valuebuf);
27521cb0ef41Sopenharmony_ci}
27531cb0ef41Sopenharmony_ci
27541cb0ef41Sopenharmony_cinghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder,
27551cb0ef41Sopenharmony_ci                                                 const uint8_t *src,
27561cb0ef41Sopenharmony_ci                                                 size_t srclen) {
27571cb0ef41Sopenharmony_ci  const uint8_t *p = src, *end;
27581cb0ef41Sopenharmony_ci  int rv;
27591cb0ef41Sopenharmony_ci  int busy = 0;
27601cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = decoder->ctx.mem;
27611cb0ef41Sopenharmony_ci  nghttp3_ssize nread;
27621cb0ef41Sopenharmony_ci  int rfin;
27631cb0ef41Sopenharmony_ci
27641cb0ef41Sopenharmony_ci  if (decoder->ctx.bad) {
27651cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
27661cb0ef41Sopenharmony_ci  }
27671cb0ef41Sopenharmony_ci
27681cb0ef41Sopenharmony_ci  if (srclen == 0) {
27691cb0ef41Sopenharmony_ci    return 0;
27701cb0ef41Sopenharmony_ci  }
27711cb0ef41Sopenharmony_ci
27721cb0ef41Sopenharmony_ci  end = src + srclen;
27731cb0ef41Sopenharmony_ci
27741cb0ef41Sopenharmony_ci  for (; p != end || busy;) {
27751cb0ef41Sopenharmony_ci    busy = 0;
27761cb0ef41Sopenharmony_ci    switch (decoder->state) {
27771cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_OPCODE:
27781cb0ef41Sopenharmony_ci      if ((*p) & 0x80) {
27791cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_INSERT_INDEXED\n");
27801cb0ef41Sopenharmony_ci        decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED;
27811cb0ef41Sopenharmony_ci        decoder->rstate.dynamic = !((*p) & 0x40);
27821cb0ef41Sopenharmony_ci        decoder->rstate.prefix = 6;
27831cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX;
27841cb0ef41Sopenharmony_ci      } else if ((*p) & 0x40) {
27851cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_INSERT\n");
27861cb0ef41Sopenharmony_ci        decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT;
27871cb0ef41Sopenharmony_ci        decoder->rstate.dynamic = 0;
27881cb0ef41Sopenharmony_ci        decoder->rstate.prefix = 5;
27891cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN;
27901cb0ef41Sopenharmony_ci      } else if ((*p) & 0x20) {
27911cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_SET_DTABLE_TABLE_CAP\n");
27921cb0ef41Sopenharmony_ci        decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP;
27931cb0ef41Sopenharmony_ci        decoder->rstate.prefix = 5;
27941cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX;
27951cb0ef41Sopenharmony_ci      } else if (!((*p) & 0x20)) {
27961cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_DUPLICATE\n");
27971cb0ef41Sopenharmony_ci        decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_DUPLICATE;
27981cb0ef41Sopenharmony_ci        decoder->rstate.dynamic = 1;
27991cb0ef41Sopenharmony_ci        decoder->rstate.prefix = 5;
28001cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX;
28011cb0ef41Sopenharmony_ci      } else {
28021cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: unknown opcode %02x\n", *p);
28031cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
28041cb0ef41Sopenharmony_ci        goto fail;
28051cb0ef41Sopenharmony_ci      }
28061cb0ef41Sopenharmony_ci      break;
28071cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_INDEX:
28081cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &decoder->rstate, p, end);
28091cb0ef41Sopenharmony_ci      if (nread < 0) {
28101cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
28111cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
28121cb0ef41Sopenharmony_ci        goto fail;
28131cb0ef41Sopenharmony_ci      }
28141cb0ef41Sopenharmony_ci
28151cb0ef41Sopenharmony_ci      p += nread;
28161cb0ef41Sopenharmony_ci
28171cb0ef41Sopenharmony_ci      if (!rfin) {
28181cb0ef41Sopenharmony_ci        return p - src;
28191cb0ef41Sopenharmony_ci      }
28201cb0ef41Sopenharmony_ci
28211cb0ef41Sopenharmony_ci      if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP) {
28221cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: Set dtable capacity to %" PRIu64 "\n",
28231cb0ef41Sopenharmony_ci               decoder->rstate.left);
28241cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_set_max_dtable_capacity(
28251cb0ef41Sopenharmony_ci            decoder, (size_t)decoder->rstate.left);
28261cb0ef41Sopenharmony_ci        if (rv != 0) {
28271cb0ef41Sopenharmony_ci          rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
28281cb0ef41Sopenharmony_ci          goto fail;
28291cb0ef41Sopenharmony_ci        }
28301cb0ef41Sopenharmony_ci
28311cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
28321cb0ef41Sopenharmony_ci        nghttp3_qpack_read_state_reset(&decoder->rstate);
28331cb0ef41Sopenharmony_ci        break;
28341cb0ef41Sopenharmony_ci      }
28351cb0ef41Sopenharmony_ci
28361cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_decoder_rel2abs(decoder, &decoder->rstate);
28371cb0ef41Sopenharmony_ci      if (rv < 0) {
28381cb0ef41Sopenharmony_ci        goto fail;
28391cb0ef41Sopenharmony_ci      }
28401cb0ef41Sopenharmony_ci
28411cb0ef41Sopenharmony_ci      if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_DUPLICATE) {
28421cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_dtable_duplicate_add(decoder);
28431cb0ef41Sopenharmony_ci        if (rv != 0) {
28441cb0ef41Sopenharmony_ci          goto fail;
28451cb0ef41Sopenharmony_ci        }
28461cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
28471cb0ef41Sopenharmony_ci        nghttp3_qpack_read_state_reset(&decoder->rstate);
28481cb0ef41Sopenharmony_ci        break;
28491cb0ef41Sopenharmony_ci      }
28501cb0ef41Sopenharmony_ci
28511cb0ef41Sopenharmony_ci      if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED) {
28521cb0ef41Sopenharmony_ci        decoder->rstate.prefix = 7;
28531cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN;
28541cb0ef41Sopenharmony_ci        break;
28551cb0ef41Sopenharmony_ci      }
28561cb0ef41Sopenharmony_ci
28571cb0ef41Sopenharmony_ci      /* Unreachable */
28581cb0ef41Sopenharmony_ci      assert(0);
28591cb0ef41Sopenharmony_ci      break;
28601cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN:
28611cb0ef41Sopenharmony_ci      qpack_read_state_check_huffman(&decoder->rstate, *p);
28621cb0ef41Sopenharmony_ci      decoder->state = NGHTTP3_QPACK_ES_STATE_READ_NAMELEN;
28631cb0ef41Sopenharmony_ci      decoder->rstate.left = 0;
28641cb0ef41Sopenharmony_ci      decoder->rstate.shift = 0;
28651cb0ef41Sopenharmony_ci      /* Fall through */
28661cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_NAMELEN:
28671cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &decoder->rstate, p, end);
28681cb0ef41Sopenharmony_ci      if (nread < 0) {
28691cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
28701cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
28711cb0ef41Sopenharmony_ci        goto fail;
28721cb0ef41Sopenharmony_ci      }
28731cb0ef41Sopenharmony_ci
28741cb0ef41Sopenharmony_ci      p += nread;
28751cb0ef41Sopenharmony_ci
28761cb0ef41Sopenharmony_ci      if (!rfin) {
28771cb0ef41Sopenharmony_ci        return p - src;
28781cb0ef41Sopenharmony_ci      }
28791cb0ef41Sopenharmony_ci
28801cb0ef41Sopenharmony_ci      if (decoder->rstate.left > NGHTTP3_QPACK_MAX_NAMELEN) {
28811cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
28821cb0ef41Sopenharmony_ci        goto fail;
28831cb0ef41Sopenharmony_ci      }
28841cb0ef41Sopenharmony_ci
28851cb0ef41Sopenharmony_ci      if (decoder->rstate.huffman_encoded) {
28861cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_NAME_HUFFMAN;
28871cb0ef41Sopenharmony_ci        nghttp3_qpack_huffman_decode_context_init(&decoder->rstate.huffman_ctx);
28881cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&decoder->rstate.name,
28891cb0ef41Sopenharmony_ci                               (size_t)decoder->rstate.left * 2 + 1, mem);
28901cb0ef41Sopenharmony_ci      } else {
28911cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_NAME;
28921cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&decoder->rstate.name,
28931cb0ef41Sopenharmony_ci                               (size_t)decoder->rstate.left + 1, mem);
28941cb0ef41Sopenharmony_ci      }
28951cb0ef41Sopenharmony_ci      if (rv != 0) {
28961cb0ef41Sopenharmony_ci        goto fail;
28971cb0ef41Sopenharmony_ci      }
28981cb0ef41Sopenharmony_ci
28991cb0ef41Sopenharmony_ci      nghttp3_buf_wrap_init(&decoder->rstate.namebuf,
29001cb0ef41Sopenharmony_ci                            decoder->rstate.name->base,
29011cb0ef41Sopenharmony_ci                            decoder->rstate.name->len);
29021cb0ef41Sopenharmony_ci      break;
29031cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_NAME_HUFFMAN:
29041cb0ef41Sopenharmony_ci      nread = qpack_read_huffman_string(&decoder->rstate,
29051cb0ef41Sopenharmony_ci                                        &decoder->rstate.namebuf, p, end);
29061cb0ef41Sopenharmony_ci      if (nread < 0) {
29071cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
29081cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
29091cb0ef41Sopenharmony_ci        goto fail;
29101cb0ef41Sopenharmony_ci      }
29111cb0ef41Sopenharmony_ci
29121cb0ef41Sopenharmony_ci      p += nread;
29131cb0ef41Sopenharmony_ci
29141cb0ef41Sopenharmony_ci      if (decoder->rstate.left) {
29151cb0ef41Sopenharmony_ci        return p - src;
29161cb0ef41Sopenharmony_ci      }
29171cb0ef41Sopenharmony_ci
29181cb0ef41Sopenharmony_ci      qpack_read_state_terminate_name(&decoder->rstate);
29191cb0ef41Sopenharmony_ci
29201cb0ef41Sopenharmony_ci      decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN;
29211cb0ef41Sopenharmony_ci      decoder->rstate.prefix = 7;
29221cb0ef41Sopenharmony_ci      break;
29231cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_NAME:
29241cb0ef41Sopenharmony_ci      nread =
29251cb0ef41Sopenharmony_ci          qpack_read_string(&decoder->rstate, &decoder->rstate.namebuf, p, end);
29261cb0ef41Sopenharmony_ci      if (nread < 0) {
29271cb0ef41Sopenharmony_ci        rv = (int)nread;
29281cb0ef41Sopenharmony_ci        goto fail;
29291cb0ef41Sopenharmony_ci      }
29301cb0ef41Sopenharmony_ci
29311cb0ef41Sopenharmony_ci      p += nread;
29321cb0ef41Sopenharmony_ci
29331cb0ef41Sopenharmony_ci      if (decoder->rstate.left) {
29341cb0ef41Sopenharmony_ci        return p - src;
29351cb0ef41Sopenharmony_ci      }
29361cb0ef41Sopenharmony_ci
29371cb0ef41Sopenharmony_ci      qpack_read_state_terminate_name(&decoder->rstate);
29381cb0ef41Sopenharmony_ci
29391cb0ef41Sopenharmony_ci      decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN;
29401cb0ef41Sopenharmony_ci      decoder->rstate.prefix = 7;
29411cb0ef41Sopenharmony_ci      break;
29421cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN:
29431cb0ef41Sopenharmony_ci      qpack_read_state_check_huffman(&decoder->rstate, *p);
29441cb0ef41Sopenharmony_ci      decoder->state = NGHTTP3_QPACK_ES_STATE_READ_VALUELEN;
29451cb0ef41Sopenharmony_ci      decoder->rstate.left = 0;
29461cb0ef41Sopenharmony_ci      decoder->rstate.shift = 0;
29471cb0ef41Sopenharmony_ci      /* Fall through */
29481cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_VALUELEN:
29491cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &decoder->rstate, p, end);
29501cb0ef41Sopenharmony_ci      if (nread < 0) {
29511cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
29521cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
29531cb0ef41Sopenharmony_ci        goto fail;
29541cb0ef41Sopenharmony_ci      }
29551cb0ef41Sopenharmony_ci
29561cb0ef41Sopenharmony_ci      p += nread;
29571cb0ef41Sopenharmony_ci
29581cb0ef41Sopenharmony_ci      if (!rfin) {
29591cb0ef41Sopenharmony_ci        return p - src;
29601cb0ef41Sopenharmony_ci      }
29611cb0ef41Sopenharmony_ci
29621cb0ef41Sopenharmony_ci      if (decoder->rstate.left > NGHTTP3_QPACK_MAX_VALUELEN) {
29631cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
29641cb0ef41Sopenharmony_ci        goto fail;
29651cb0ef41Sopenharmony_ci      }
29661cb0ef41Sopenharmony_ci
29671cb0ef41Sopenharmony_ci      if (decoder->rstate.huffman_encoded) {
29681cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_VALUE_HUFFMAN;
29691cb0ef41Sopenharmony_ci        nghttp3_qpack_huffman_decode_context_init(&decoder->rstate.huffman_ctx);
29701cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&decoder->rstate.value,
29711cb0ef41Sopenharmony_ci                               (size_t)decoder->rstate.left * 2 + 1, mem);
29721cb0ef41Sopenharmony_ci      } else {
29731cb0ef41Sopenharmony_ci        decoder->state = NGHTTP3_QPACK_ES_STATE_READ_VALUE;
29741cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&decoder->rstate.value,
29751cb0ef41Sopenharmony_ci                               (size_t)decoder->rstate.left + 1, mem);
29761cb0ef41Sopenharmony_ci      }
29771cb0ef41Sopenharmony_ci      if (rv != 0) {
29781cb0ef41Sopenharmony_ci        goto fail;
29791cb0ef41Sopenharmony_ci      }
29801cb0ef41Sopenharmony_ci
29811cb0ef41Sopenharmony_ci      nghttp3_buf_wrap_init(&decoder->rstate.valuebuf,
29821cb0ef41Sopenharmony_ci                            decoder->rstate.value->base,
29831cb0ef41Sopenharmony_ci                            decoder->rstate.value->len);
29841cb0ef41Sopenharmony_ci
29851cb0ef41Sopenharmony_ci      /* value might be 0 length */
29861cb0ef41Sopenharmony_ci      busy = 1;
29871cb0ef41Sopenharmony_ci      break;
29881cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_VALUE_HUFFMAN:
29891cb0ef41Sopenharmony_ci      nread = qpack_read_huffman_string(&decoder->rstate,
29901cb0ef41Sopenharmony_ci                                        &decoder->rstate.valuebuf, p, end);
29911cb0ef41Sopenharmony_ci      if (nread < 0) {
29921cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
29931cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
29941cb0ef41Sopenharmony_ci        goto fail;
29951cb0ef41Sopenharmony_ci      }
29961cb0ef41Sopenharmony_ci
29971cb0ef41Sopenharmony_ci      p += nread;
29981cb0ef41Sopenharmony_ci
29991cb0ef41Sopenharmony_ci      if (decoder->rstate.left) {
30001cb0ef41Sopenharmony_ci        return p - src;
30011cb0ef41Sopenharmony_ci      }
30021cb0ef41Sopenharmony_ci
30031cb0ef41Sopenharmony_ci      qpack_read_state_terminate_value(&decoder->rstate);
30041cb0ef41Sopenharmony_ci
30051cb0ef41Sopenharmony_ci      switch (decoder->opcode) {
30061cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED:
30071cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_dtable_indexed_add(decoder);
30081cb0ef41Sopenharmony_ci        break;
30091cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_ES_OPCODE_INSERT:
30101cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_dtable_literal_add(decoder);
30111cb0ef41Sopenharmony_ci        break;
30121cb0ef41Sopenharmony_ci      default:
30131cb0ef41Sopenharmony_ci        /* Unreachable */
30141cb0ef41Sopenharmony_ci        assert(0);
30151cb0ef41Sopenharmony_ci        abort();
30161cb0ef41Sopenharmony_ci      }
30171cb0ef41Sopenharmony_ci      if (rv != 0) {
30181cb0ef41Sopenharmony_ci        goto fail;
30191cb0ef41Sopenharmony_ci      }
30201cb0ef41Sopenharmony_ci
30211cb0ef41Sopenharmony_ci      decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
30221cb0ef41Sopenharmony_ci      nghttp3_qpack_read_state_reset(&decoder->rstate);
30231cb0ef41Sopenharmony_ci      break;
30241cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_ES_STATE_READ_VALUE:
30251cb0ef41Sopenharmony_ci      nread = qpack_read_string(&decoder->rstate, &decoder->rstate.valuebuf, p,
30261cb0ef41Sopenharmony_ci                                end);
30271cb0ef41Sopenharmony_ci      if (nread < 0) {
30281cb0ef41Sopenharmony_ci        rv = (int)nread;
30291cb0ef41Sopenharmony_ci        goto fail;
30301cb0ef41Sopenharmony_ci      }
30311cb0ef41Sopenharmony_ci
30321cb0ef41Sopenharmony_ci      p += nread;
30331cb0ef41Sopenharmony_ci
30341cb0ef41Sopenharmony_ci      if (decoder->rstate.left) {
30351cb0ef41Sopenharmony_ci        return p - src;
30361cb0ef41Sopenharmony_ci      }
30371cb0ef41Sopenharmony_ci
30381cb0ef41Sopenharmony_ci      qpack_read_state_terminate_value(&decoder->rstate);
30391cb0ef41Sopenharmony_ci
30401cb0ef41Sopenharmony_ci      switch (decoder->opcode) {
30411cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED:
30421cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_dtable_indexed_add(decoder);
30431cb0ef41Sopenharmony_ci        break;
30441cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_ES_OPCODE_INSERT:
30451cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_dtable_literal_add(decoder);
30461cb0ef41Sopenharmony_ci        break;
30471cb0ef41Sopenharmony_ci      default:
30481cb0ef41Sopenharmony_ci        /* Unreachable */
30491cb0ef41Sopenharmony_ci        assert(0);
30501cb0ef41Sopenharmony_ci        abort();
30511cb0ef41Sopenharmony_ci      }
30521cb0ef41Sopenharmony_ci      if (rv != 0) {
30531cb0ef41Sopenharmony_ci        goto fail;
30541cb0ef41Sopenharmony_ci      }
30551cb0ef41Sopenharmony_ci
30561cb0ef41Sopenharmony_ci      decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
30571cb0ef41Sopenharmony_ci      nghttp3_qpack_read_state_reset(&decoder->rstate);
30581cb0ef41Sopenharmony_ci      break;
30591cb0ef41Sopenharmony_ci    }
30601cb0ef41Sopenharmony_ci  }
30611cb0ef41Sopenharmony_ci
30621cb0ef41Sopenharmony_ci  return p - src;
30631cb0ef41Sopenharmony_ci
30641cb0ef41Sopenharmony_cifail:
30651cb0ef41Sopenharmony_ci  decoder->ctx.bad = 1;
30661cb0ef41Sopenharmony_ci  return rv;
30671cb0ef41Sopenharmony_ci}
30681cb0ef41Sopenharmony_ci
30691cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_set_max_dtable_capacity(
30701cb0ef41Sopenharmony_ci    nghttp3_qpack_decoder *decoder, size_t max_dtable_capacity) {
30711cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
30721cb0ef41Sopenharmony_ci  size_t i;
30731cb0ef41Sopenharmony_ci  nghttp3_qpack_context *ctx = &decoder->ctx;
30741cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = ctx->mem;
30751cb0ef41Sopenharmony_ci
30761cb0ef41Sopenharmony_ci  if (max_dtable_capacity > decoder->ctx.hard_max_dtable_capacity) {
30771cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_INVALID_ARGUMENT;
30781cb0ef41Sopenharmony_ci  }
30791cb0ef41Sopenharmony_ci
30801cb0ef41Sopenharmony_ci  ctx->max_dtable_capacity = max_dtable_capacity;
30811cb0ef41Sopenharmony_ci
30821cb0ef41Sopenharmony_ci  while (ctx->dtable_size > max_dtable_capacity) {
30831cb0ef41Sopenharmony_ci    i = nghttp3_ringbuf_len(&ctx->dtable);
30841cb0ef41Sopenharmony_ci    assert(i);
30851cb0ef41Sopenharmony_ci    ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, i - 1);
30861cb0ef41Sopenharmony_ci
30871cb0ef41Sopenharmony_ci    ctx->dtable_size -= table_space(ent->nv.name->len, ent->nv.value->len);
30881cb0ef41Sopenharmony_ci
30891cb0ef41Sopenharmony_ci    nghttp3_ringbuf_pop_back(&ctx->dtable);
30901cb0ef41Sopenharmony_ci    nghttp3_qpack_entry_free(ent);
30911cb0ef41Sopenharmony_ci    nghttp3_mem_free(mem, ent);
30921cb0ef41Sopenharmony_ci  }
30931cb0ef41Sopenharmony_ci
30941cb0ef41Sopenharmony_ci  return 0;
30951cb0ef41Sopenharmony_ci}
30961cb0ef41Sopenharmony_ci
30971cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_dtable_indexed_add(nghttp3_qpack_decoder *decoder) {
30981cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: Insert With Name Reference (%s) absidx=%" PRIu64 ": "
30991cb0ef41Sopenharmony_ci         "value=%*s\n",
31001cb0ef41Sopenharmony_ci         decoder->rstate.dynamic ? "dynamic" : "static", decoder->rstate.absidx,
31011cb0ef41Sopenharmony_ci         (int)decoder->rstate.value->len, decoder->rstate.value->base);
31021cb0ef41Sopenharmony_ci
31031cb0ef41Sopenharmony_ci  if (decoder->rstate.dynamic) {
31041cb0ef41Sopenharmony_ci    return nghttp3_qpack_decoder_dtable_dynamic_add(decoder);
31051cb0ef41Sopenharmony_ci  }
31061cb0ef41Sopenharmony_ci
31071cb0ef41Sopenharmony_ci  return nghttp3_qpack_decoder_dtable_static_add(decoder);
31081cb0ef41Sopenharmony_ci}
31091cb0ef41Sopenharmony_ci
31101cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_dtable_static_add(nghttp3_qpack_decoder *decoder) {
31111cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
31121cb0ef41Sopenharmony_ci  int rv;
31131cb0ef41Sopenharmony_ci  const nghttp3_qpack_static_header *shd;
31141cb0ef41Sopenharmony_ci
31151cb0ef41Sopenharmony_ci  shd = &stable[decoder->rstate.absidx];
31161cb0ef41Sopenharmony_ci
31171cb0ef41Sopenharmony_ci  if (table_space(shd->name.len, decoder->rstate.value->len) >
31181cb0ef41Sopenharmony_ci      decoder->ctx.max_dtable_capacity) {
31191cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
31201cb0ef41Sopenharmony_ci  }
31211cb0ef41Sopenharmony_ci
31221cb0ef41Sopenharmony_ci  qnv.name = (nghttp3_rcbuf *)&shd->name;
31231cb0ef41Sopenharmony_ci  qnv.value = decoder->rstate.value;
31241cb0ef41Sopenharmony_ci  qnv.token = shd->token;
31251cb0ef41Sopenharmony_ci  qnv.flags = NGHTTP3_NV_FLAG_NONE;
31261cb0ef41Sopenharmony_ci
31271cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
31281cb0ef41Sopenharmony_ci
31291cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
31301cb0ef41Sopenharmony_ci
31311cb0ef41Sopenharmony_ci  return rv;
31321cb0ef41Sopenharmony_ci}
31331cb0ef41Sopenharmony_ci
31341cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_dtable_dynamic_add(nghttp3_qpack_decoder *decoder) {
31351cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
31361cb0ef41Sopenharmony_ci  int rv;
31371cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
31381cb0ef41Sopenharmony_ci
31391cb0ef41Sopenharmony_ci  ent = nghttp3_qpack_context_dtable_get(&decoder->ctx, decoder->rstate.absidx);
31401cb0ef41Sopenharmony_ci
31411cb0ef41Sopenharmony_ci  if (table_space(ent->nv.name->len, decoder->rstate.value->len) >
31421cb0ef41Sopenharmony_ci      decoder->ctx.max_dtable_capacity) {
31431cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
31441cb0ef41Sopenharmony_ci  }
31451cb0ef41Sopenharmony_ci
31461cb0ef41Sopenharmony_ci  qnv.name = ent->nv.name;
31471cb0ef41Sopenharmony_ci  qnv.value = decoder->rstate.value;
31481cb0ef41Sopenharmony_ci  qnv.token = ent->nv.token;
31491cb0ef41Sopenharmony_ci  qnv.flags = NGHTTP3_NV_FLAG_NONE;
31501cb0ef41Sopenharmony_ci
31511cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(qnv.name);
31521cb0ef41Sopenharmony_ci
31531cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
31541cb0ef41Sopenharmony_ci
31551cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
31561cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.name);
31571cb0ef41Sopenharmony_ci
31581cb0ef41Sopenharmony_ci  return rv;
31591cb0ef41Sopenharmony_ci}
31601cb0ef41Sopenharmony_ci
31611cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_dtable_duplicate_add(nghttp3_qpack_decoder *decoder) {
31621cb0ef41Sopenharmony_ci  int rv;
31631cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
31641cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
31651cb0ef41Sopenharmony_ci
31661cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: Insert duplicate absidx=%" PRIu64 "\n",
31671cb0ef41Sopenharmony_ci         decoder->rstate.absidx);
31681cb0ef41Sopenharmony_ci
31691cb0ef41Sopenharmony_ci  ent = nghttp3_qpack_context_dtable_get(&decoder->ctx, decoder->rstate.absidx);
31701cb0ef41Sopenharmony_ci
31711cb0ef41Sopenharmony_ci  if (table_space(ent->nv.name->len, ent->nv.value->len) >
31721cb0ef41Sopenharmony_ci      decoder->ctx.max_dtable_capacity) {
31731cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
31741cb0ef41Sopenharmony_ci  }
31751cb0ef41Sopenharmony_ci
31761cb0ef41Sopenharmony_ci  qnv = ent->nv;
31771cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(qnv.name);
31781cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(qnv.value);
31791cb0ef41Sopenharmony_ci
31801cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
31811cb0ef41Sopenharmony_ci
31821cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
31831cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.name);
31841cb0ef41Sopenharmony_ci
31851cb0ef41Sopenharmony_ci  return rv;
31861cb0ef41Sopenharmony_ci}
31871cb0ef41Sopenharmony_ci
31881cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_dtable_literal_add(nghttp3_qpack_decoder *decoder) {
31891cb0ef41Sopenharmony_ci  nghttp3_qpack_nv qnv;
31901cb0ef41Sopenharmony_ci  int rv;
31911cb0ef41Sopenharmony_ci
31921cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: Insert With Literal Name: name=%*s value=%*s\n",
31931cb0ef41Sopenharmony_ci         (int)decoder->rstate.name->len, decoder->rstate.name->base,
31941cb0ef41Sopenharmony_ci         (int)decoder->rstate.value->len, decoder->rstate.value->base);
31951cb0ef41Sopenharmony_ci
31961cb0ef41Sopenharmony_ci  if (table_space(decoder->rstate.name->len, decoder->rstate.value->len) >
31971cb0ef41Sopenharmony_ci      decoder->ctx.max_dtable_capacity) {
31981cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
31991cb0ef41Sopenharmony_ci  }
32001cb0ef41Sopenharmony_ci
32011cb0ef41Sopenharmony_ci  qnv.name = decoder->rstate.name;
32021cb0ef41Sopenharmony_ci  qnv.value = decoder->rstate.value;
32031cb0ef41Sopenharmony_ci  qnv.token = qpack_lookup_token(qnv.name->base, qnv.name->len);
32041cb0ef41Sopenharmony_ci  qnv.flags = NGHTTP3_NV_FLAG_NONE;
32051cb0ef41Sopenharmony_ci
32061cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
32071cb0ef41Sopenharmony_ci
32081cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.value);
32091cb0ef41Sopenharmony_ci  nghttp3_rcbuf_decref(qnv.name);
32101cb0ef41Sopenharmony_ci
32111cb0ef41Sopenharmony_ci  return rv;
32121cb0ef41Sopenharmony_ci}
32131cb0ef41Sopenharmony_ci
32141cb0ef41Sopenharmony_civoid nghttp3_qpack_decoder_set_max_concurrent_streams(
32151cb0ef41Sopenharmony_ci    nghttp3_qpack_decoder *decoder, size_t max_concurrent_streams) {
32161cb0ef41Sopenharmony_ci  decoder->max_concurrent_streams =
32171cb0ef41Sopenharmony_ci      nghttp3_max(decoder->max_concurrent_streams, max_concurrent_streams);
32181cb0ef41Sopenharmony_ci}
32191cb0ef41Sopenharmony_ci
32201cb0ef41Sopenharmony_civoid nghttp3_qpack_stream_context_init(nghttp3_qpack_stream_context *sctx,
32211cb0ef41Sopenharmony_ci                                       int64_t stream_id,
32221cb0ef41Sopenharmony_ci                                       const nghttp3_mem *mem) {
32231cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state_reset(&sctx->rstate);
32241cb0ef41Sopenharmony_ci
32251cb0ef41Sopenharmony_ci  sctx->mem = mem;
32261cb0ef41Sopenharmony_ci  sctx->rstate.prefix = 8;
32271cb0ef41Sopenharmony_ci  sctx->state = NGHTTP3_QPACK_RS_STATE_RICNT;
32281cb0ef41Sopenharmony_ci  sctx->opcode = 0;
32291cb0ef41Sopenharmony_ci  sctx->stream_id = stream_id;
32301cb0ef41Sopenharmony_ci  sctx->ricnt = 0;
32311cb0ef41Sopenharmony_ci  sctx->dbase_sign = 0;
32321cb0ef41Sopenharmony_ci  sctx->base = 0;
32331cb0ef41Sopenharmony_ci}
32341cb0ef41Sopenharmony_ci
32351cb0ef41Sopenharmony_civoid nghttp3_qpack_stream_context_free(nghttp3_qpack_stream_context *sctx) {
32361cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state_free(&sctx->rstate);
32371cb0ef41Sopenharmony_ci}
32381cb0ef41Sopenharmony_ci
32391cb0ef41Sopenharmony_civoid nghttp3_qpack_stream_context_reset(nghttp3_qpack_stream_context *sctx) {
32401cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_context_init(sctx, sctx->stream_id, sctx->mem);
32411cb0ef41Sopenharmony_ci}
32421cb0ef41Sopenharmony_ci
32431cb0ef41Sopenharmony_ciuint64_t
32441cb0ef41Sopenharmony_cinghttp3_qpack_stream_context_get_ricnt(nghttp3_qpack_stream_context *sctx) {
32451cb0ef41Sopenharmony_ci  return sctx->ricnt;
32461cb0ef41Sopenharmony_ci}
32471cb0ef41Sopenharmony_ci
32481cb0ef41Sopenharmony_cinghttp3_ssize
32491cb0ef41Sopenharmony_cinghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder,
32501cb0ef41Sopenharmony_ci                                   nghttp3_qpack_stream_context *sctx,
32511cb0ef41Sopenharmony_ci                                   nghttp3_qpack_nv *nv, uint8_t *pflags,
32521cb0ef41Sopenharmony_ci                                   const uint8_t *src, size_t srclen, int fin) {
32531cb0ef41Sopenharmony_ci  const uint8_t *p = src, *end = src ? src + srclen : src;
32541cb0ef41Sopenharmony_ci  int rv;
32551cb0ef41Sopenharmony_ci  int busy = 0;
32561cb0ef41Sopenharmony_ci  nghttp3_ssize nread;
32571cb0ef41Sopenharmony_ci  int rfin;
32581cb0ef41Sopenharmony_ci  const nghttp3_mem *mem = decoder->ctx.mem;
32591cb0ef41Sopenharmony_ci
32601cb0ef41Sopenharmony_ci  if (decoder->ctx.bad) {
32611cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
32621cb0ef41Sopenharmony_ci  }
32631cb0ef41Sopenharmony_ci
32641cb0ef41Sopenharmony_ci  *pflags = NGHTTP3_QPACK_DECODE_FLAG_NONE;
32651cb0ef41Sopenharmony_ci
32661cb0ef41Sopenharmony_ci  for (; p != end || busy;) {
32671cb0ef41Sopenharmony_ci    busy = 0;
32681cb0ef41Sopenharmony_ci    switch (sctx->state) {
32691cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_RICNT:
32701cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
32711cb0ef41Sopenharmony_ci      if (nread < 0) {
32721cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
32731cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
32741cb0ef41Sopenharmony_ci        goto fail;
32751cb0ef41Sopenharmony_ci      }
32761cb0ef41Sopenharmony_ci
32771cb0ef41Sopenharmony_ci      p += nread;
32781cb0ef41Sopenharmony_ci
32791cb0ef41Sopenharmony_ci      if (!rfin) {
32801cb0ef41Sopenharmony_ci        goto almost_ok;
32811cb0ef41Sopenharmony_ci      }
32821cb0ef41Sopenharmony_ci
32831cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_decoder_reconstruct_ricnt(decoder, &sctx->ricnt,
32841cb0ef41Sopenharmony_ci                                                   sctx->rstate.left);
32851cb0ef41Sopenharmony_ci      if (rv != 0) {
32861cb0ef41Sopenharmony_ci        goto fail;
32871cb0ef41Sopenharmony_ci      }
32881cb0ef41Sopenharmony_ci
32891cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_DBASE_SIGN;
32901cb0ef41Sopenharmony_ci      break;
32911cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_DBASE_SIGN:
32921cb0ef41Sopenharmony_ci      if ((*p) & 0x80) {
32931cb0ef41Sopenharmony_ci        sctx->dbase_sign = 1;
32941cb0ef41Sopenharmony_ci      }
32951cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_DBASE;
32961cb0ef41Sopenharmony_ci      sctx->rstate.left = 0;
32971cb0ef41Sopenharmony_ci      sctx->rstate.prefix = 7;
32981cb0ef41Sopenharmony_ci      sctx->rstate.shift = 0;
32991cb0ef41Sopenharmony_ci      /* Fall through */
33001cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_DBASE:
33011cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
33021cb0ef41Sopenharmony_ci      if (nread < 0) {
33031cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
33041cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
33051cb0ef41Sopenharmony_ci        goto fail;
33061cb0ef41Sopenharmony_ci      }
33071cb0ef41Sopenharmony_ci
33081cb0ef41Sopenharmony_ci      p += nread;
33091cb0ef41Sopenharmony_ci
33101cb0ef41Sopenharmony_ci      if (!rfin) {
33111cb0ef41Sopenharmony_ci        goto almost_ok;
33121cb0ef41Sopenharmony_ci      }
33131cb0ef41Sopenharmony_ci
33141cb0ef41Sopenharmony_ci      if (sctx->dbase_sign) {
33151cb0ef41Sopenharmony_ci        if (sctx->ricnt <= sctx->rstate.left) {
33161cb0ef41Sopenharmony_ci          rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
33171cb0ef41Sopenharmony_ci          goto fail;
33181cb0ef41Sopenharmony_ci        }
33191cb0ef41Sopenharmony_ci        sctx->base = sctx->ricnt - sctx->rstate.left - 1;
33201cb0ef41Sopenharmony_ci      } else {
33211cb0ef41Sopenharmony_ci        sctx->base = sctx->ricnt + sctx->rstate.left;
33221cb0ef41Sopenharmony_ci      }
33231cb0ef41Sopenharmony_ci
33241cb0ef41Sopenharmony_ci      DEBUGF("qpack::decode: ricnt=%" PRIu64 " base=%" PRIu64 " icnt=%" PRIu64
33251cb0ef41Sopenharmony_ci             "\n",
33261cb0ef41Sopenharmony_ci             sctx->ricnt, sctx->base, decoder->ctx.next_absidx);
33271cb0ef41Sopenharmony_ci
33281cb0ef41Sopenharmony_ci      if (sctx->ricnt > decoder->ctx.next_absidx) {
33291cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: stream blocked\n");
33301cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_BLOCKED;
33311cb0ef41Sopenharmony_ci        *pflags |= NGHTTP3_QPACK_DECODE_FLAG_BLOCKED;
33321cb0ef41Sopenharmony_ci        return p - src;
33331cb0ef41Sopenharmony_ci      }
33341cb0ef41Sopenharmony_ci
33351cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
33361cb0ef41Sopenharmony_ci      sctx->rstate.left = 0;
33371cb0ef41Sopenharmony_ci      sctx->rstate.shift = 0;
33381cb0ef41Sopenharmony_ci      break;
33391cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_OPCODE:
33401cb0ef41Sopenharmony_ci      assert(sctx->rstate.left == 0);
33411cb0ef41Sopenharmony_ci      assert(sctx->rstate.shift == 0);
33421cb0ef41Sopenharmony_ci      if ((*p) & 0x80) {
33431cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_INDEXED\n");
33441cb0ef41Sopenharmony_ci        sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED;
33451cb0ef41Sopenharmony_ci        sctx->rstate.dynamic = !((*p) & 0x40);
33461cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 6;
33471cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
33481cb0ef41Sopenharmony_ci      } else if ((*p) & 0x40) {
33491cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_INDEXED_NAME\n");
33501cb0ef41Sopenharmony_ci        sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME;
33511cb0ef41Sopenharmony_ci        sctx->rstate.never = (*p) & 0x20;
33521cb0ef41Sopenharmony_ci        sctx->rstate.dynamic = !((*p) & 0x10);
33531cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 4;
33541cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
33551cb0ef41Sopenharmony_ci      } else if ((*p) & 0x20) {
33561cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_LITERAL\n");
33571cb0ef41Sopenharmony_ci        sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_LITERAL;
33581cb0ef41Sopenharmony_ci        sctx->rstate.never = (*p) & 0x10;
33591cb0ef41Sopenharmony_ci        sctx->rstate.dynamic = 0;
33601cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 3;
33611cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN;
33621cb0ef41Sopenharmony_ci      } else if ((*p) & 0x10) {
33631cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_INDEXED_PB\n");
33641cb0ef41Sopenharmony_ci        sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB;
33651cb0ef41Sopenharmony_ci        sctx->rstate.dynamic = 1;
33661cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 4;
33671cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
33681cb0ef41Sopenharmony_ci      } else {
33691cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: OPCODE_INDEXED_NAME_PB\n");
33701cb0ef41Sopenharmony_ci        sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB;
33711cb0ef41Sopenharmony_ci        sctx->rstate.never = (*p) & 0x08;
33721cb0ef41Sopenharmony_ci        sctx->rstate.dynamic = 1;
33731cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 3;
33741cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
33751cb0ef41Sopenharmony_ci      }
33761cb0ef41Sopenharmony_ci      break;
33771cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_INDEX:
33781cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
33791cb0ef41Sopenharmony_ci      if (nread < 0) {
33801cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
33811cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
33821cb0ef41Sopenharmony_ci        goto fail;
33831cb0ef41Sopenharmony_ci      }
33841cb0ef41Sopenharmony_ci
33851cb0ef41Sopenharmony_ci      p += nread;
33861cb0ef41Sopenharmony_ci
33871cb0ef41Sopenharmony_ci      if (!rfin) {
33881cb0ef41Sopenharmony_ci        goto almost_ok;
33891cb0ef41Sopenharmony_ci      }
33901cb0ef41Sopenharmony_ci
33911cb0ef41Sopenharmony_ci      switch (sctx->opcode) {
33921cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED:
33931cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_brel2abs(decoder, sctx);
33941cb0ef41Sopenharmony_ci        if (rv != 0) {
33951cb0ef41Sopenharmony_ci          goto fail;
33961cb0ef41Sopenharmony_ci        }
33971cb0ef41Sopenharmony_ci        nghttp3_qpack_decoder_emit_indexed(decoder, sctx, nv);
33981cb0ef41Sopenharmony_ci        *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
33991cb0ef41Sopenharmony_ci
34001cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
34011cb0ef41Sopenharmony_ci        nghttp3_qpack_read_state_reset(&sctx->rstate);
34021cb0ef41Sopenharmony_ci
34031cb0ef41Sopenharmony_ci        return p - src;
34041cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB:
34051cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_pbrel2abs(decoder, sctx);
34061cb0ef41Sopenharmony_ci        if (rv != 0) {
34071cb0ef41Sopenharmony_ci          goto fail;
34081cb0ef41Sopenharmony_ci        }
34091cb0ef41Sopenharmony_ci        nghttp3_qpack_decoder_emit_indexed(decoder, sctx, nv);
34101cb0ef41Sopenharmony_ci        *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
34111cb0ef41Sopenharmony_ci
34121cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
34131cb0ef41Sopenharmony_ci        nghttp3_qpack_read_state_reset(&sctx->rstate);
34141cb0ef41Sopenharmony_ci
34151cb0ef41Sopenharmony_ci        return p - src;
34161cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME:
34171cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_brel2abs(decoder, sctx);
34181cb0ef41Sopenharmony_ci        if (rv != 0) {
34191cb0ef41Sopenharmony_ci          goto fail;
34201cb0ef41Sopenharmony_ci        }
34211cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 7;
34221cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
34231cb0ef41Sopenharmony_ci        break;
34241cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB:
34251cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_pbrel2abs(decoder, sctx);
34261cb0ef41Sopenharmony_ci        if (rv != 0) {
34271cb0ef41Sopenharmony_ci          goto fail;
34281cb0ef41Sopenharmony_ci        }
34291cb0ef41Sopenharmony_ci        sctx->rstate.prefix = 7;
34301cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
34311cb0ef41Sopenharmony_ci        break;
34321cb0ef41Sopenharmony_ci      default:
34331cb0ef41Sopenharmony_ci        /* Unreachable */
34341cb0ef41Sopenharmony_ci        assert(0);
34351cb0ef41Sopenharmony_ci      }
34361cb0ef41Sopenharmony_ci      break;
34371cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN:
34381cb0ef41Sopenharmony_ci      qpack_read_state_check_huffman(&sctx->rstate, *p);
34391cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_READ_NAMELEN;
34401cb0ef41Sopenharmony_ci      sctx->rstate.left = 0;
34411cb0ef41Sopenharmony_ci      sctx->rstate.shift = 0;
34421cb0ef41Sopenharmony_ci      /* Fall through */
34431cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_NAMELEN:
34441cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
34451cb0ef41Sopenharmony_ci      if (nread < 0) {
34461cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
34471cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
34481cb0ef41Sopenharmony_ci        goto fail;
34491cb0ef41Sopenharmony_ci      }
34501cb0ef41Sopenharmony_ci
34511cb0ef41Sopenharmony_ci      p += nread;
34521cb0ef41Sopenharmony_ci
34531cb0ef41Sopenharmony_ci      if (!rfin) {
34541cb0ef41Sopenharmony_ci        goto almost_ok;
34551cb0ef41Sopenharmony_ci      }
34561cb0ef41Sopenharmony_ci
34571cb0ef41Sopenharmony_ci      if (sctx->rstate.left > NGHTTP3_QPACK_MAX_NAMELEN) {
34581cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
34591cb0ef41Sopenharmony_ci        goto fail;
34601cb0ef41Sopenharmony_ci      }
34611cb0ef41Sopenharmony_ci
34621cb0ef41Sopenharmony_ci      if (sctx->rstate.huffman_encoded) {
34631cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_NAME_HUFFMAN;
34641cb0ef41Sopenharmony_ci        nghttp3_qpack_huffman_decode_context_init(&sctx->rstate.huffman_ctx);
34651cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&sctx->rstate.name,
34661cb0ef41Sopenharmony_ci                               (size_t)sctx->rstate.left * 2 + 1, mem);
34671cb0ef41Sopenharmony_ci      } else {
34681cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_NAME;
34691cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&sctx->rstate.name,
34701cb0ef41Sopenharmony_ci                               (size_t)sctx->rstate.left + 1, mem);
34711cb0ef41Sopenharmony_ci      }
34721cb0ef41Sopenharmony_ci      if (rv != 0) {
34731cb0ef41Sopenharmony_ci        goto fail;
34741cb0ef41Sopenharmony_ci      }
34751cb0ef41Sopenharmony_ci
34761cb0ef41Sopenharmony_ci      nghttp3_buf_wrap_init(&sctx->rstate.namebuf, sctx->rstate.name->base,
34771cb0ef41Sopenharmony_ci                            sctx->rstate.name->len);
34781cb0ef41Sopenharmony_ci      break;
34791cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_NAME_HUFFMAN:
34801cb0ef41Sopenharmony_ci      nread = qpack_read_huffman_string(&sctx->rstate, &sctx->rstate.namebuf, p,
34811cb0ef41Sopenharmony_ci                                        end);
34821cb0ef41Sopenharmony_ci      if (nread < 0) {
34831cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
34841cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
34851cb0ef41Sopenharmony_ci        goto fail;
34861cb0ef41Sopenharmony_ci      }
34871cb0ef41Sopenharmony_ci
34881cb0ef41Sopenharmony_ci      p += nread;
34891cb0ef41Sopenharmony_ci
34901cb0ef41Sopenharmony_ci      if (sctx->rstate.left) {
34911cb0ef41Sopenharmony_ci        goto almost_ok;
34921cb0ef41Sopenharmony_ci      }
34931cb0ef41Sopenharmony_ci
34941cb0ef41Sopenharmony_ci      qpack_read_state_terminate_name(&sctx->rstate);
34951cb0ef41Sopenharmony_ci
34961cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
34971cb0ef41Sopenharmony_ci      sctx->rstate.prefix = 7;
34981cb0ef41Sopenharmony_ci      break;
34991cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_NAME:
35001cb0ef41Sopenharmony_ci      nread = qpack_read_string(&sctx->rstate, &sctx->rstate.namebuf, p, end);
35011cb0ef41Sopenharmony_ci      if (nread < 0) {
35021cb0ef41Sopenharmony_ci        rv = (int)nread;
35031cb0ef41Sopenharmony_ci        goto fail;
35041cb0ef41Sopenharmony_ci      }
35051cb0ef41Sopenharmony_ci
35061cb0ef41Sopenharmony_ci      p += nread;
35071cb0ef41Sopenharmony_ci
35081cb0ef41Sopenharmony_ci      if (sctx->rstate.left) {
35091cb0ef41Sopenharmony_ci        goto almost_ok;
35101cb0ef41Sopenharmony_ci      }
35111cb0ef41Sopenharmony_ci
35121cb0ef41Sopenharmony_ci      qpack_read_state_terminate_name(&sctx->rstate);
35131cb0ef41Sopenharmony_ci
35141cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
35151cb0ef41Sopenharmony_ci      sctx->rstate.prefix = 7;
35161cb0ef41Sopenharmony_ci      break;
35171cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN:
35181cb0ef41Sopenharmony_ci      qpack_read_state_check_huffman(&sctx->rstate, *p);
35191cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_READ_VALUELEN;
35201cb0ef41Sopenharmony_ci      sctx->rstate.left = 0;
35211cb0ef41Sopenharmony_ci      sctx->rstate.shift = 0;
35221cb0ef41Sopenharmony_ci      /* Fall through */
35231cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_VALUELEN:
35241cb0ef41Sopenharmony_ci      nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
35251cb0ef41Sopenharmony_ci      if (nread < 0) {
35261cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
35271cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
35281cb0ef41Sopenharmony_ci        goto fail;
35291cb0ef41Sopenharmony_ci      }
35301cb0ef41Sopenharmony_ci
35311cb0ef41Sopenharmony_ci      p += nread;
35321cb0ef41Sopenharmony_ci
35331cb0ef41Sopenharmony_ci      if (!rfin) {
35341cb0ef41Sopenharmony_ci        goto almost_ok;
35351cb0ef41Sopenharmony_ci      }
35361cb0ef41Sopenharmony_ci
35371cb0ef41Sopenharmony_ci      if (sctx->rstate.left > NGHTTP3_QPACK_MAX_VALUELEN) {
35381cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
35391cb0ef41Sopenharmony_ci        goto fail;
35401cb0ef41Sopenharmony_ci      }
35411cb0ef41Sopenharmony_ci
35421cb0ef41Sopenharmony_ci      if (sctx->rstate.huffman_encoded) {
35431cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_VALUE_HUFFMAN;
35441cb0ef41Sopenharmony_ci        nghttp3_qpack_huffman_decode_context_init(&sctx->rstate.huffman_ctx);
35451cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&sctx->rstate.value,
35461cb0ef41Sopenharmony_ci                               (size_t)sctx->rstate.left * 2 + 1, mem);
35471cb0ef41Sopenharmony_ci      } else {
35481cb0ef41Sopenharmony_ci        sctx->state = NGHTTP3_QPACK_RS_STATE_READ_VALUE;
35491cb0ef41Sopenharmony_ci        rv = nghttp3_rcbuf_new(&sctx->rstate.value,
35501cb0ef41Sopenharmony_ci                               (size_t)sctx->rstate.left + 1, mem);
35511cb0ef41Sopenharmony_ci      }
35521cb0ef41Sopenharmony_ci      if (rv != 0) {
35531cb0ef41Sopenharmony_ci        goto fail;
35541cb0ef41Sopenharmony_ci      }
35551cb0ef41Sopenharmony_ci
35561cb0ef41Sopenharmony_ci      nghttp3_buf_wrap_init(&sctx->rstate.valuebuf, sctx->rstate.value->base,
35571cb0ef41Sopenharmony_ci                            sctx->rstate.value->len);
35581cb0ef41Sopenharmony_ci
35591cb0ef41Sopenharmony_ci      /* value might be 0 length */
35601cb0ef41Sopenharmony_ci      busy = 1;
35611cb0ef41Sopenharmony_ci      break;
35621cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_VALUE_HUFFMAN:
35631cb0ef41Sopenharmony_ci      nread = qpack_read_huffman_string(&sctx->rstate, &sctx->rstate.valuebuf,
35641cb0ef41Sopenharmony_ci                                        p, end);
35651cb0ef41Sopenharmony_ci      if (nread < 0) {
35661cb0ef41Sopenharmony_ci        assert(NGHTTP3_ERR_QPACK_FATAL == nread);
35671cb0ef41Sopenharmony_ci        rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
35681cb0ef41Sopenharmony_ci        goto fail;
35691cb0ef41Sopenharmony_ci      }
35701cb0ef41Sopenharmony_ci
35711cb0ef41Sopenharmony_ci      p += nread;
35721cb0ef41Sopenharmony_ci
35731cb0ef41Sopenharmony_ci      if (sctx->rstate.left) {
35741cb0ef41Sopenharmony_ci        goto almost_ok;
35751cb0ef41Sopenharmony_ci      }
35761cb0ef41Sopenharmony_ci
35771cb0ef41Sopenharmony_ci      qpack_read_state_terminate_value(&sctx->rstate);
35781cb0ef41Sopenharmony_ci
35791cb0ef41Sopenharmony_ci      switch (sctx->opcode) {
35801cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME:
35811cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB:
35821cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_emit_indexed_name(decoder, sctx, nv);
35831cb0ef41Sopenharmony_ci        if (rv != 0) {
35841cb0ef41Sopenharmony_ci          goto fail;
35851cb0ef41Sopenharmony_ci        }
35861cb0ef41Sopenharmony_ci
35871cb0ef41Sopenharmony_ci        break;
35881cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_LITERAL:
35891cb0ef41Sopenharmony_ci        nghttp3_qpack_decoder_emit_literal(decoder, sctx, nv);
35901cb0ef41Sopenharmony_ci        break;
35911cb0ef41Sopenharmony_ci      default:
35921cb0ef41Sopenharmony_ci        /* Unreachable */
35931cb0ef41Sopenharmony_ci        assert(0);
35941cb0ef41Sopenharmony_ci      }
35951cb0ef41Sopenharmony_ci
35961cb0ef41Sopenharmony_ci      *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
35971cb0ef41Sopenharmony_ci
35981cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
35991cb0ef41Sopenharmony_ci      nghttp3_qpack_read_state_reset(&sctx->rstate);
36001cb0ef41Sopenharmony_ci
36011cb0ef41Sopenharmony_ci      return p - src;
36021cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_READ_VALUE:
36031cb0ef41Sopenharmony_ci      nread = qpack_read_string(&sctx->rstate, &sctx->rstate.valuebuf, p, end);
36041cb0ef41Sopenharmony_ci      if (nread < 0) {
36051cb0ef41Sopenharmony_ci        rv = (int)nread;
36061cb0ef41Sopenharmony_ci        goto fail;
36071cb0ef41Sopenharmony_ci      }
36081cb0ef41Sopenharmony_ci
36091cb0ef41Sopenharmony_ci      p += nread;
36101cb0ef41Sopenharmony_ci
36111cb0ef41Sopenharmony_ci      if (sctx->rstate.left) {
36121cb0ef41Sopenharmony_ci        goto almost_ok;
36131cb0ef41Sopenharmony_ci      }
36141cb0ef41Sopenharmony_ci
36151cb0ef41Sopenharmony_ci      qpack_read_state_terminate_value(&sctx->rstate);
36161cb0ef41Sopenharmony_ci
36171cb0ef41Sopenharmony_ci      switch (sctx->opcode) {
36181cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME:
36191cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB:
36201cb0ef41Sopenharmony_ci        rv = nghttp3_qpack_decoder_emit_indexed_name(decoder, sctx, nv);
36211cb0ef41Sopenharmony_ci        if (rv != 0) {
36221cb0ef41Sopenharmony_ci          goto fail;
36231cb0ef41Sopenharmony_ci        }
36241cb0ef41Sopenharmony_ci
36251cb0ef41Sopenharmony_ci        break;
36261cb0ef41Sopenharmony_ci      case NGHTTP3_QPACK_RS_OPCODE_LITERAL:
36271cb0ef41Sopenharmony_ci        nghttp3_qpack_decoder_emit_literal(decoder, sctx, nv);
36281cb0ef41Sopenharmony_ci        break;
36291cb0ef41Sopenharmony_ci      default:
36301cb0ef41Sopenharmony_ci        /* Unreachable */
36311cb0ef41Sopenharmony_ci        assert(0);
36321cb0ef41Sopenharmony_ci      }
36331cb0ef41Sopenharmony_ci
36341cb0ef41Sopenharmony_ci      *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
36351cb0ef41Sopenharmony_ci
36361cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
36371cb0ef41Sopenharmony_ci      nghttp3_qpack_read_state_reset(&sctx->rstate);
36381cb0ef41Sopenharmony_ci
36391cb0ef41Sopenharmony_ci      return p - src;
36401cb0ef41Sopenharmony_ci    case NGHTTP3_QPACK_RS_STATE_BLOCKED:
36411cb0ef41Sopenharmony_ci      if (sctx->ricnt > decoder->ctx.next_absidx) {
36421cb0ef41Sopenharmony_ci        DEBUGF("qpack::decode: stream still blocked\n");
36431cb0ef41Sopenharmony_ci        *pflags |= NGHTTP3_QPACK_DECODE_FLAG_BLOCKED;
36441cb0ef41Sopenharmony_ci        return p - src;
36451cb0ef41Sopenharmony_ci      }
36461cb0ef41Sopenharmony_ci      sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
36471cb0ef41Sopenharmony_ci      nghttp3_qpack_read_state_reset(&sctx->rstate);
36481cb0ef41Sopenharmony_ci      break;
36491cb0ef41Sopenharmony_ci    }
36501cb0ef41Sopenharmony_ci  }
36511cb0ef41Sopenharmony_ci
36521cb0ef41Sopenharmony_cialmost_ok:
36531cb0ef41Sopenharmony_ci  if (fin) {
36541cb0ef41Sopenharmony_ci    if (sctx->state != NGHTTP3_QPACK_RS_STATE_OPCODE) {
36551cb0ef41Sopenharmony_ci      rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
36561cb0ef41Sopenharmony_ci      goto fail;
36571cb0ef41Sopenharmony_ci    }
36581cb0ef41Sopenharmony_ci
36591cb0ef41Sopenharmony_ci    *pflags |= NGHTTP3_QPACK_DECODE_FLAG_FINAL;
36601cb0ef41Sopenharmony_ci
36611cb0ef41Sopenharmony_ci    if (sctx->ricnt) {
36621cb0ef41Sopenharmony_ci      rv = nghttp3_qpack_decoder_write_section_ack(decoder, sctx);
36631cb0ef41Sopenharmony_ci      if (rv != 0) {
36641cb0ef41Sopenharmony_ci        goto fail;
36651cb0ef41Sopenharmony_ci      }
36661cb0ef41Sopenharmony_ci    }
36671cb0ef41Sopenharmony_ci  }
36681cb0ef41Sopenharmony_ci
36691cb0ef41Sopenharmony_ci  return p - src;
36701cb0ef41Sopenharmony_ci
36711cb0ef41Sopenharmony_cifail:
36721cb0ef41Sopenharmony_ci  decoder->ctx.bad = 1;
36731cb0ef41Sopenharmony_ci  return rv;
36741cb0ef41Sopenharmony_ci}
36751cb0ef41Sopenharmony_ci
36761cb0ef41Sopenharmony_cistatic int qpack_decoder_dbuf_overflow(nghttp3_qpack_decoder *decoder) {
36771cb0ef41Sopenharmony_ci  size_t limit = nghttp3_max(decoder->max_concurrent_streams, 100);
36781cb0ef41Sopenharmony_ci  /* 10 = nghttp3_qpack_put_varint_len((1ULL << 62) - 1, 2)) */
36791cb0ef41Sopenharmony_ci  return nghttp3_buf_len(&decoder->dbuf) > limit * 2 * 10;
36801cb0ef41Sopenharmony_ci}
36811cb0ef41Sopenharmony_ci
36821cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_write_section_ack(
36831cb0ef41Sopenharmony_ci    nghttp3_qpack_decoder *decoder, const nghttp3_qpack_stream_context *sctx) {
36841cb0ef41Sopenharmony_ci  nghttp3_buf *dbuf = &decoder->dbuf;
36851cb0ef41Sopenharmony_ci  uint8_t *p;
36861cb0ef41Sopenharmony_ci  int rv;
36871cb0ef41Sopenharmony_ci
36881cb0ef41Sopenharmony_ci  if (qpack_decoder_dbuf_overflow(decoder)) {
36891cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
36901cb0ef41Sopenharmony_ci  }
36911cb0ef41Sopenharmony_ci
36921cb0ef41Sopenharmony_ci  rv = reserve_buf_small(
36931cb0ef41Sopenharmony_ci      dbuf, nghttp3_qpack_put_varint_len((uint64_t)sctx->stream_id, 7),
36941cb0ef41Sopenharmony_ci      decoder->ctx.mem);
36951cb0ef41Sopenharmony_ci  if (rv != 0) {
36961cb0ef41Sopenharmony_ci    return rv;
36971cb0ef41Sopenharmony_ci  }
36981cb0ef41Sopenharmony_ci
36991cb0ef41Sopenharmony_ci  p = dbuf->last;
37001cb0ef41Sopenharmony_ci  *p = 0x80;
37011cb0ef41Sopenharmony_ci  dbuf->last = nghttp3_qpack_put_varint(p, (uint64_t)sctx->stream_id, 7);
37021cb0ef41Sopenharmony_ci
37031cb0ef41Sopenharmony_ci  if (decoder->written_icnt < sctx->ricnt) {
37041cb0ef41Sopenharmony_ci    decoder->written_icnt = sctx->ricnt;
37051cb0ef41Sopenharmony_ci  }
37061cb0ef41Sopenharmony_ci
37071cb0ef41Sopenharmony_ci  return 0;
37081cb0ef41Sopenharmony_ci}
37091cb0ef41Sopenharmony_ci
37101cb0ef41Sopenharmony_cisize_t
37111cb0ef41Sopenharmony_cinghttp3_qpack_decoder_get_decoder_streamlen(nghttp3_qpack_decoder *decoder) {
37121cb0ef41Sopenharmony_ci  uint64_t n;
37131cb0ef41Sopenharmony_ci  size_t len = 0;
37141cb0ef41Sopenharmony_ci
37151cb0ef41Sopenharmony_ci  if (decoder->written_icnt < decoder->ctx.next_absidx) {
37161cb0ef41Sopenharmony_ci    n = decoder->ctx.next_absidx - decoder->written_icnt;
37171cb0ef41Sopenharmony_ci    len = nghttp3_qpack_put_varint_len(n, 6);
37181cb0ef41Sopenharmony_ci  }
37191cb0ef41Sopenharmony_ci
37201cb0ef41Sopenharmony_ci  return nghttp3_buf_len(&decoder->dbuf) + len;
37211cb0ef41Sopenharmony_ci}
37221cb0ef41Sopenharmony_ci
37231cb0ef41Sopenharmony_civoid nghttp3_qpack_decoder_write_decoder(nghttp3_qpack_decoder *decoder,
37241cb0ef41Sopenharmony_ci                                         nghttp3_buf *dbuf) {
37251cb0ef41Sopenharmony_ci  uint8_t *p;
37261cb0ef41Sopenharmony_ci  uint64_t n = 0;
37271cb0ef41Sopenharmony_ci  size_t len = 0;
37281cb0ef41Sopenharmony_ci  (void)len;
37291cb0ef41Sopenharmony_ci
37301cb0ef41Sopenharmony_ci  if (decoder->written_icnt < decoder->ctx.next_absidx) {
37311cb0ef41Sopenharmony_ci    n = decoder->ctx.next_absidx - decoder->written_icnt;
37321cb0ef41Sopenharmony_ci    len = nghttp3_qpack_put_varint_len(n, 6);
37331cb0ef41Sopenharmony_ci  }
37341cb0ef41Sopenharmony_ci
37351cb0ef41Sopenharmony_ci  assert(nghttp3_buf_left(dbuf) >= nghttp3_buf_len(&decoder->dbuf) + len);
37361cb0ef41Sopenharmony_ci
37371cb0ef41Sopenharmony_ci  if (nghttp3_buf_len(&decoder->dbuf)) {
37381cb0ef41Sopenharmony_ci    dbuf->last = nghttp3_cpymem(dbuf->last, decoder->dbuf.pos,
37391cb0ef41Sopenharmony_ci                                nghttp3_buf_len(&decoder->dbuf));
37401cb0ef41Sopenharmony_ci  }
37411cb0ef41Sopenharmony_ci
37421cb0ef41Sopenharmony_ci  if (n) {
37431cb0ef41Sopenharmony_ci    p = dbuf->last;
37441cb0ef41Sopenharmony_ci    *p = 0;
37451cb0ef41Sopenharmony_ci    dbuf->last = nghttp3_qpack_put_varint(p, n, 6);
37461cb0ef41Sopenharmony_ci
37471cb0ef41Sopenharmony_ci    decoder->written_icnt = decoder->ctx.next_absidx;
37481cb0ef41Sopenharmony_ci  }
37491cb0ef41Sopenharmony_ci
37501cb0ef41Sopenharmony_ci  nghttp3_buf_reset(&decoder->dbuf);
37511cb0ef41Sopenharmony_ci}
37521cb0ef41Sopenharmony_ci
37531cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_cancel_stream(nghttp3_qpack_decoder *decoder,
37541cb0ef41Sopenharmony_ci                                        int64_t stream_id) {
37551cb0ef41Sopenharmony_ci  uint8_t *p;
37561cb0ef41Sopenharmony_ci  int rv;
37571cb0ef41Sopenharmony_ci
37581cb0ef41Sopenharmony_ci  if (qpack_decoder_dbuf_overflow(decoder)) {
37591cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
37601cb0ef41Sopenharmony_ci  }
37611cb0ef41Sopenharmony_ci
37621cb0ef41Sopenharmony_ci  rv = reserve_buf(&decoder->dbuf,
37631cb0ef41Sopenharmony_ci                   nghttp3_qpack_put_varint_len((uint64_t)stream_id, 6),
37641cb0ef41Sopenharmony_ci                   decoder->ctx.mem);
37651cb0ef41Sopenharmony_ci  if (rv != 0) {
37661cb0ef41Sopenharmony_ci    return rv;
37671cb0ef41Sopenharmony_ci  }
37681cb0ef41Sopenharmony_ci
37691cb0ef41Sopenharmony_ci  p = decoder->dbuf.last;
37701cb0ef41Sopenharmony_ci  *p = 0x40;
37711cb0ef41Sopenharmony_ci  decoder->dbuf.last = nghttp3_qpack_put_varint(p, (uint64_t)stream_id, 6);
37721cb0ef41Sopenharmony_ci
37731cb0ef41Sopenharmony_ci  return 0;
37741cb0ef41Sopenharmony_ci}
37751cb0ef41Sopenharmony_ci
37761cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_reconstruct_ricnt(nghttp3_qpack_decoder *decoder,
37771cb0ef41Sopenharmony_ci                                            uint64_t *dest, uint64_t encricnt) {
37781cb0ef41Sopenharmony_ci  uint64_t max_ents, full, max, max_wrapped, ricnt;
37791cb0ef41Sopenharmony_ci
37801cb0ef41Sopenharmony_ci  if (encricnt == 0) {
37811cb0ef41Sopenharmony_ci    *dest = 0;
37821cb0ef41Sopenharmony_ci    return 0;
37831cb0ef41Sopenharmony_ci  }
37841cb0ef41Sopenharmony_ci
37851cb0ef41Sopenharmony_ci  max_ents =
37861cb0ef41Sopenharmony_ci      decoder->ctx.hard_max_dtable_capacity / NGHTTP3_QPACK_ENTRY_OVERHEAD;
37871cb0ef41Sopenharmony_ci  full = 2 * max_ents;
37881cb0ef41Sopenharmony_ci
37891cb0ef41Sopenharmony_ci  if (encricnt > full) {
37901cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
37911cb0ef41Sopenharmony_ci  }
37921cb0ef41Sopenharmony_ci
37931cb0ef41Sopenharmony_ci  max = decoder->ctx.next_absidx + max_ents;
37941cb0ef41Sopenharmony_ci  max_wrapped = max / full * full;
37951cb0ef41Sopenharmony_ci  ricnt = max_wrapped + encricnt - 1;
37961cb0ef41Sopenharmony_ci
37971cb0ef41Sopenharmony_ci  if (ricnt > max) {
37981cb0ef41Sopenharmony_ci    if (ricnt <= full) {
37991cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38001cb0ef41Sopenharmony_ci    }
38011cb0ef41Sopenharmony_ci    ricnt -= full;
38021cb0ef41Sopenharmony_ci  }
38031cb0ef41Sopenharmony_ci
38041cb0ef41Sopenharmony_ci  if (ricnt == 0) {
38051cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38061cb0ef41Sopenharmony_ci  }
38071cb0ef41Sopenharmony_ci
38081cb0ef41Sopenharmony_ci  *dest = ricnt;
38091cb0ef41Sopenharmony_ci
38101cb0ef41Sopenharmony_ci  return 0;
38111cb0ef41Sopenharmony_ci}
38121cb0ef41Sopenharmony_ci
38131cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_rel2abs(nghttp3_qpack_decoder *decoder,
38141cb0ef41Sopenharmony_ci                                  nghttp3_qpack_read_state *rstate) {
38151cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: dynamic=%d relidx=%" PRIu64 " icnt=%" PRIu64 "\n",
38161cb0ef41Sopenharmony_ci         rstate->dynamic, rstate->left, decoder->ctx.next_absidx);
38171cb0ef41Sopenharmony_ci
38181cb0ef41Sopenharmony_ci  if (rstate->dynamic) {
38191cb0ef41Sopenharmony_ci    if (decoder->ctx.next_absidx < rstate->left + 1) {
38201cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
38211cb0ef41Sopenharmony_ci    }
38221cb0ef41Sopenharmony_ci    rstate->absidx = decoder->ctx.next_absidx - rstate->left - 1;
38231cb0ef41Sopenharmony_ci  } else {
38241cb0ef41Sopenharmony_ci    rstate->absidx = rstate->left;
38251cb0ef41Sopenharmony_ci  }
38261cb0ef41Sopenharmony_ci  if (qpack_decoder_validate_index(decoder, rstate) != 0) {
38271cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
38281cb0ef41Sopenharmony_ci  }
38291cb0ef41Sopenharmony_ci  return 0;
38301cb0ef41Sopenharmony_ci}
38311cb0ef41Sopenharmony_ci
38321cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_brel2abs(nghttp3_qpack_decoder *decoder,
38331cb0ef41Sopenharmony_ci                                   nghttp3_qpack_stream_context *sctx) {
38341cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state *rstate = &sctx->rstate;
38351cb0ef41Sopenharmony_ci
38361cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: dynamic=%d relidx=%" PRIu64 " base=%" PRIu64
38371cb0ef41Sopenharmony_ci         " icnt=%" PRIu64 "\n",
38381cb0ef41Sopenharmony_ci         rstate->dynamic, rstate->left, sctx->base, decoder->ctx.next_absidx);
38391cb0ef41Sopenharmony_ci
38401cb0ef41Sopenharmony_ci  if (rstate->dynamic) {
38411cb0ef41Sopenharmony_ci    if (sctx->base < rstate->left + 1) {
38421cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38431cb0ef41Sopenharmony_ci    }
38441cb0ef41Sopenharmony_ci    rstate->absidx = sctx->base - rstate->left - 1;
38451cb0ef41Sopenharmony_ci
38461cb0ef41Sopenharmony_ci    if (rstate->absidx >= sctx->ricnt) {
38471cb0ef41Sopenharmony_ci      return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38481cb0ef41Sopenharmony_ci    }
38491cb0ef41Sopenharmony_ci  } else {
38501cb0ef41Sopenharmony_ci    rstate->absidx = rstate->left;
38511cb0ef41Sopenharmony_ci  }
38521cb0ef41Sopenharmony_ci
38531cb0ef41Sopenharmony_ci  if (qpack_decoder_validate_index(decoder, rstate) != 0) {
38541cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38551cb0ef41Sopenharmony_ci  }
38561cb0ef41Sopenharmony_ci  return 0;
38571cb0ef41Sopenharmony_ci}
38581cb0ef41Sopenharmony_ci
38591cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_pbrel2abs(nghttp3_qpack_decoder *decoder,
38601cb0ef41Sopenharmony_ci                                    nghttp3_qpack_stream_context *sctx) {
38611cb0ef41Sopenharmony_ci  nghttp3_qpack_read_state *rstate = &sctx->rstate;
38621cb0ef41Sopenharmony_ci
38631cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: pbidx=%" PRIu64 " base=%" PRIu64 " icnt=%" PRIu64 "\n",
38641cb0ef41Sopenharmony_ci         rstate->left, sctx->base, decoder->ctx.next_absidx);
38651cb0ef41Sopenharmony_ci
38661cb0ef41Sopenharmony_ci  assert(rstate->dynamic);
38671cb0ef41Sopenharmony_ci
38681cb0ef41Sopenharmony_ci  rstate->absidx = rstate->left + sctx->base;
38691cb0ef41Sopenharmony_ci
38701cb0ef41Sopenharmony_ci  if (rstate->absidx >= sctx->ricnt) {
38711cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38721cb0ef41Sopenharmony_ci  }
38731cb0ef41Sopenharmony_ci
38741cb0ef41Sopenharmony_ci  if (qpack_decoder_validate_index(decoder, rstate) != 0) {
38751cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
38761cb0ef41Sopenharmony_ci  }
38771cb0ef41Sopenharmony_ci  return 0;
38781cb0ef41Sopenharmony_ci}
38791cb0ef41Sopenharmony_ci
38801cb0ef41Sopenharmony_cistatic void
38811cb0ef41Sopenharmony_ciqpack_decoder_emit_static_indexed(nghttp3_qpack_decoder *decoder,
38821cb0ef41Sopenharmony_ci                                  nghttp3_qpack_stream_context *sctx,
38831cb0ef41Sopenharmony_ci                                  nghttp3_qpack_nv *nv) {
38841cb0ef41Sopenharmony_ci  const nghttp3_qpack_static_header *shd = &stable[sctx->rstate.absidx];
38851cb0ef41Sopenharmony_ci  (void)decoder;
38861cb0ef41Sopenharmony_ci
38871cb0ef41Sopenharmony_ci  nv->name = (nghttp3_rcbuf *)&shd->name;
38881cb0ef41Sopenharmony_ci  nv->value = (nghttp3_rcbuf *)&shd->value;
38891cb0ef41Sopenharmony_ci  nv->token = shd->token;
38901cb0ef41Sopenharmony_ci  nv->flags = NGHTTP3_NV_FLAG_NONE;
38911cb0ef41Sopenharmony_ci}
38921cb0ef41Sopenharmony_ci
38931cb0ef41Sopenharmony_cistatic void
38941cb0ef41Sopenharmony_ciqpack_decoder_emit_dynamic_indexed(nghttp3_qpack_decoder *decoder,
38951cb0ef41Sopenharmony_ci                                   nghttp3_qpack_stream_context *sctx,
38961cb0ef41Sopenharmony_ci                                   nghttp3_qpack_nv *nv) {
38971cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent =
38981cb0ef41Sopenharmony_ci      nghttp3_qpack_context_dtable_get(&decoder->ctx, sctx->rstate.absidx);
38991cb0ef41Sopenharmony_ci
39001cb0ef41Sopenharmony_ci  *nv = ent->nv;
39011cb0ef41Sopenharmony_ci
39021cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(nv->name);
39031cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(nv->value);
39041cb0ef41Sopenharmony_ci}
39051cb0ef41Sopenharmony_ci
39061cb0ef41Sopenharmony_civoid nghttp3_qpack_decoder_emit_indexed(nghttp3_qpack_decoder *decoder,
39071cb0ef41Sopenharmony_ci                                        nghttp3_qpack_stream_context *sctx,
39081cb0ef41Sopenharmony_ci                                        nghttp3_qpack_nv *nv) {
39091cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: Indexed (%s) absidx=%" PRIu64 "\n",
39101cb0ef41Sopenharmony_ci         sctx->rstate.dynamic ? "dynamic" : "static", sctx->rstate.absidx);
39111cb0ef41Sopenharmony_ci
39121cb0ef41Sopenharmony_ci  if (sctx->rstate.dynamic) {
39131cb0ef41Sopenharmony_ci    qpack_decoder_emit_dynamic_indexed(decoder, sctx, nv);
39141cb0ef41Sopenharmony_ci  } else {
39151cb0ef41Sopenharmony_ci    qpack_decoder_emit_static_indexed(decoder, sctx, nv);
39161cb0ef41Sopenharmony_ci  }
39171cb0ef41Sopenharmony_ci}
39181cb0ef41Sopenharmony_ci
39191cb0ef41Sopenharmony_cistatic void
39201cb0ef41Sopenharmony_ciqpack_decoder_emit_static_indexed_name(nghttp3_qpack_decoder *decoder,
39211cb0ef41Sopenharmony_ci                                       nghttp3_qpack_stream_context *sctx,
39221cb0ef41Sopenharmony_ci                                       nghttp3_qpack_nv *nv) {
39231cb0ef41Sopenharmony_ci  const nghttp3_qpack_static_header *shd = &stable[sctx->rstate.absidx];
39241cb0ef41Sopenharmony_ci  (void)decoder;
39251cb0ef41Sopenharmony_ci
39261cb0ef41Sopenharmony_ci  nv->name = (nghttp3_rcbuf *)&shd->name;
39271cb0ef41Sopenharmony_ci  nv->value = sctx->rstate.value;
39281cb0ef41Sopenharmony_ci  nv->token = shd->token;
39291cb0ef41Sopenharmony_ci  nv->flags =
39301cb0ef41Sopenharmony_ci      sctx->rstate.never ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE;
39311cb0ef41Sopenharmony_ci
39321cb0ef41Sopenharmony_ci  sctx->rstate.value = NULL;
39331cb0ef41Sopenharmony_ci}
39341cb0ef41Sopenharmony_ci
39351cb0ef41Sopenharmony_cistatic int
39361cb0ef41Sopenharmony_ciqpack_decoder_emit_dynamic_indexed_name(nghttp3_qpack_decoder *decoder,
39371cb0ef41Sopenharmony_ci                                        nghttp3_qpack_stream_context *sctx,
39381cb0ef41Sopenharmony_ci                                        nghttp3_qpack_nv *nv) {
39391cb0ef41Sopenharmony_ci  nghttp3_qpack_entry *ent;
39401cb0ef41Sopenharmony_ci
39411cb0ef41Sopenharmony_ci  /* A broken encoder might change dtable capacity while processing
39421cb0ef41Sopenharmony_ci     request stream instruction.  Check the absidx again. */
39431cb0ef41Sopenharmony_ci  if (qpack_decoder_validate_index(decoder, &sctx->rstate) != 0) {
39441cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
39451cb0ef41Sopenharmony_ci  }
39461cb0ef41Sopenharmony_ci
39471cb0ef41Sopenharmony_ci  ent = nghttp3_qpack_context_dtable_get(&decoder->ctx, sctx->rstate.absidx);
39481cb0ef41Sopenharmony_ci
39491cb0ef41Sopenharmony_ci  nv->name = ent->nv.name;
39501cb0ef41Sopenharmony_ci  nv->value = sctx->rstate.value;
39511cb0ef41Sopenharmony_ci  nv->token = ent->nv.token;
39521cb0ef41Sopenharmony_ci  nv->flags =
39531cb0ef41Sopenharmony_ci      sctx->rstate.never ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE;
39541cb0ef41Sopenharmony_ci
39551cb0ef41Sopenharmony_ci  nghttp3_rcbuf_incref(nv->name);
39561cb0ef41Sopenharmony_ci
39571cb0ef41Sopenharmony_ci  sctx->rstate.value = NULL;
39581cb0ef41Sopenharmony_ci
39591cb0ef41Sopenharmony_ci  return 0;
39601cb0ef41Sopenharmony_ci}
39611cb0ef41Sopenharmony_ci
39621cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_emit_indexed_name(nghttp3_qpack_decoder *decoder,
39631cb0ef41Sopenharmony_ci                                            nghttp3_qpack_stream_context *sctx,
39641cb0ef41Sopenharmony_ci                                            nghttp3_qpack_nv *nv) {
39651cb0ef41Sopenharmony_ci  (void)decoder;
39661cb0ef41Sopenharmony_ci
39671cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: Indexed name (%s) absidx=%" PRIu64 " value=%*s\n",
39681cb0ef41Sopenharmony_ci         sctx->rstate.dynamic ? "dynamic" : "static", sctx->rstate.absidx,
39691cb0ef41Sopenharmony_ci         (int)sctx->rstate.value->len, sctx->rstate.value->base);
39701cb0ef41Sopenharmony_ci
39711cb0ef41Sopenharmony_ci  if (sctx->rstate.dynamic) {
39721cb0ef41Sopenharmony_ci    return qpack_decoder_emit_dynamic_indexed_name(decoder, sctx, nv);
39731cb0ef41Sopenharmony_ci  }
39741cb0ef41Sopenharmony_ci
39751cb0ef41Sopenharmony_ci  qpack_decoder_emit_static_indexed_name(decoder, sctx, nv);
39761cb0ef41Sopenharmony_ci
39771cb0ef41Sopenharmony_ci  return 0;
39781cb0ef41Sopenharmony_ci}
39791cb0ef41Sopenharmony_ci
39801cb0ef41Sopenharmony_civoid nghttp3_qpack_decoder_emit_literal(nghttp3_qpack_decoder *decoder,
39811cb0ef41Sopenharmony_ci                                        nghttp3_qpack_stream_context *sctx,
39821cb0ef41Sopenharmony_ci                                        nghttp3_qpack_nv *nv) {
39831cb0ef41Sopenharmony_ci  (void)decoder;
39841cb0ef41Sopenharmony_ci
39851cb0ef41Sopenharmony_ci  DEBUGF("qpack::decode: Emit literal name=%*s value=%*s\n",
39861cb0ef41Sopenharmony_ci         (int)sctx->rstate.name->len, sctx->rstate.name->base,
39871cb0ef41Sopenharmony_ci         (int)sctx->rstate.value->len, sctx->rstate.value->base);
39881cb0ef41Sopenharmony_ci
39891cb0ef41Sopenharmony_ci  nv->name = sctx->rstate.name;
39901cb0ef41Sopenharmony_ci  nv->value = sctx->rstate.value;
39911cb0ef41Sopenharmony_ci  nv->token = qpack_lookup_token(nv->name->base, nv->name->len);
39921cb0ef41Sopenharmony_ci  nv->flags =
39931cb0ef41Sopenharmony_ci      sctx->rstate.never ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE;
39941cb0ef41Sopenharmony_ci
39951cb0ef41Sopenharmony_ci  sctx->rstate.name = NULL;
39961cb0ef41Sopenharmony_ci  sctx->rstate.value = NULL;
39971cb0ef41Sopenharmony_ci}
39981cb0ef41Sopenharmony_ci
39991cb0ef41Sopenharmony_ciint nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
40001cb0ef41Sopenharmony_ci                              size_t hard_max_dtable_capacity,
40011cb0ef41Sopenharmony_ci                              const nghttp3_mem *mem) {
40021cb0ef41Sopenharmony_ci  int rv;
40031cb0ef41Sopenharmony_ci  nghttp3_qpack_encoder *p;
40041cb0ef41Sopenharmony_ci
40051cb0ef41Sopenharmony_ci  p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_encoder));
40061cb0ef41Sopenharmony_ci  if (p == NULL) {
40071cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_NOMEM;
40081cb0ef41Sopenharmony_ci  }
40091cb0ef41Sopenharmony_ci
40101cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, mem);
40111cb0ef41Sopenharmony_ci  if (rv != 0) {
40121cb0ef41Sopenharmony_ci    return rv;
40131cb0ef41Sopenharmony_ci  }
40141cb0ef41Sopenharmony_ci
40151cb0ef41Sopenharmony_ci  *pencoder = p;
40161cb0ef41Sopenharmony_ci
40171cb0ef41Sopenharmony_ci  return 0;
40181cb0ef41Sopenharmony_ci}
40191cb0ef41Sopenharmony_ci
40201cb0ef41Sopenharmony_civoid nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder) {
40211cb0ef41Sopenharmony_ci  const nghttp3_mem *mem;
40221cb0ef41Sopenharmony_ci
40231cb0ef41Sopenharmony_ci  if (encoder == NULL) {
40241cb0ef41Sopenharmony_ci    return;
40251cb0ef41Sopenharmony_ci  }
40261cb0ef41Sopenharmony_ci
40271cb0ef41Sopenharmony_ci  mem = encoder->ctx.mem;
40281cb0ef41Sopenharmony_ci
40291cb0ef41Sopenharmony_ci  nghttp3_qpack_encoder_free(encoder);
40301cb0ef41Sopenharmony_ci  nghttp3_mem_free(mem, encoder);
40311cb0ef41Sopenharmony_ci}
40321cb0ef41Sopenharmony_ci
40331cb0ef41Sopenharmony_ciint nghttp3_qpack_stream_context_new(nghttp3_qpack_stream_context **psctx,
40341cb0ef41Sopenharmony_ci                                     int64_t stream_id,
40351cb0ef41Sopenharmony_ci                                     const nghttp3_mem *mem) {
40361cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_context *p;
40371cb0ef41Sopenharmony_ci
40381cb0ef41Sopenharmony_ci  p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream_context));
40391cb0ef41Sopenharmony_ci  if (p == NULL) {
40401cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_NOMEM;
40411cb0ef41Sopenharmony_ci  }
40421cb0ef41Sopenharmony_ci
40431cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_context_init(p, stream_id, mem);
40441cb0ef41Sopenharmony_ci
40451cb0ef41Sopenharmony_ci  *psctx = p;
40461cb0ef41Sopenharmony_ci
40471cb0ef41Sopenharmony_ci  return 0;
40481cb0ef41Sopenharmony_ci}
40491cb0ef41Sopenharmony_ci
40501cb0ef41Sopenharmony_civoid nghttp3_qpack_stream_context_del(nghttp3_qpack_stream_context *sctx) {
40511cb0ef41Sopenharmony_ci  const nghttp3_mem *mem;
40521cb0ef41Sopenharmony_ci
40531cb0ef41Sopenharmony_ci  if (sctx == NULL) {
40541cb0ef41Sopenharmony_ci    return;
40551cb0ef41Sopenharmony_ci  }
40561cb0ef41Sopenharmony_ci
40571cb0ef41Sopenharmony_ci  mem = sctx->mem;
40581cb0ef41Sopenharmony_ci
40591cb0ef41Sopenharmony_ci  nghttp3_qpack_stream_context_free(sctx);
40601cb0ef41Sopenharmony_ci  nghttp3_mem_free(mem, sctx);
40611cb0ef41Sopenharmony_ci}
40621cb0ef41Sopenharmony_ci
40631cb0ef41Sopenharmony_ciint nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
40641cb0ef41Sopenharmony_ci                              size_t hard_max_dtable_capacity,
40651cb0ef41Sopenharmony_ci                              size_t max_blocked_streams,
40661cb0ef41Sopenharmony_ci                              const nghttp3_mem *mem) {
40671cb0ef41Sopenharmony_ci  int rv;
40681cb0ef41Sopenharmony_ci  nghttp3_qpack_decoder *p;
40691cb0ef41Sopenharmony_ci
40701cb0ef41Sopenharmony_ci  p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_decoder));
40711cb0ef41Sopenharmony_ci  if (p == NULL) {
40721cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_NOMEM;
40731cb0ef41Sopenharmony_ci  }
40741cb0ef41Sopenharmony_ci
40751cb0ef41Sopenharmony_ci  rv = nghttp3_qpack_decoder_init(p, hard_max_dtable_capacity,
40761cb0ef41Sopenharmony_ci                                  max_blocked_streams, mem);
40771cb0ef41Sopenharmony_ci  if (rv != 0) {
40781cb0ef41Sopenharmony_ci    return rv;
40791cb0ef41Sopenharmony_ci  }
40801cb0ef41Sopenharmony_ci
40811cb0ef41Sopenharmony_ci  *pdecoder = p;
40821cb0ef41Sopenharmony_ci
40831cb0ef41Sopenharmony_ci  return 0;
40841cb0ef41Sopenharmony_ci}
40851cb0ef41Sopenharmony_ci
40861cb0ef41Sopenharmony_civoid nghttp3_qpack_decoder_del(nghttp3_qpack_decoder *decoder) {
40871cb0ef41Sopenharmony_ci  const nghttp3_mem *mem;
40881cb0ef41Sopenharmony_ci
40891cb0ef41Sopenharmony_ci  if (decoder == NULL) {
40901cb0ef41Sopenharmony_ci    return;
40911cb0ef41Sopenharmony_ci  }
40921cb0ef41Sopenharmony_ci
40931cb0ef41Sopenharmony_ci  mem = decoder->ctx.mem;
40941cb0ef41Sopenharmony_ci
40951cb0ef41Sopenharmony_ci  nghttp3_qpack_decoder_free(decoder);
40961cb0ef41Sopenharmony_ci  nghttp3_mem_free(mem, decoder);
40971cb0ef41Sopenharmony_ci}
40981cb0ef41Sopenharmony_ci
40991cb0ef41Sopenharmony_ciuint64_t nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder) {
41001cb0ef41Sopenharmony_ci  return decoder->ctx.next_absidx;
41011cb0ef41Sopenharmony_ci}
4102