xref: /third_party/libwebsockets/lib/roles/h2/hpack.c (revision d4afb5ce)
1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci */
24d4afb5ceSopenharmony_ci
25d4afb5ceSopenharmony_ci#include "private-lib-core.h"
26d4afb5ceSopenharmony_ci
27d4afb5ceSopenharmony_ci/*
28d4afb5ceSopenharmony_ci * Official static header table for HPACK
29d4afb5ceSopenharmony_ci *        +-------+-----------------------------+---------------+
30d4afb5ceSopenharmony_ci          | 1     | :authority                  |               |
31d4afb5ceSopenharmony_ci          | 2     | :method                     | GET           |
32d4afb5ceSopenharmony_ci          | 3     | :method                     | POST          |
33d4afb5ceSopenharmony_ci          | 4     | :path                       | /             |
34d4afb5ceSopenharmony_ci          | 5     | :path                       | /index.html   |
35d4afb5ceSopenharmony_ci          | 6     | :scheme                     | http          |
36d4afb5ceSopenharmony_ci          | 7     | :scheme                     | https         |
37d4afb5ceSopenharmony_ci          | 8     | :status                     | 200           |
38d4afb5ceSopenharmony_ci          | 9     | :status                     | 204           |
39d4afb5ceSopenharmony_ci          | 10    | :status                     | 206           |
40d4afb5ceSopenharmony_ci          | 11    | :status                     | 304           |
41d4afb5ceSopenharmony_ci          | 12    | :status                     | 400           |
42d4afb5ceSopenharmony_ci          | 13    | :status                     | 404           |
43d4afb5ceSopenharmony_ci          | 14    | :status                     | 500           |
44d4afb5ceSopenharmony_ci          | 15    | accept-charset              |               |
45d4afb5ceSopenharmony_ci          | 16    | accept-encoding             | gzip, deflate |
46d4afb5ceSopenharmony_ci          | 17    | accept-language             |               |
47d4afb5ceSopenharmony_ci          | 18    | accept-ranges               |               |
48d4afb5ceSopenharmony_ci          | 19    | accept                      |               |
49d4afb5ceSopenharmony_ci          | 20    | access-control-allow-origin |               |
50d4afb5ceSopenharmony_ci          | 21    | age                         |               |
51d4afb5ceSopenharmony_ci          | 22    | allow                       |               |
52d4afb5ceSopenharmony_ci          | 23    | authorization               |               |
53d4afb5ceSopenharmony_ci          | 24    | cache-control               |               |
54d4afb5ceSopenharmony_ci          | 25    | content-disposition         |               |
55d4afb5ceSopenharmony_ci          | 26    | content-encoding            |               |
56d4afb5ceSopenharmony_ci          | 27    | content-language            |               |
57d4afb5ceSopenharmony_ci          | 28    | content-length              |               |
58d4afb5ceSopenharmony_ci          | 29    | content-location            |               |
59d4afb5ceSopenharmony_ci          | 30    | content-range               |               |
60d4afb5ceSopenharmony_ci          | 31    | content-type                |               |
61d4afb5ceSopenharmony_ci          | 32    | cookie                      |               |
62d4afb5ceSopenharmony_ci          | 33    | date                        |               |
63d4afb5ceSopenharmony_ci          | 34    | etag                        |               |
64d4afb5ceSopenharmony_ci          | 35    | expect                      |               |
65d4afb5ceSopenharmony_ci          | 36    | expires                     |               |
66d4afb5ceSopenharmony_ci          | 37    | from                        |               |
67d4afb5ceSopenharmony_ci          | 38    | host                        |               |
68d4afb5ceSopenharmony_ci          | 39    | if-match                    |               |
69d4afb5ceSopenharmony_ci          | 40    | if-modified-since           |               |
70d4afb5ceSopenharmony_ci          | 41    | if-none-match               |               |
71d4afb5ceSopenharmony_ci          | 42    | if-range                    |               |
72d4afb5ceSopenharmony_ci          | 43    | if-unmodified-since         |               |
73d4afb5ceSopenharmony_ci          | 44    | last-modified               |               |
74d4afb5ceSopenharmony_ci          | 45    | link                        |               |
75d4afb5ceSopenharmony_ci          | 46    | location                    |               |
76d4afb5ceSopenharmony_ci          | 47    | max-forwards                |               |
77d4afb5ceSopenharmony_ci          | 48    | proxy-authenticate          |               |
78d4afb5ceSopenharmony_ci          | 49    | proxy-authorization         |               |
79d4afb5ceSopenharmony_ci          | 50    | range                       |               |
80d4afb5ceSopenharmony_ci          | 51    | referer                     |               |
81d4afb5ceSopenharmony_ci          | 52    | refresh                     |               |
82d4afb5ceSopenharmony_ci          | 53    | retry-after                 |               |
83d4afb5ceSopenharmony_ci          | 54    | server                      |               |
84d4afb5ceSopenharmony_ci          | 55    | set-cookie                  |               |
85d4afb5ceSopenharmony_ci          | 56    | strict-transport-security   |               |
86d4afb5ceSopenharmony_ci          | 57    | transfer-encoding           |               |
87d4afb5ceSopenharmony_ci          | 58    | user-agent                  |               |
88d4afb5ceSopenharmony_ci          | 59    | vary                        |               |
89d4afb5ceSopenharmony_ci          | 60    | via                         |               |
90d4afb5ceSopenharmony_ci          | 61    | www-authenticate            |               |
91d4afb5ceSopenharmony_ci          +-------+-----------------------------+---------------+
92d4afb5ceSopenharmony_ci*/
93d4afb5ceSopenharmony_ci
94d4afb5ceSopenharmony_cistatic const uint8_t static_hdr_len[62] = {
95d4afb5ceSopenharmony_ci		0, /* starts at 1 */
96d4afb5ceSopenharmony_ci		10,  7,  7,  5,  5,    7,  7,  7,  7,  7,
97d4afb5ceSopenharmony_ci		 7,  7,  7,  7, 14,   15, 15, 13,  6, 27,
98d4afb5ceSopenharmony_ci		 3,  5, 13, 13, 19,   16, 16, 14, 16, 13,
99d4afb5ceSopenharmony_ci		12,  6,  4,  4,  6,    7,  4,  4,  8, 17,
100d4afb5ceSopenharmony_ci		13,  8, 19, 13,  4,    8, 12, 18, 19,  5,
101d4afb5ceSopenharmony_ci		 7,  7, 11,  6, 10,   25, 17, 10,  4,  3,
102d4afb5ceSopenharmony_ci		16
103d4afb5ceSopenharmony_ci};
104d4afb5ceSopenharmony_ci
105d4afb5ceSopenharmony_cistatic const unsigned char static_token[] = {
106d4afb5ceSopenharmony_ci	0,
107d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_AUTHORITY,
108d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_METHOD,
109d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_METHOD,
110d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_PATH,
111d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_PATH,
112d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_SCHEME,
113d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_SCHEME,
114d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
115d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
116d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
117d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
118d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
119d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
120d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COLON_STATUS,
121d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ACCEPT_CHARSET,
122d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ACCEPT_ENCODING,
123d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
124d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ACCEPT_RANGES,
125d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ACCEPT,
126d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
127d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_AGE,
128d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ALLOW,
129d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_AUTHORIZATION,
130d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CACHE_CONTROL,
131d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
132d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_ENCODING,
133d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
134d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_LENGTH,
135d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_LOCATION,
136d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_RANGE,
137d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_CONTENT_TYPE,
138d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_COOKIE,
139d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_DATE,
140d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_ETAG,
141d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_EXPECT,
142d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_EXPIRES,
143d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_FROM,
144d4afb5ceSopenharmony_ci	WSI_TOKEN_HOST,
145d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_IF_MATCH,
146d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
147d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_IF_NONE_MATCH,
148d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_IF_RANGE,
149d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
150d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_LAST_MODIFIED,
151d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_LINK,
152d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_LOCATION,
153d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_MAX_FORWARDS,
154d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
155d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
156d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_RANGE,
157d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_REFERER,
158d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_REFRESH,
159d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_RETRY_AFTER,
160d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_SERVER,
161d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_SET_COOKIE,
162d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
163d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_TRANSFER_ENCODING,
164d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_USER_AGENT,
165d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_VARY,
166d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_VIA,
167d4afb5ceSopenharmony_ci	WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
168d4afb5ceSopenharmony_ci};
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci/* some of the entries imply values as well as header names */
171d4afb5ceSopenharmony_ci
172d4afb5ceSopenharmony_cistatic const char * const http2_canned[] = {
173d4afb5ceSopenharmony_ci	"",
174d4afb5ceSopenharmony_ci	"",
175d4afb5ceSopenharmony_ci	"GET",
176d4afb5ceSopenharmony_ci	"POST",
177d4afb5ceSopenharmony_ci	"/",
178d4afb5ceSopenharmony_ci	"/index.html",
179d4afb5ceSopenharmony_ci	"http",
180d4afb5ceSopenharmony_ci	"https",
181d4afb5ceSopenharmony_ci	"200",
182d4afb5ceSopenharmony_ci	"204",
183d4afb5ceSopenharmony_ci	"206",
184d4afb5ceSopenharmony_ci	"304",
185d4afb5ceSopenharmony_ci	"400",
186d4afb5ceSopenharmony_ci	"404",
187d4afb5ceSopenharmony_ci	"500",
188d4afb5ceSopenharmony_ci	"",
189d4afb5ceSopenharmony_ci	"gzip, deflate"
190d4afb5ceSopenharmony_ci};
191d4afb5ceSopenharmony_ci
192d4afb5ceSopenharmony_ci/* see minihuf.c */
193d4afb5ceSopenharmony_ci
194d4afb5ceSopenharmony_ci#include "huftable.h"
195d4afb5ceSopenharmony_ci
196d4afb5ceSopenharmony_cistatic int huftable_decode(int pos, char c)
197d4afb5ceSopenharmony_ci{
198d4afb5ceSopenharmony_ci	int q = pos + !!c;
199d4afb5ceSopenharmony_ci
200d4afb5ceSopenharmony_ci	if (lextable_terms[q >> 3] & (1 << (q & 7))) /* terminal */
201d4afb5ceSopenharmony_ci		return lextable[q] | 0x8000;
202d4afb5ceSopenharmony_ci
203d4afb5ceSopenharmony_ci	return pos + (lextable[q] << 1);
204d4afb5ceSopenharmony_ci}
205d4afb5ceSopenharmony_ci
206d4afb5ceSopenharmony_cistatic int lws_frag_start(struct lws *wsi, int hdr_token_idx)
207d4afb5ceSopenharmony_ci{
208d4afb5ceSopenharmony_ci	struct allocated_headers *ah = wsi->http.ah;
209d4afb5ceSopenharmony_ci
210d4afb5ceSopenharmony_ci	if (!ah) {
211d4afb5ceSopenharmony_ci		lwsl_notice("%s: no ah\n", __func__);
212d4afb5ceSopenharmony_ci		return 1;
213d4afb5ceSopenharmony_ci	}
214d4afb5ceSopenharmony_ci
215d4afb5ceSopenharmony_ci	ah->hdr_token_idx = -1;
216d4afb5ceSopenharmony_ci
217d4afb5ceSopenharmony_ci	lwsl_header("%s: token %d ah->pos = %d, ah->nfrag = %d\n",
218d4afb5ceSopenharmony_ci		   __func__, hdr_token_idx, ah->pos, ah->nfrag);
219d4afb5ceSopenharmony_ci
220d4afb5ceSopenharmony_ci	if (!hdr_token_idx) {
221d4afb5ceSopenharmony_ci		lwsl_err("%s: zero hdr_token_idx\n", __func__);
222d4afb5ceSopenharmony_ci		return 1;
223d4afb5ceSopenharmony_ci	}
224d4afb5ceSopenharmony_ci
225d4afb5ceSopenharmony_ci	if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frag_index)) {
226d4afb5ceSopenharmony_ci		lwsl_err("%s: frag index %d too big\n", __func__, ah->nfrag);
227d4afb5ceSopenharmony_ci		return 1;
228d4afb5ceSopenharmony_ci	}
229d4afb5ceSopenharmony_ci
230d4afb5ceSopenharmony_ci	if ((hdr_token_idx == WSI_TOKEN_HTTP_COLON_AUTHORITY ||
231d4afb5ceSopenharmony_ci	     hdr_token_idx == WSI_TOKEN_HTTP_COLON_METHOD ||
232d4afb5ceSopenharmony_ci	     hdr_token_idx == WSI_TOKEN_HTTP_COLON_PATH ||
233d4afb5ceSopenharmony_ci	     hdr_token_idx == WSI_TOKEN_COLON_PROTOCOL ||
234d4afb5ceSopenharmony_ci	     hdr_token_idx == WSI_TOKEN_HTTP_COLON_SCHEME) &&
235d4afb5ceSopenharmony_ci	     ah->frag_index[hdr_token_idx]) {
236d4afb5ceSopenharmony_ci		if (!(ah->frags[ah->frag_index[hdr_token_idx]].flags & 1)) {
237d4afb5ceSopenharmony_ci			lws_h2_goaway(lws_get_network_wsi(wsi),
238d4afb5ceSopenharmony_ci				      H2_ERR_PROTOCOL_ERROR,
239d4afb5ceSopenharmony_ci				      "Duplicated pseudoheader");
240d4afb5ceSopenharmony_ci			return 1;
241d4afb5ceSopenharmony_ci		}
242d4afb5ceSopenharmony_ci	}
243d4afb5ceSopenharmony_ci
244d4afb5ceSopenharmony_ci	if (ah->nfrag == 0)
245d4afb5ceSopenharmony_ci		ah->nfrag = 1;
246d4afb5ceSopenharmony_ci
247d4afb5ceSopenharmony_ci	ah->frags[ah->nfrag].offset = ah->pos;
248d4afb5ceSopenharmony_ci	ah->frags[ah->nfrag].len = 0;
249d4afb5ceSopenharmony_ci	ah->frags[ah->nfrag].nfrag = 0;
250d4afb5ceSopenharmony_ci	ah->frags[ah->nfrag].flags = 2; /* we had reason to set it */
251d4afb5ceSopenharmony_ci
252d4afb5ceSopenharmony_ci	ah->hdr_token_idx = hdr_token_idx;
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_ci	/*
255d4afb5ceSopenharmony_ci	 * Okay, but we could be, eg, the second or subsequent cookie: header
256d4afb5ceSopenharmony_ci	 */
257d4afb5ceSopenharmony_ci
258d4afb5ceSopenharmony_ci	if (ah->frag_index[hdr_token_idx]) {
259d4afb5ceSopenharmony_ci		int n;
260d4afb5ceSopenharmony_ci
261d4afb5ceSopenharmony_ci		/* find the last fragment for this header... */
262d4afb5ceSopenharmony_ci		n = ah->frag_index[hdr_token_idx];
263d4afb5ceSopenharmony_ci		while (ah->frags[n].nfrag)
264d4afb5ceSopenharmony_ci			n = ah->frags[n].nfrag;
265d4afb5ceSopenharmony_ci		/* and point it to continue in our continuation fragment */
266d4afb5ceSopenharmony_ci		ah->frags[n].nfrag = ah->nfrag;
267d4afb5ceSopenharmony_ci	} else
268d4afb5ceSopenharmony_ci		ah->frag_index[hdr_token_idx] = ah->nfrag;
269d4afb5ceSopenharmony_ci
270d4afb5ceSopenharmony_ci	return 0;
271d4afb5ceSopenharmony_ci}
272d4afb5ceSopenharmony_ci
273d4afb5ceSopenharmony_cistatic int lws_frag_append(struct lws *wsi, unsigned char c)
274d4afb5ceSopenharmony_ci{
275d4afb5ceSopenharmony_ci	struct allocated_headers *ah = wsi->http.ah;
276d4afb5ceSopenharmony_ci
277d4afb5ceSopenharmony_ci	ah->data[ah->pos++] = (char)c;
278d4afb5ceSopenharmony_ci	ah->frags[ah->nfrag].len++;
279d4afb5ceSopenharmony_ci
280d4afb5ceSopenharmony_ci	return (unsigned int)ah->pos >= wsi->a.context->max_http_header_data;
281d4afb5ceSopenharmony_ci}
282d4afb5ceSopenharmony_ci
283d4afb5ceSopenharmony_cistatic int lws_frag_end(struct lws *wsi)
284d4afb5ceSopenharmony_ci{
285d4afb5ceSopenharmony_ci	lwsl_header("%s\n", __func__);
286d4afb5ceSopenharmony_ci	if (lws_frag_append(wsi, 0))
287d4afb5ceSopenharmony_ci		return 1;
288d4afb5ceSopenharmony_ci
289d4afb5ceSopenharmony_ci	/* don't account for the terminating NUL in the logical length */
290d4afb5ceSopenharmony_ci	wsi->http.ah->frags[wsi->http.ah->nfrag].len--;
291d4afb5ceSopenharmony_ci
292d4afb5ceSopenharmony_ci	wsi->http.ah->nfrag++;
293d4afb5ceSopenharmony_ci	return 0;
294d4afb5ceSopenharmony_ci}
295d4afb5ceSopenharmony_ci
296d4afb5ceSopenharmony_ciint
297d4afb5ceSopenharmony_cilws_hdr_extant(struct lws *wsi, enum lws_token_indexes h)
298d4afb5ceSopenharmony_ci{
299d4afb5ceSopenharmony_ci	struct allocated_headers *ah = wsi->http.ah;
300d4afb5ceSopenharmony_ci	int n;
301d4afb5ceSopenharmony_ci
302d4afb5ceSopenharmony_ci	if (!ah)
303d4afb5ceSopenharmony_ci		return 0;
304d4afb5ceSopenharmony_ci
305d4afb5ceSopenharmony_ci	n = ah->frag_index[h];
306d4afb5ceSopenharmony_ci	if (!n)
307d4afb5ceSopenharmony_ci		return 0;
308d4afb5ceSopenharmony_ci
309d4afb5ceSopenharmony_ci	return !!(ah->frags[n].flags & 2);
310d4afb5ceSopenharmony_ci}
311d4afb5ceSopenharmony_ci
312d4afb5ceSopenharmony_cistatic void lws_dump_header(struct lws *wsi, int hdr)
313d4afb5ceSopenharmony_ci{
314d4afb5ceSopenharmony_ci	char s[200];
315d4afb5ceSopenharmony_ci	const unsigned char *p;
316d4afb5ceSopenharmony_ci	int len;
317d4afb5ceSopenharmony_ci
318d4afb5ceSopenharmony_ci	if (hdr == LWS_HPACK_IGNORE_ENTRY) {
319d4afb5ceSopenharmony_ci		lwsl_notice("hdr tok ignored\n");
320d4afb5ceSopenharmony_ci		return;
321d4afb5ceSopenharmony_ci	}
322d4afb5ceSopenharmony_ci
323d4afb5ceSopenharmony_ci	(void)p;
324d4afb5ceSopenharmony_ci
325d4afb5ceSopenharmony_ci	len = lws_hdr_copy(wsi, s, sizeof(s) - 1, (enum lws_token_indexes)hdr);
326d4afb5ceSopenharmony_ci	if (len < 0)
327d4afb5ceSopenharmony_ci		strcpy(s, "(too big to show)");
328d4afb5ceSopenharmony_ci	else
329d4afb5ceSopenharmony_ci		s[len] = '\0';
330d4afb5ceSopenharmony_ci#if defined(_DEBUG)
331d4afb5ceSopenharmony_ci	p = lws_token_to_string((enum lws_token_indexes)hdr);
332d4afb5ceSopenharmony_ci	lwsl_header("  hdr tok %d (%s) = '%s' (len %d)\n", hdr,
333d4afb5ceSopenharmony_ci		   p ? (char *)p : (char *)"null", s, len);
334d4afb5ceSopenharmony_ci#endif
335d4afb5ceSopenharmony_ci}
336d4afb5ceSopenharmony_ci
337d4afb5ceSopenharmony_ci/*
338d4afb5ceSopenharmony_ci * dynamic table
339d4afb5ceSopenharmony_ci *
340d4afb5ceSopenharmony_ci *  [ 0 ....   num_entries - 1]
341d4afb5ceSopenharmony_ci *
342d4afb5ceSopenharmony_ci *  Starts filling at 0+
343d4afb5ceSopenharmony_ci *
344d4afb5ceSopenharmony_ci *  #62 is *most recently entered*
345d4afb5ceSopenharmony_ci *
346d4afb5ceSopenharmony_ci *  Number of entries is not restricted, but aggregated size of the entry
347d4afb5ceSopenharmony_ci *  payloads is.  Unfortunately the way HPACK does this is specific to an
348d4afb5ceSopenharmony_ci *  imagined implementation, and lws implementation is much more efficient
349d4afb5ceSopenharmony_ci *  (ignoring unknown headers and using the lws token index for the header
350d4afb5ceSopenharmony_ci *  name part).
351d4afb5ceSopenharmony_ci */
352d4afb5ceSopenharmony_ci
353d4afb5ceSopenharmony_ci/*
354d4afb5ceSopenharmony_ci * returns 0 if dynamic entry (arg and len are filled)
355d4afb5ceSopenharmony_ci * returns -1 if failure
356d4afb5ceSopenharmony_ci * returns nonzero token index if actually static token
357d4afb5ceSopenharmony_ci */
358d4afb5ceSopenharmony_cistatic int
359d4afb5ceSopenharmony_cilws_token_from_index(struct lws *wsi, int index, const char **arg, int *len,
360d4afb5ceSopenharmony_ci		     uint32_t *hdr_len)
361d4afb5ceSopenharmony_ci{
362d4afb5ceSopenharmony_ci	struct hpack_dynamic_table *dyn;
363d4afb5ceSopenharmony_ci
364d4afb5ceSopenharmony_ci	if (index == LWS_HPACK_IGNORE_ENTRY)
365d4afb5ceSopenharmony_ci		return LWS_HPACK_IGNORE_ENTRY;
366d4afb5ceSopenharmony_ci
367d4afb5ceSopenharmony_ci	/* dynamic table only belongs to network wsi */
368d4afb5ceSopenharmony_ci	wsi = lws_get_network_wsi(wsi);
369d4afb5ceSopenharmony_ci	if (!wsi->h2.h2n)
370d4afb5ceSopenharmony_ci		return -1;
371d4afb5ceSopenharmony_ci
372d4afb5ceSopenharmony_ci	dyn = &wsi->h2.h2n->hpack_dyn_table;
373d4afb5ceSopenharmony_ci
374d4afb5ceSopenharmony_ci	if (index < 0)
375d4afb5ceSopenharmony_ci		return -1;
376d4afb5ceSopenharmony_ci
377d4afb5ceSopenharmony_ci	if (index < (int)LWS_ARRAY_SIZE(static_token)) {
378d4afb5ceSopenharmony_ci		if (arg && index < (int)LWS_ARRAY_SIZE(http2_canned)) {
379d4afb5ceSopenharmony_ci			*arg = http2_canned[index];
380d4afb5ceSopenharmony_ci			*len = (int)strlen(http2_canned[index]);
381d4afb5ceSopenharmony_ci		}
382d4afb5ceSopenharmony_ci		if (hdr_len)
383d4afb5ceSopenharmony_ci			*hdr_len = static_hdr_len[index];
384d4afb5ceSopenharmony_ci
385d4afb5ceSopenharmony_ci		return static_token[index];
386d4afb5ceSopenharmony_ci	}
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci	if (!dyn) {
389d4afb5ceSopenharmony_ci		lwsl_notice("no dynamic table\n");
390d4afb5ceSopenharmony_ci		return -1;
391d4afb5ceSopenharmony_ci	}
392d4afb5ceSopenharmony_ci
393d4afb5ceSopenharmony_ci	if (index >= (int)LWS_ARRAY_SIZE(static_token) + dyn->used_entries) {
394d4afb5ceSopenharmony_ci		lwsl_info("  %s: adjusted index %d >= %d\n", __func__, index,
395d4afb5ceSopenharmony_ci				(int)LWS_ARRAY_SIZE(static_token) + dyn->used_entries);
396d4afb5ceSopenharmony_ci		lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
397d4afb5ceSopenharmony_ci			      "index out of range");
398d4afb5ceSopenharmony_ci		return -1;
399d4afb5ceSopenharmony_ci	}
400d4afb5ceSopenharmony_ci
401d4afb5ceSopenharmony_ci	index -= (int)LWS_ARRAY_SIZE(static_token);
402d4afb5ceSopenharmony_ci	index = lws_safe_modulo(dyn->pos - 1 - index, dyn->num_entries);
403d4afb5ceSopenharmony_ci	if (index < 0)
404d4afb5ceSopenharmony_ci		index += dyn->num_entries;
405d4afb5ceSopenharmony_ci
406d4afb5ceSopenharmony_ci	lwsl_header("%s: dyn index %d, tok %d\n", __func__, index,
407d4afb5ceSopenharmony_ci		    dyn->entries[index].lws_hdr_idx);
408d4afb5ceSopenharmony_ci
409d4afb5ceSopenharmony_ci	if (arg && len) {
410d4afb5ceSopenharmony_ci		*arg = dyn->entries[index].value;
411d4afb5ceSopenharmony_ci		*len = dyn->entries[index].value_len;
412d4afb5ceSopenharmony_ci	}
413d4afb5ceSopenharmony_ci
414d4afb5ceSopenharmony_ci	if (hdr_len)
415d4afb5ceSopenharmony_ci		*hdr_len = dyn->entries[index].hdr_len;
416d4afb5ceSopenharmony_ci
417d4afb5ceSopenharmony_ci	return dyn->entries[index].lws_hdr_idx;
418d4afb5ceSopenharmony_ci}
419d4afb5ceSopenharmony_ci
420d4afb5ceSopenharmony_cistatic int
421d4afb5ceSopenharmony_cilws_h2_dynamic_table_dump(struct lws *wsi)
422d4afb5ceSopenharmony_ci{
423d4afb5ceSopenharmony_ci#if 0
424d4afb5ceSopenharmony_ci	struct lws *nwsi = lws_get_network_wsi(wsi);
425d4afb5ceSopenharmony_ci	struct hpack_dynamic_table *dyn;
426d4afb5ceSopenharmony_ci	int n, m;
427d4afb5ceSopenharmony_ci	const char *p;
428d4afb5ceSopenharmony_ci
429d4afb5ceSopenharmony_ci	if (!nwsi->h2.h2n)
430d4afb5ceSopenharmony_ci		return 1;
431d4afb5ceSopenharmony_ci	dyn = &nwsi->h2.h2n->hpack_dyn_table;
432d4afb5ceSopenharmony_ci
433d4afb5ceSopenharmony_ci	lwsl_header("Dump dyn table for nwsi %s (%d / %d members, pos = %d, "
434d4afb5ceSopenharmony_ci		    "start index %d, virt used %d / %d)\n", lws_wsi_tag(nwsi),
435d4afb5ceSopenharmony_ci		    dyn->used_entries, dyn->num_entries, dyn->pos,
436d4afb5ceSopenharmony_ci		    (uint32_t)LWS_ARRAY_SIZE(static_token),
437d4afb5ceSopenharmony_ci		    dyn->virtual_payload_usage, dyn->virtual_payload_max);
438d4afb5ceSopenharmony_ci
439d4afb5ceSopenharmony_ci	for (n = 0; n < dyn->used_entries; n++) {
440d4afb5ceSopenharmony_ci		m = lws_safe_modulo(dyn->pos - 1 - n, dyn->num_entries);
441d4afb5ceSopenharmony_ci		if (m < 0)
442d4afb5ceSopenharmony_ci			m += dyn->num_entries;
443d4afb5ceSopenharmony_ci		if (dyn->entries[m].lws_hdr_idx != LWS_HPACK_IGNORE_ENTRY)
444d4afb5ceSopenharmony_ci			p = (const char *)lws_token_to_string(
445d4afb5ceSopenharmony_ci					dyn->entries[m].lws_hdr_idx);
446d4afb5ceSopenharmony_ci		else
447d4afb5ceSopenharmony_ci			p = "(ignored)";
448d4afb5ceSopenharmony_ci		lwsl_header("   %3d: tok %s: (len %d) val '%s'\n",
449d4afb5ceSopenharmony_ci			    (int)(n + LWS_ARRAY_SIZE(static_token)), p,
450d4afb5ceSopenharmony_ci			    dyn->entries[m].hdr_len, dyn->entries[m].value ?
451d4afb5ceSopenharmony_ci			    dyn->entries[m].value : "null");
452d4afb5ceSopenharmony_ci	}
453d4afb5ceSopenharmony_ci#endif
454d4afb5ceSopenharmony_ci	return 0;
455d4afb5ceSopenharmony_ci}
456d4afb5ceSopenharmony_ci
457d4afb5ceSopenharmony_cistatic void
458d4afb5ceSopenharmony_cilws_dynamic_free(struct hpack_dynamic_table *dyn, int idx)
459d4afb5ceSopenharmony_ci{
460d4afb5ceSopenharmony_ci	lwsl_header("freeing %d for reuse\n", idx);
461d4afb5ceSopenharmony_ci	dyn->virtual_payload_usage = (uint32_t)((unsigned int)dyn->virtual_payload_usage - (unsigned int)(dyn->entries[idx].value_len +
462d4afb5ceSopenharmony_ci				dyn->entries[idx].hdr_len));
463d4afb5ceSopenharmony_ci	lws_free_set_NULL(dyn->entries[idx].value);
464d4afb5ceSopenharmony_ci	dyn->entries[idx].value = NULL;
465d4afb5ceSopenharmony_ci	dyn->entries[idx].value_len = 0;
466d4afb5ceSopenharmony_ci	dyn->entries[idx].hdr_len = 0;
467d4afb5ceSopenharmony_ci	dyn->entries[idx].lws_hdr_idx = LWS_HPACK_IGNORE_ENTRY;
468d4afb5ceSopenharmony_ci	dyn->used_entries--;
469d4afb5ceSopenharmony_ci}
470d4afb5ceSopenharmony_ci
471d4afb5ceSopenharmony_ci/*
472d4afb5ceSopenharmony_ci * There are two address spaces, 1) internal ringbuffer and 2) HPACK indexes.
473d4afb5ceSopenharmony_ci *
474d4afb5ceSopenharmony_ci * Internal ringbuffer:
475d4afb5ceSopenharmony_ci *
476d4afb5ceSopenharmony_ci * The internal ringbuffer wraps as we keep filling it, dyn->pos points to
477d4afb5ceSopenharmony_ci * the next index to be written.
478d4afb5ceSopenharmony_ci *
479d4afb5ceSopenharmony_ci * HPACK indexes:
480d4afb5ceSopenharmony_ci *
481d4afb5ceSopenharmony_ci * The last-written entry becomes entry 0, the previously-last-written entry
482d4afb5ceSopenharmony_ci * becomes entry 1 etc.
483d4afb5ceSopenharmony_ci */
484d4afb5ceSopenharmony_ci
485d4afb5ceSopenharmony_cistatic int
486d4afb5ceSopenharmony_cilws_dynamic_token_insert(struct lws *wsi, int hdr_len,
487d4afb5ceSopenharmony_ci			 int lws_hdr_index, char *arg, size_t len)
488d4afb5ceSopenharmony_ci{
489d4afb5ceSopenharmony_ci	struct hpack_dynamic_table *dyn;
490d4afb5ceSopenharmony_ci	int new_index;
491d4afb5ceSopenharmony_ci
492d4afb5ceSopenharmony_ci	/* dynamic table only belongs to network wsi */
493d4afb5ceSopenharmony_ci	wsi = lws_get_network_wsi(wsi);
494d4afb5ceSopenharmony_ci	if (!wsi->h2.h2n)
495d4afb5ceSopenharmony_ci		return 1;
496d4afb5ceSopenharmony_ci	dyn = &wsi->h2.h2n->hpack_dyn_table;
497d4afb5ceSopenharmony_ci
498d4afb5ceSopenharmony_ci	if (!dyn->entries) {
499d4afb5ceSopenharmony_ci		lwsl_err("%s: unsized dyn table\n", __func__);
500d4afb5ceSopenharmony_ci
501d4afb5ceSopenharmony_ci		return 1;
502d4afb5ceSopenharmony_ci	}
503d4afb5ceSopenharmony_ci	lws_h2_dynamic_table_dump(wsi);
504d4afb5ceSopenharmony_ci
505d4afb5ceSopenharmony_ci	new_index = lws_safe_modulo(dyn->pos, dyn->num_entries);
506d4afb5ceSopenharmony_ci	if (dyn->num_entries && dyn->used_entries == dyn->num_entries) {
507d4afb5ceSopenharmony_ci		if (dyn->virtual_payload_usage < dyn->virtual_payload_max)
508d4afb5ceSopenharmony_ci			lwsl_err("Dropping header content before limit!\n");
509d4afb5ceSopenharmony_ci		/* we have to drop the oldest to make space */
510d4afb5ceSopenharmony_ci		lws_dynamic_free(dyn, new_index);
511d4afb5ceSopenharmony_ci	}
512d4afb5ceSopenharmony_ci
513d4afb5ceSopenharmony_ci	/*
514d4afb5ceSopenharmony_ci	 * evict guys to make room, allowing for some overage.  We have to
515d4afb5ceSopenharmony_ci	 * take care about getting a single huge header, and evicting
516d4afb5ceSopenharmony_ci	 * everything
517d4afb5ceSopenharmony_ci	 */
518d4afb5ceSopenharmony_ci
519d4afb5ceSopenharmony_ci	while (dyn->virtual_payload_usage &&
520d4afb5ceSopenharmony_ci	       dyn->used_entries &&
521d4afb5ceSopenharmony_ci	       dyn->virtual_payload_usage + (unsigned int)hdr_len + len >
522d4afb5ceSopenharmony_ci				dyn->virtual_payload_max + 1024) {
523d4afb5ceSopenharmony_ci		int n = lws_safe_modulo(dyn->pos - dyn->used_entries,
524d4afb5ceSopenharmony_ci						dyn->num_entries);
525d4afb5ceSopenharmony_ci		if (n < 0)
526d4afb5ceSopenharmony_ci			n += dyn->num_entries;
527d4afb5ceSopenharmony_ci		lws_dynamic_free(dyn, n);
528d4afb5ceSopenharmony_ci	}
529d4afb5ceSopenharmony_ci
530d4afb5ceSopenharmony_ci	if (dyn->used_entries < dyn->num_entries)
531d4afb5ceSopenharmony_ci		dyn->used_entries++;
532d4afb5ceSopenharmony_ci
533d4afb5ceSopenharmony_ci	dyn->entries[new_index].value_len = 0;
534d4afb5ceSopenharmony_ci
535d4afb5ceSopenharmony_ci	if (lws_hdr_index != LWS_HPACK_IGNORE_ENTRY) {
536d4afb5ceSopenharmony_ci		if (dyn->entries[new_index].value)
537d4afb5ceSopenharmony_ci			lws_free_set_NULL(dyn->entries[new_index].value);
538d4afb5ceSopenharmony_ci		dyn->entries[new_index].value =
539d4afb5ceSopenharmony_ci				lws_malloc(len + 1, "hpack dyn");
540d4afb5ceSopenharmony_ci		if (!dyn->entries[new_index].value)
541d4afb5ceSopenharmony_ci			return 1;
542d4afb5ceSopenharmony_ci
543d4afb5ceSopenharmony_ci		memcpy(dyn->entries[new_index].value, arg, len);
544d4afb5ceSopenharmony_ci		dyn->entries[new_index].value[len] = '\0';
545d4afb5ceSopenharmony_ci		dyn->entries[new_index].value_len = (uint16_t)len;
546d4afb5ceSopenharmony_ci	} else
547d4afb5ceSopenharmony_ci		dyn->entries[new_index].value = NULL;
548d4afb5ceSopenharmony_ci
549d4afb5ceSopenharmony_ci	dyn->entries[new_index].lws_hdr_idx = (uint16_t)lws_hdr_index;
550d4afb5ceSopenharmony_ci	dyn->entries[new_index].hdr_len = (uint16_t)hdr_len;
551d4afb5ceSopenharmony_ci
552d4afb5ceSopenharmony_ci	dyn->virtual_payload_usage = (uint32_t)(dyn->virtual_payload_usage +
553d4afb5ceSopenharmony_ci					(unsigned int)hdr_len + len);
554d4afb5ceSopenharmony_ci
555d4afb5ceSopenharmony_ci	lwsl_info("%s: index %ld: lws_hdr_index 0x%x, hdr len %d, '%s' len %d\n",
556d4afb5ceSopenharmony_ci		  __func__, (long)LWS_ARRAY_SIZE(static_token),
557d4afb5ceSopenharmony_ci		  lws_hdr_index, hdr_len, dyn->entries[new_index].value ?
558d4afb5ceSopenharmony_ci				 dyn->entries[new_index].value : "null", (int)len);
559d4afb5ceSopenharmony_ci
560d4afb5ceSopenharmony_ci	dyn->pos = (uint16_t)lws_safe_modulo(dyn->pos + 1, dyn->num_entries);
561d4afb5ceSopenharmony_ci
562d4afb5ceSopenharmony_ci	lws_h2_dynamic_table_dump(wsi);
563d4afb5ceSopenharmony_ci
564d4afb5ceSopenharmony_ci	return 0;
565d4afb5ceSopenharmony_ci}
566d4afb5ceSopenharmony_ci
567d4afb5ceSopenharmony_ciint
568d4afb5ceSopenharmony_cilws_hpack_dynamic_size(struct lws *wsi, int size)
569d4afb5ceSopenharmony_ci{
570d4afb5ceSopenharmony_ci	struct hpack_dynamic_table *dyn;
571d4afb5ceSopenharmony_ci	struct hpack_dt_entry *dte;
572d4afb5ceSopenharmony_ci	struct lws *nwsi;
573d4afb5ceSopenharmony_ci	int min, n = 0, m;
574d4afb5ceSopenharmony_ci
575d4afb5ceSopenharmony_ci	/*
576d4afb5ceSopenharmony_ci	 * "size" here is coming from the http/2 SETTING
577d4afb5ceSopenharmony_ci	 * SETTINGS_HEADER_TABLE_SIZE.  This is a (virtual, in our case)
578d4afb5ceSopenharmony_ci	 * linear buffer containing dynamic header names and values... when it
579d4afb5ceSopenharmony_ci	 * is full, old entries are evicted.
580d4afb5ceSopenharmony_ci	 *
581d4afb5ceSopenharmony_ci	 * We encode the header as an lws_hdr_idx, which is all the rest of
582d4afb5ceSopenharmony_ci	 * lws cares about; if there is no matching header we store an empty
583d4afb5ceSopenharmony_ci	 * entry in the dyn table as a placeholder.
584d4afb5ceSopenharmony_ci	 *
585d4afb5ceSopenharmony_ci	 * So to make the two systems work together we keep an accounting of
586d4afb5ceSopenharmony_ci	 * what we are using to decide when to evict... we must only evict
587d4afb5ceSopenharmony_ci	 * things when the remote peer's accounting also makes him feel he
588d4afb5ceSopenharmony_ci	 * should evict something.
589d4afb5ceSopenharmony_ci	 */
590d4afb5ceSopenharmony_ci
591d4afb5ceSopenharmony_ci	nwsi = lws_get_network_wsi(wsi);
592d4afb5ceSopenharmony_ci	if (!nwsi->h2.h2n)
593d4afb5ceSopenharmony_ci		goto bail;
594d4afb5ceSopenharmony_ci
595d4afb5ceSopenharmony_ci	dyn = &nwsi->h2.h2n->hpack_dyn_table;
596d4afb5ceSopenharmony_ci	lwsl_info("%s: from %d to %d, lim %u\n", __func__,
597d4afb5ceSopenharmony_ci		  (int)dyn->num_entries, size,
598d4afb5ceSopenharmony_ci		  (unsigned int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]);
599d4afb5ceSopenharmony_ci
600d4afb5ceSopenharmony_ci	if (!size) {
601d4afb5ceSopenharmony_ci		size = dyn->num_entries * 8;
602d4afb5ceSopenharmony_ci		lws_hpack_destroy_dynamic_header(wsi);
603d4afb5ceSopenharmony_ci	}
604d4afb5ceSopenharmony_ci
605d4afb5ceSopenharmony_ci	if (size > (int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]) {
606d4afb5ceSopenharmony_ci		lwsl_info("rejecting hpack dyn size %u vs %u\n", size,
607d4afb5ceSopenharmony_ci			  (unsigned int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]);
608d4afb5ceSopenharmony_ci
609d4afb5ceSopenharmony_ci		// this seems necessary to work with some browsers
610d4afb5ceSopenharmony_ci
611d4afb5ceSopenharmony_ci		if (nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE] == 65536 &&
612d4afb5ceSopenharmony_ci				size == 65537) { /* h2spec */
613d4afb5ceSopenharmony_ci			lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
614d4afb5ceSopenharmony_ci				  "Asked for header table bigger than we told");
615d4afb5ceSopenharmony_ci			goto bail;
616d4afb5ceSopenharmony_ci		}
617d4afb5ceSopenharmony_ci
618d4afb5ceSopenharmony_ci		size = (int)nwsi->a.vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE];
619d4afb5ceSopenharmony_ci	}
620d4afb5ceSopenharmony_ci
621d4afb5ceSopenharmony_ci	dyn->virtual_payload_max = (uint32_t)size;
622d4afb5ceSopenharmony_ci
623d4afb5ceSopenharmony_ci	size = size / 8;
624d4afb5ceSopenharmony_ci	min = size;
625d4afb5ceSopenharmony_ci	if (min > dyn->used_entries)
626d4afb5ceSopenharmony_ci		min = dyn->used_entries;
627d4afb5ceSopenharmony_ci
628d4afb5ceSopenharmony_ci	if (size == dyn->num_entries)
629d4afb5ceSopenharmony_ci		return 0;
630d4afb5ceSopenharmony_ci
631d4afb5ceSopenharmony_ci	if (dyn->num_entries < min)
632d4afb5ceSopenharmony_ci		min = dyn->num_entries;
633d4afb5ceSopenharmony_ci
634d4afb5ceSopenharmony_ci	// lwsl_notice("dte requested size %d\n", size);
635d4afb5ceSopenharmony_ci
636d4afb5ceSopenharmony_ci	dte = lws_zalloc(sizeof(*dte) * (unsigned int)(size + 1), "dynamic table entries");
637d4afb5ceSopenharmony_ci	if (!dte)
638d4afb5ceSopenharmony_ci		goto bail;
639d4afb5ceSopenharmony_ci
640d4afb5ceSopenharmony_ci	while (dyn->virtual_payload_usage && dyn->used_entries &&
641d4afb5ceSopenharmony_ci	       dyn->virtual_payload_usage > dyn->virtual_payload_max) {
642d4afb5ceSopenharmony_ci		n = lws_safe_modulo(dyn->pos - dyn->used_entries, dyn->num_entries);
643d4afb5ceSopenharmony_ci		if (n < 0)
644d4afb5ceSopenharmony_ci			n += dyn->num_entries;
645d4afb5ceSopenharmony_ci		lws_dynamic_free(dyn, n);
646d4afb5ceSopenharmony_ci	}
647d4afb5ceSopenharmony_ci
648d4afb5ceSopenharmony_ci	if (min > dyn->used_entries)
649d4afb5ceSopenharmony_ci		min = dyn->used_entries;
650d4afb5ceSopenharmony_ci
651d4afb5ceSopenharmony_ci	if (dyn->entries) {
652d4afb5ceSopenharmony_ci		for (n = 0; n < min; n++) {
653d4afb5ceSopenharmony_ci			m = (dyn->pos - dyn->used_entries + n) %
654d4afb5ceSopenharmony_ci						dyn->num_entries;
655d4afb5ceSopenharmony_ci			if (m < 0)
656d4afb5ceSopenharmony_ci				m += dyn->num_entries;
657d4afb5ceSopenharmony_ci			dte[n] = dyn->entries[m];
658d4afb5ceSopenharmony_ci		}
659d4afb5ceSopenharmony_ci
660d4afb5ceSopenharmony_ci		lws_free(dyn->entries);
661d4afb5ceSopenharmony_ci	}
662d4afb5ceSopenharmony_ci
663d4afb5ceSopenharmony_ci	dyn->entries = dte;
664d4afb5ceSopenharmony_ci	dyn->num_entries = (uint16_t)size;
665d4afb5ceSopenharmony_ci	dyn->used_entries = (uint16_t)min;
666d4afb5ceSopenharmony_ci	if (size)
667d4afb5ceSopenharmony_ci		dyn->pos = (uint16_t)lws_safe_modulo(min, size);
668d4afb5ceSopenharmony_ci	else
669d4afb5ceSopenharmony_ci		dyn->pos = 0;
670d4afb5ceSopenharmony_ci
671d4afb5ceSopenharmony_ci	lws_h2_dynamic_table_dump(wsi);
672d4afb5ceSopenharmony_ci
673d4afb5ceSopenharmony_ci	return 0;
674d4afb5ceSopenharmony_ci
675d4afb5ceSopenharmony_cibail:
676d4afb5ceSopenharmony_ci	lwsl_info("%s: failed to resize to %d\n", __func__, size);
677d4afb5ceSopenharmony_ci
678d4afb5ceSopenharmony_ci	return 1;
679d4afb5ceSopenharmony_ci}
680d4afb5ceSopenharmony_ci
681d4afb5ceSopenharmony_civoid
682d4afb5ceSopenharmony_cilws_hpack_destroy_dynamic_header(struct lws *wsi)
683d4afb5ceSopenharmony_ci{
684d4afb5ceSopenharmony_ci	struct hpack_dynamic_table *dyn;
685d4afb5ceSopenharmony_ci	int n;
686d4afb5ceSopenharmony_ci
687d4afb5ceSopenharmony_ci	if (!wsi->h2.h2n)
688d4afb5ceSopenharmony_ci		return;
689d4afb5ceSopenharmony_ci
690d4afb5ceSopenharmony_ci	dyn = &wsi->h2.h2n->hpack_dyn_table;
691d4afb5ceSopenharmony_ci
692d4afb5ceSopenharmony_ci	if (!dyn->entries)
693d4afb5ceSopenharmony_ci		return;
694d4afb5ceSopenharmony_ci
695d4afb5ceSopenharmony_ci	for (n = 0; n < dyn->num_entries; n++)
696d4afb5ceSopenharmony_ci		if (dyn->entries[n].value)
697d4afb5ceSopenharmony_ci			lws_free_set_NULL(dyn->entries[n].value);
698d4afb5ceSopenharmony_ci
699d4afb5ceSopenharmony_ci	lws_free_set_NULL(dyn->entries);
700d4afb5ceSopenharmony_ci}
701d4afb5ceSopenharmony_ci
702d4afb5ceSopenharmony_cistatic int
703d4afb5ceSopenharmony_cilws_hpack_use_idx_hdr(struct lws *wsi, int idx, int known_token)
704d4afb5ceSopenharmony_ci{
705d4afb5ceSopenharmony_ci	const char *arg = NULL;
706d4afb5ceSopenharmony_ci	int len = 0;
707d4afb5ceSopenharmony_ci	const char *p = NULL;
708d4afb5ceSopenharmony_ci	int tok = lws_token_from_index(wsi, idx, &arg, &len, NULL);
709d4afb5ceSopenharmony_ci
710d4afb5ceSopenharmony_ci	if (tok == LWS_HPACK_IGNORE_ENTRY) {
711d4afb5ceSopenharmony_ci		lwsl_header("%s: lws_token says ignore, returning\n", __func__);
712d4afb5ceSopenharmony_ci		return 0;
713d4afb5ceSopenharmony_ci	}
714d4afb5ceSopenharmony_ci
715d4afb5ceSopenharmony_ci	if (tok == -1) {
716d4afb5ceSopenharmony_ci		lwsl_info("%s: idx %d mapped to tok %d\n", __func__, idx, tok);
717d4afb5ceSopenharmony_ci		return 1;
718d4afb5ceSopenharmony_ci	}
719d4afb5ceSopenharmony_ci
720d4afb5ceSopenharmony_ci	if (arg) {
721d4afb5ceSopenharmony_ci		/* dynamic result */
722d4afb5ceSopenharmony_ci		if (known_token > 0)
723d4afb5ceSopenharmony_ci			tok = known_token;
724d4afb5ceSopenharmony_ci		lwsl_header("%s: dyn: idx %d '%s' tok %d\n", __func__, idx, arg,
725d4afb5ceSopenharmony_ci			   tok);
726d4afb5ceSopenharmony_ci	} else
727d4afb5ceSopenharmony_ci		lwsl_header("writing indexed hdr %d (tok %d '%s')\n", idx, tok,
728d4afb5ceSopenharmony_ci				lws_token_to_string((enum lws_token_indexes)tok));
729d4afb5ceSopenharmony_ci
730d4afb5ceSopenharmony_ci	if (tok == LWS_HPACK_IGNORE_ENTRY)
731d4afb5ceSopenharmony_ci		return 0;
732d4afb5ceSopenharmony_ci
733d4afb5ceSopenharmony_ci	if (arg)
734d4afb5ceSopenharmony_ci		p = arg;
735d4afb5ceSopenharmony_ci
736d4afb5ceSopenharmony_ci	if (idx < (int)LWS_ARRAY_SIZE(http2_canned))
737d4afb5ceSopenharmony_ci		p = http2_canned[idx];
738d4afb5ceSopenharmony_ci
739d4afb5ceSopenharmony_ci	if (lws_frag_start(wsi, tok))
740d4afb5ceSopenharmony_ci		return 1;
741d4afb5ceSopenharmony_ci
742d4afb5ceSopenharmony_ci	if (p)
743d4afb5ceSopenharmony_ci		while (*p && len--)
744d4afb5ceSopenharmony_ci			if (lws_frag_append(wsi, (unsigned char)*p++))
745d4afb5ceSopenharmony_ci				return 1;
746d4afb5ceSopenharmony_ci
747d4afb5ceSopenharmony_ci	if (lws_frag_end(wsi))
748d4afb5ceSopenharmony_ci		return 1;
749d4afb5ceSopenharmony_ci
750d4afb5ceSopenharmony_ci	lws_dump_header(wsi, tok);
751d4afb5ceSopenharmony_ci
752d4afb5ceSopenharmony_ci	return 0;
753d4afb5ceSopenharmony_ci}
754d4afb5ceSopenharmony_ci
755d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2)
756d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
757d4afb5ceSopenharmony_ci	0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
758d4afb5ceSopenharmony_ci};
759d4afb5ceSopenharmony_ci#endif
760d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) &&  defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2)
761d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
762d4afb5ceSopenharmony_ci	0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
763d4afb5ceSopenharmony_ci};
764d4afb5ceSopenharmony_ci#endif
765d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) &&  defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2)
766d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
767d4afb5ceSopenharmony_ci	0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
768d4afb5ceSopenharmony_ci};
769d4afb5ceSopenharmony_ci#endif
770d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) &&  defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) &&  defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2)
771d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
772d4afb5ceSopenharmony_ci	0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
773d4afb5ceSopenharmony_ci};
774d4afb5ceSopenharmony_ci#endif
775d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) &&  defined(LWS_ROLE_H2)
776d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
777d4afb5ceSopenharmony_ci	0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
778d4afb5ceSopenharmony_ci};
779d4afb5ceSopenharmony_ci#endif
780d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) &&  defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) &&  defined(LWS_ROLE_H2)
781d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
782d4afb5ceSopenharmony_ci	0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x09,0x00,0x00,0x00,0x00,0x00,0x00,
783d4afb5ceSopenharmony_ci};
784d4afb5ceSopenharmony_ci#endif
785d4afb5ceSopenharmony_ci#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) &&  defined(LWS_ROLE_WS) &&  defined(LWS_ROLE_H2)
786d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
787d4afb5ceSopenharmony_ci	0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,
788d4afb5ceSopenharmony_ci};
789d4afb5ceSopenharmony_ci#endif
790d4afb5ceSopenharmony_ci#if defined(LWS_HTTP_HEADERS_ALL) || ( defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) &&  defined(LWS_ROLE_WS) &&  defined(LWS_ROLE_H2))
791d4afb5ceSopenharmony_cistatic uint8_t lws_header_implies_psuedoheader_map[] = {
792d4afb5ceSopenharmony_ci	0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x24,0x00,0x00,0x00,0x00,0x00,
793d4afb5ceSopenharmony_ci};
794d4afb5ceSopenharmony_ci#endif
795d4afb5ceSopenharmony_ci
796d4afb5ceSopenharmony_ci
797d4afb5ceSopenharmony_cistatic int
798d4afb5ceSopenharmony_cilws_hpack_handle_pseudo_rules(struct lws *nwsi, struct lws *wsi, int m)
799d4afb5ceSopenharmony_ci{
800d4afb5ceSopenharmony_ci	if (m == LWS_HPACK_IGNORE_ENTRY || m == -1)
801d4afb5ceSopenharmony_ci		return 0;
802d4afb5ceSopenharmony_ci
803d4afb5ceSopenharmony_ci	if (wsi->seen_nonpseudoheader &&
804d4afb5ceSopenharmony_ci	    (lws_header_implies_psuedoheader_map[m >> 3] & (1 << (m & 7)))) {
805d4afb5ceSopenharmony_ci
806d4afb5ceSopenharmony_ci		lwsl_info("lws tok %d seems to be a pseudoheader\n", m);
807d4afb5ceSopenharmony_ci
808d4afb5ceSopenharmony_ci		/*
809d4afb5ceSopenharmony_ci		 * it's not legal to see a
810d4afb5ceSopenharmony_ci		 * pseudoheader after normal
811d4afb5ceSopenharmony_ci		 * headers
812d4afb5ceSopenharmony_ci		 */
813d4afb5ceSopenharmony_ci		lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
814d4afb5ceSopenharmony_ci			"Pseudoheader after normal hdrs");
815d4afb5ceSopenharmony_ci		return 1;
816d4afb5ceSopenharmony_ci	}
817d4afb5ceSopenharmony_ci
818d4afb5ceSopenharmony_ci	if (!(lws_header_implies_psuedoheader_map[m >> 3] & (1 << (m & 7))))
819d4afb5ceSopenharmony_ci		wsi->seen_nonpseudoheader = 1;
820d4afb5ceSopenharmony_ci
821d4afb5ceSopenharmony_ci	return 0;
822d4afb5ceSopenharmony_ci}
823d4afb5ceSopenharmony_ci
824d4afb5ceSopenharmony_ciint lws_hpack_interpret(struct lws *wsi, unsigned char c)
825d4afb5ceSopenharmony_ci{
826d4afb5ceSopenharmony_ci	struct lws *nwsi = lws_get_network_wsi(wsi);
827d4afb5ceSopenharmony_ci	struct lws_h2_netconn *h2n = nwsi->h2.h2n;
828d4afb5ceSopenharmony_ci	struct allocated_headers *ah = wsi->http.ah;
829d4afb5ceSopenharmony_ci	unsigned int prev;
830d4afb5ceSopenharmony_ci	unsigned char c1;
831d4afb5ceSopenharmony_ci	int n, m, plen;
832d4afb5ceSopenharmony_ci
833d4afb5ceSopenharmony_ci	if (!h2n)
834d4afb5ceSopenharmony_ci		return -1;
835d4afb5ceSopenharmony_ci
836d4afb5ceSopenharmony_ci	/*
837d4afb5ceSopenharmony_ci	 * HPKT_INDEXED_HDR_7		  1xxxxxxx: just "header field"
838d4afb5ceSopenharmony_ci	 * HPKT_INDEXED_HDR_6_VALUE_INCR  01xxxxxx: NEW indexed hdr + val
839d4afb5ceSopenharmony_ci	 * HPKT_LITERAL_HDR_VALUE_INCR	  01000000: NEW literal hdr + val
840d4afb5ceSopenharmony_ci	 * HPKT_INDEXED_HDR_4_VALUE	  0000xxxx: indexed hdr + val
841d4afb5ceSopenharmony_ci	 * HPKT_INDEXED_HDR_4_VALUE_NEVER 0001xxxx: NEVER NEW indexed hdr + val
842d4afb5ceSopenharmony_ci	 * HPKT_LITERAL_HDR_VALUE	  00000000: literal hdr + val
843d4afb5ceSopenharmony_ci	 * HPKT_LITERAL_HDR_VALUE_NEVER	  00010000: NEVER NEW literal hdr + val
844d4afb5ceSopenharmony_ci	 */
845d4afb5ceSopenharmony_ci	switch (h2n->hpack) {
846d4afb5ceSopenharmony_ci
847d4afb5ceSopenharmony_ci	case HPKS_TYPE:
848d4afb5ceSopenharmony_ci		h2n->is_first_header_char = 1;
849d4afb5ceSopenharmony_ci		h2n->huff_pad = 0;
850d4afb5ceSopenharmony_ci		h2n->zero_huff_padding = 0;
851d4afb5ceSopenharmony_ci		h2n->last_action_dyntable_resize = 0;
852d4afb5ceSopenharmony_ci		h2n->ext_count = 0;
853d4afb5ceSopenharmony_ci		h2n->hpack_hdr_len = 0;
854d4afb5ceSopenharmony_ci		h2n->unknown_header = 0;
855d4afb5ceSopenharmony_ci		ah->parser_state = 255;
856d4afb5ceSopenharmony_ci
857d4afb5ceSopenharmony_ci		if (c & 0x80) { /* 1....  indexed header field only */
858d4afb5ceSopenharmony_ci			/* just a possibly-extended integer */
859d4afb5ceSopenharmony_ci			h2n->hpack_type = HPKT_INDEXED_HDR_7;
860d4afb5ceSopenharmony_ci			lwsl_header("HPKT_INDEXED_HDR_7 hdr %d\n", c & 0x7f);
861d4afb5ceSopenharmony_ci			lws_h2_dynamic_table_dump(wsi);
862d4afb5ceSopenharmony_ci
863d4afb5ceSopenharmony_ci			h2n->hdr_idx = c & 0x7f;
864d4afb5ceSopenharmony_ci			if ((c & 0x7f) == 0x7f) {
865d4afb5ceSopenharmony_ci				h2n->hpack_len = 0;
866d4afb5ceSopenharmony_ci				h2n->hpack_m = 0x7f;
867d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_IDX_EXT;
868d4afb5ceSopenharmony_ci				break;
869d4afb5ceSopenharmony_ci			}
870d4afb5ceSopenharmony_ci			if (!h2n->hdr_idx) {
871d4afb5ceSopenharmony_ci				lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
872d4afb5ceSopenharmony_ci					      "hdr index 0 seen");
873d4afb5ceSopenharmony_ci					return 1;
874d4afb5ceSopenharmony_ci			}
875d4afb5ceSopenharmony_ci
876d4afb5ceSopenharmony_ci			m = lws_token_from_index(wsi, (int)h2n->hdr_idx,
877d4afb5ceSopenharmony_ci						 NULL, NULL, NULL);
878d4afb5ceSopenharmony_ci			if (lws_hpack_handle_pseudo_rules(nwsi, wsi, m))
879d4afb5ceSopenharmony_ci				return 1;
880d4afb5ceSopenharmony_ci
881d4afb5ceSopenharmony_ci			lwsl_header("HPKT_INDEXED_HDR_7: hdr %d\n", c & 0x7f);
882d4afb5ceSopenharmony_ci			if (lws_hpack_use_idx_hdr(wsi, c & 0x7f, -1)) {
883d4afb5ceSopenharmony_ci				lwsl_header("%s: idx hdr wr fail\n", __func__);
884d4afb5ceSopenharmony_ci				return 1;
885d4afb5ceSopenharmony_ci			}
886d4afb5ceSopenharmony_ci			/* stay at same state */
887d4afb5ceSopenharmony_ci			break;
888d4afb5ceSopenharmony_ci		}
889d4afb5ceSopenharmony_ci		if (c & 0x40) { /* 01.... indexed or literal header incr idx */
890d4afb5ceSopenharmony_ci			/*
891d4afb5ceSopenharmony_ci			 * [possibly-ext hdr idx (6) | new literal hdr name]
892d4afb5ceSopenharmony_ci			 * H + possibly-ext value length
893d4afb5ceSopenharmony_ci			 * literal value
894d4afb5ceSopenharmony_ci			 */
895d4afb5ceSopenharmony_ci			h2n->hdr_idx = 0;
896d4afb5ceSopenharmony_ci			if (c == 0x40) { /* literal header */
897d4afb5ceSopenharmony_ci				lwsl_header("   HPKT_LITERAL_HDR_VALUE_INCR\n");
898d4afb5ceSopenharmony_ci				h2n->hpack_type = HPKT_LITERAL_HDR_VALUE_INCR;
899d4afb5ceSopenharmony_ci				h2n->value = 0;
900d4afb5ceSopenharmony_ci				h2n->hpack_len = 0;
901d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_HLEN;
902d4afb5ceSopenharmony_ci				break;
903d4afb5ceSopenharmony_ci			}
904d4afb5ceSopenharmony_ci			/* indexed header */
905d4afb5ceSopenharmony_ci			h2n->hpack_type = HPKT_INDEXED_HDR_6_VALUE_INCR;
906d4afb5ceSopenharmony_ci			lwsl_header(" HPKT_INDEXED_HDR_6_VALUE_INCR (hdr %d)\n",
907d4afb5ceSopenharmony_ci				   c & 0x3f);
908d4afb5ceSopenharmony_ci			h2n->hdr_idx = c & 0x3f;
909d4afb5ceSopenharmony_ci			if ((c & 0x3f) == 0x3f) {
910d4afb5ceSopenharmony_ci				h2n->hpack_m = 0x3f;
911d4afb5ceSopenharmony_ci				h2n->hpack_len = 0;
912d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_IDX_EXT;
913d4afb5ceSopenharmony_ci				break;
914d4afb5ceSopenharmony_ci			}
915d4afb5ceSopenharmony_ci
916d4afb5ceSopenharmony_ci			h2n->value = 1;
917d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_HLEN;
918d4afb5ceSopenharmony_ci			if (!h2n->hdr_idx) {
919d4afb5ceSopenharmony_ci				lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
920d4afb5ceSopenharmony_ci					      "hdr index 0 seen");
921d4afb5ceSopenharmony_ci					return 1;
922d4afb5ceSopenharmony_ci			}
923d4afb5ceSopenharmony_ci			break;
924d4afb5ceSopenharmony_ci		}
925d4afb5ceSopenharmony_ci		switch(c & 0xf0) {
926d4afb5ceSopenharmony_ci		case 0x10: /* literal header never index */
927d4afb5ceSopenharmony_ci		case 0:    /* literal header without indexing */
928d4afb5ceSopenharmony_ci			/*
929d4afb5ceSopenharmony_ci			 * follows 0x40 except 4-bit hdr idx
930d4afb5ceSopenharmony_ci			 * and don't add to index
931d4afb5ceSopenharmony_ci			 */
932d4afb5ceSopenharmony_ci			if (c == 0) { /* literal name */
933d4afb5ceSopenharmony_ci				h2n->hpack_type = HPKT_LITERAL_HDR_VALUE;
934d4afb5ceSopenharmony_ci				lwsl_header("   HPKT_LITERAL_HDR_VALUE\n");
935d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_HLEN;
936d4afb5ceSopenharmony_ci				h2n->value = 0;
937d4afb5ceSopenharmony_ci				break;
938d4afb5ceSopenharmony_ci			}
939d4afb5ceSopenharmony_ci			if (c == 0x10) { /* literal name NEVER */
940d4afb5ceSopenharmony_ci				h2n->hpack_type = HPKT_LITERAL_HDR_VALUE_NEVER;
941d4afb5ceSopenharmony_ci				lwsl_header("  HPKT_LITERAL_HDR_VALUE_NEVER\n");
942d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_HLEN;
943d4afb5ceSopenharmony_ci				h2n->value = 0;
944d4afb5ceSopenharmony_ci				break;
945d4afb5ceSopenharmony_ci			}
946d4afb5ceSopenharmony_ci			lwsl_header("indexed\n");
947d4afb5ceSopenharmony_ci			/* indexed name */
948d4afb5ceSopenharmony_ci			if (c & 0x10) {
949d4afb5ceSopenharmony_ci				h2n->hpack_type = HPKT_INDEXED_HDR_4_VALUE_NEVER;
950d4afb5ceSopenharmony_ci				lwsl_header("HPKT_LITERAL_HDR_4_VALUE_NEVER\n");
951d4afb5ceSopenharmony_ci			} else {
952d4afb5ceSopenharmony_ci				h2n->hpack_type = HPKT_INDEXED_HDR_4_VALUE;
953d4afb5ceSopenharmony_ci				lwsl_header("   HPKT_INDEXED_HDR_4_VALUE\n");
954d4afb5ceSopenharmony_ci			}
955d4afb5ceSopenharmony_ci			h2n->hdr_idx = 0;
956d4afb5ceSopenharmony_ci			if ((c & 0xf) == 0xf) {
957d4afb5ceSopenharmony_ci				h2n->hpack_len = c & 0xf;
958d4afb5ceSopenharmony_ci				h2n->hpack_m = 0xf;
959d4afb5ceSopenharmony_ci				h2n->hpack_len = 0;
960d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_IDX_EXT;
961d4afb5ceSopenharmony_ci				break;
962d4afb5ceSopenharmony_ci			}
963d4afb5ceSopenharmony_ci			h2n->hdr_idx = c & 0xf;
964d4afb5ceSopenharmony_ci			h2n->value = 1;
965d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_HLEN;
966d4afb5ceSopenharmony_ci			break;
967d4afb5ceSopenharmony_ci
968d4afb5ceSopenharmony_ci		case 0x20:
969d4afb5ceSopenharmony_ci		case 0x30: /* header table size update */
970d4afb5ceSopenharmony_ci			/* possibly-extended size value (5) */
971d4afb5ceSopenharmony_ci			lwsl_header("HPKT_SIZE_5 %x\n", c &0x1f);
972d4afb5ceSopenharmony_ci			h2n->hpack_type = HPKT_SIZE_5;
973d4afb5ceSopenharmony_ci			h2n->hpack_len = c & 0x1f;
974d4afb5ceSopenharmony_ci			if (h2n->hpack_len == 0x1f) {
975d4afb5ceSopenharmony_ci				h2n->hpack_m = 0x1f;
976d4afb5ceSopenharmony_ci				h2n->hpack_len = 0;
977d4afb5ceSopenharmony_ci				h2n->hpack = HPKS_IDX_EXT;
978d4afb5ceSopenharmony_ci				break;
979d4afb5ceSopenharmony_ci			}
980d4afb5ceSopenharmony_ci			h2n->last_action_dyntable_resize = 1;
981d4afb5ceSopenharmony_ci			if (lws_hpack_dynamic_size(wsi, (int)h2n->hpack_len))
982d4afb5ceSopenharmony_ci				return 1;
983d4afb5ceSopenharmony_ci			break;
984d4afb5ceSopenharmony_ci		}
985d4afb5ceSopenharmony_ci		break;
986d4afb5ceSopenharmony_ci
987d4afb5ceSopenharmony_ci	case HPKS_IDX_EXT:
988d4afb5ceSopenharmony_ci		h2n->hpack_len = (uint32_t)((unsigned int)h2n->hpack_len |
989d4afb5ceSopenharmony_ci				(unsigned int)((c & 0x7f) << h2n->ext_count));
990d4afb5ceSopenharmony_ci		h2n->ext_count = (uint8_t)(h2n->ext_count + 7);
991d4afb5ceSopenharmony_ci		if (c & 0x80) /* extended int not complete yet */
992d4afb5ceSopenharmony_ci			break;
993d4afb5ceSopenharmony_ci
994d4afb5ceSopenharmony_ci		/* extended integer done */
995d4afb5ceSopenharmony_ci		h2n->hpack_len += h2n->hpack_m;
996d4afb5ceSopenharmony_ci		lwsl_header("HPKS_IDX_EXT: hpack_len %u\n", (unsigned int)h2n->hpack_len);
997d4afb5ceSopenharmony_ci
998d4afb5ceSopenharmony_ci		switch (h2n->hpack_type) {
999d4afb5ceSopenharmony_ci		case HPKT_INDEXED_HDR_7:
1000d4afb5ceSopenharmony_ci			if (lws_hpack_use_idx_hdr(wsi, (int)h2n->hpack_len,
1001d4afb5ceSopenharmony_ci						  (int)h2n->hdr_idx)) {
1002d4afb5ceSopenharmony_ci				lwsl_notice("%s: hd7 use fail\n", __func__);
1003d4afb5ceSopenharmony_ci				return 1;
1004d4afb5ceSopenharmony_ci			}
1005d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_TYPE;
1006d4afb5ceSopenharmony_ci			break;
1007d4afb5ceSopenharmony_ci
1008d4afb5ceSopenharmony_ci		case HPKT_SIZE_5:
1009d4afb5ceSopenharmony_ci			h2n->last_action_dyntable_resize = 1;
1010d4afb5ceSopenharmony_ci			if (lws_hpack_dynamic_size(wsi, (int)h2n->hpack_len))
1011d4afb5ceSopenharmony_ci				return 1;
1012d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_TYPE;
1013d4afb5ceSopenharmony_ci			break;
1014d4afb5ceSopenharmony_ci
1015d4afb5ceSopenharmony_ci		default:
1016d4afb5ceSopenharmony_ci			h2n->hdr_idx = h2n->hpack_len;
1017d4afb5ceSopenharmony_ci			if (!h2n->hdr_idx) {
1018d4afb5ceSopenharmony_ci				lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
1019d4afb5ceSopenharmony_ci					      "extended header index was 0");
1020d4afb5ceSopenharmony_ci				return 1;
1021d4afb5ceSopenharmony_ci			}
1022d4afb5ceSopenharmony_ci			h2n->value = 1;
1023d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_HLEN;
1024d4afb5ceSopenharmony_ci			break;
1025d4afb5ceSopenharmony_ci		}
1026d4afb5ceSopenharmony_ci		break;
1027d4afb5ceSopenharmony_ci
1028d4afb5ceSopenharmony_ci	case HPKS_HLEN: /* [ H | 7+ ] */
1029d4afb5ceSopenharmony_ci		h2n->huff = !!(c & 0x80);
1030d4afb5ceSopenharmony_ci		h2n->hpack_pos = 0;
1031d4afb5ceSopenharmony_ci		h2n->hpack_len = c & 0x7f;
1032d4afb5ceSopenharmony_ci
1033d4afb5ceSopenharmony_ci		if (h2n->hpack_len == 0x7f) {
1034d4afb5ceSopenharmony_ci			h2n->hpack_m = 0x7f;
1035d4afb5ceSopenharmony_ci			h2n->hpack_len = 0;
1036d4afb5ceSopenharmony_ci			h2n->ext_count = 0;
1037d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_HLEN_EXT;
1038d4afb5ceSopenharmony_ci			break;
1039d4afb5ceSopenharmony_ci		}
1040d4afb5ceSopenharmony_ci
1041d4afb5ceSopenharmony_ci		if (h2n->value && !h2n->hpack_len) {
1042d4afb5ceSopenharmony_ci			lwsl_debug("%s: zero-length header data\n", __func__);
1043d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_TYPE;
1044d4afb5ceSopenharmony_ci			goto fin;
1045d4afb5ceSopenharmony_ci		}
1046d4afb5ceSopenharmony_ci
1047d4afb5ceSopenharmony_cipre_data:
1048d4afb5ceSopenharmony_ci		h2n->hpack = HPKS_DATA;
1049d4afb5ceSopenharmony_ci		if (!h2n->value || !h2n->hdr_idx) {
1050d4afb5ceSopenharmony_ci			ah->parser_state = WSI_TOKEN_NAME_PART;
1051d4afb5ceSopenharmony_ci			ah->lextable_pos = 0;
1052d4afb5ceSopenharmony_ci			h2n->unknown_header = 0;
1053d4afb5ceSopenharmony_ci			break;
1054d4afb5ceSopenharmony_ci		}
1055d4afb5ceSopenharmony_ci
1056d4afb5ceSopenharmony_ci		if (h2n->hpack_type == HPKT_LITERAL_HDR_VALUE ||
1057d4afb5ceSopenharmony_ci		    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR ||
1058d4afb5ceSopenharmony_ci		    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER) {
1059d4afb5ceSopenharmony_ci			n = ah->parser_state;
1060d4afb5ceSopenharmony_ci			if (n == 255) {
1061d4afb5ceSopenharmony_ci				n = -1;
1062d4afb5ceSopenharmony_ci				h2n->hdr_idx = (uint32_t)-1;
1063d4afb5ceSopenharmony_ci			} else
1064d4afb5ceSopenharmony_ci				h2n->hdr_idx = 1;
1065d4afb5ceSopenharmony_ci		} else {
1066d4afb5ceSopenharmony_ci			n = lws_token_from_index(wsi, (int)h2n->hdr_idx, NULL,
1067d4afb5ceSopenharmony_ci						 NULL, NULL);
1068d4afb5ceSopenharmony_ci			lwsl_header("  lws_tok_from_idx(%u) says %d\n",
1069d4afb5ceSopenharmony_ci				   (unsigned int)h2n->hdr_idx, n);
1070d4afb5ceSopenharmony_ci		}
1071d4afb5ceSopenharmony_ci
1072d4afb5ceSopenharmony_ci		if (n == LWS_HPACK_IGNORE_ENTRY || n == -1)
1073d4afb5ceSopenharmony_ci			h2n->hdr_idx = LWS_HPACK_IGNORE_ENTRY;
1074d4afb5ceSopenharmony_ci
1075d4afb5ceSopenharmony_ci		switch (h2n->hpack_type) {
1076d4afb5ceSopenharmony_ci		/*
1077d4afb5ceSopenharmony_ci		 * hpack types with literal headers were parsed by the lws
1078d4afb5ceSopenharmony_ci		 * header SM... on recognition of a known lws header, it does
1079d4afb5ceSopenharmony_ci		 * the correct lws_frag_start() for us already.  Other types
1080d4afb5ceSopenharmony_ci		 * (ie, indexed header) need us to do it here.
1081d4afb5ceSopenharmony_ci		 */
1082d4afb5ceSopenharmony_ci		case HPKT_LITERAL_HDR_VALUE_INCR:
1083d4afb5ceSopenharmony_ci		case HPKT_LITERAL_HDR_VALUE:
1084d4afb5ceSopenharmony_ci		case HPKT_LITERAL_HDR_VALUE_NEVER:
1085d4afb5ceSopenharmony_ci			break;
1086d4afb5ceSopenharmony_ci		default:
1087d4afb5ceSopenharmony_ci			if (n != -1 && n != LWS_HPACK_IGNORE_ENTRY &&
1088d4afb5ceSopenharmony_ci			    lws_frag_start(wsi, n)) {
1089d4afb5ceSopenharmony_ci				lwsl_header("%s: frag start failed\n",
1090d4afb5ceSopenharmony_ci					    __func__);
1091d4afb5ceSopenharmony_ci				return 1;
1092d4afb5ceSopenharmony_ci			}
1093d4afb5ceSopenharmony_ci			break;
1094d4afb5ceSopenharmony_ci		}
1095d4afb5ceSopenharmony_ci		break;
1096d4afb5ceSopenharmony_ci
1097d4afb5ceSopenharmony_ci	case HPKS_HLEN_EXT:
1098d4afb5ceSopenharmony_ci		h2n->hpack_len = (uint32_t)((unsigned int)h2n->hpack_len |
1099d4afb5ceSopenharmony_ci				(unsigned int)((c & 0x7f) << h2n->ext_count));
1100d4afb5ceSopenharmony_ci		h2n->ext_count = (uint8_t)(h2n->ext_count + 7);
1101d4afb5ceSopenharmony_ci		if (c & 0x80) /* extended integer not complete yet */
1102d4afb5ceSopenharmony_ci			break;
1103d4afb5ceSopenharmony_ci
1104d4afb5ceSopenharmony_ci		h2n->hpack_len += h2n->hpack_m;
1105d4afb5ceSopenharmony_ci		goto pre_data;
1106d4afb5ceSopenharmony_ci
1107d4afb5ceSopenharmony_ci	case HPKS_DATA:
1108d4afb5ceSopenharmony_ci		//lwsl_header(" 0x%02X huff %d\n", c, h2n->huff);
1109d4afb5ceSopenharmony_ci			c1 = c;
1110d4afb5ceSopenharmony_ci
1111d4afb5ceSopenharmony_ci		for (n = 0; n < 8; n++) {
1112d4afb5ceSopenharmony_ci			if (h2n->huff) {
1113d4afb5ceSopenharmony_ci				char b = (c >> 7) & 1;
1114d4afb5ceSopenharmony_ci				prev = h2n->hpack_pos;
1115d4afb5ceSopenharmony_ci				h2n->hpack_pos = (uint16_t)huftable_decode(
1116d4afb5ceSopenharmony_ci						(int)h2n->hpack_pos, b);
1117d4afb5ceSopenharmony_ci				c = (unsigned char)(c << 1);
1118d4afb5ceSopenharmony_ci				if (h2n->hpack_pos == 0xffff) {
1119d4afb5ceSopenharmony_ci					lwsl_notice("Huffman err\n");
1120d4afb5ceSopenharmony_ci					return 1;
1121d4afb5ceSopenharmony_ci				}
1122d4afb5ceSopenharmony_ci				if (!(h2n->hpack_pos & 0x8000)) {
1123d4afb5ceSopenharmony_ci					if (!b)
1124d4afb5ceSopenharmony_ci						h2n->zero_huff_padding = 1;
1125d4afb5ceSopenharmony_ci					h2n->huff_pad++;
1126d4afb5ceSopenharmony_ci					continue;
1127d4afb5ceSopenharmony_ci				}
1128d4afb5ceSopenharmony_ci				c1 = (uint8_t)(h2n->hpack_pos & 0x7fff);
1129d4afb5ceSopenharmony_ci				h2n->hpack_pos = 0;
1130d4afb5ceSopenharmony_ci				h2n->huff_pad = 0;
1131d4afb5ceSopenharmony_ci				h2n->zero_huff_padding = 0;
1132d4afb5ceSopenharmony_ci
1133d4afb5ceSopenharmony_ci				/* EOS |11111111|11111111|11111111|111111 */
1134d4afb5ceSopenharmony_ci				if (!c1 && prev == HUFTABLE_0x100_PREV) {
1135d4afb5ceSopenharmony_ci					lws_h2_goaway(nwsi,
1136d4afb5ceSopenharmony_ci						H2_ERR_COMPRESSION_ERROR,
1137d4afb5ceSopenharmony_ci						"Huffman EOT seen");
1138d4afb5ceSopenharmony_ci					return 1;
1139d4afb5ceSopenharmony_ci				}
1140d4afb5ceSopenharmony_ci			} else
1141d4afb5ceSopenharmony_ci				n = 8;
1142d4afb5ceSopenharmony_ci
1143d4afb5ceSopenharmony_ci			if (h2n->value) { /* value */
1144d4afb5ceSopenharmony_ci
1145d4afb5ceSopenharmony_ci				if (h2n->hdr_idx &&
1146d4afb5ceSopenharmony_ci				    h2n->hdr_idx != LWS_HPACK_IGNORE_ENTRY) {
1147d4afb5ceSopenharmony_ci
1148d4afb5ceSopenharmony_ci					if (ah->hdr_token_idx ==
1149d4afb5ceSopenharmony_ci					    WSI_TOKEN_HTTP_COLON_PATH) {
1150d4afb5ceSopenharmony_ci
1151d4afb5ceSopenharmony_ci						switch (lws_parse_urldecode(
1152d4afb5ceSopenharmony_ci								    wsi, &c1)) {
1153d4afb5ceSopenharmony_ci						case LPUR_CONTINUE:
1154d4afb5ceSopenharmony_ci							break;
1155d4afb5ceSopenharmony_ci						case LPUR_SWALLOW:
1156d4afb5ceSopenharmony_ci							goto swallow;
1157d4afb5ceSopenharmony_ci						case LPUR_EXCESSIVE:
1158d4afb5ceSopenharmony_ci						case LPUR_FORBID:
1159d4afb5ceSopenharmony_ci							lws_h2_goaway(nwsi,
1160d4afb5ceSopenharmony_ci							  H2_ERR_PROTOCOL_ERROR,
1161d4afb5ceSopenharmony_ci							  "Evil URI");
1162d4afb5ceSopenharmony_ci							return 1;
1163d4afb5ceSopenharmony_ci
1164d4afb5ceSopenharmony_ci						default:
1165d4afb5ceSopenharmony_ci							return -1;
1166d4afb5ceSopenharmony_ci						}
1167d4afb5ceSopenharmony_ci					}
1168d4afb5ceSopenharmony_ci					if (lws_frag_append(wsi, c1)) {
1169d4afb5ceSopenharmony_ci						lwsl_notice(
1170d4afb5ceSopenharmony_ci							"%s: frag app fail\n",
1171d4afb5ceSopenharmony_ci							    __func__);
1172d4afb5ceSopenharmony_ci						return 1;
1173d4afb5ceSopenharmony_ci					}
1174d4afb5ceSopenharmony_ci				} //else
1175d4afb5ceSopenharmony_ci					//lwsl_header("ignoring %c\n", c1);
1176d4afb5ceSopenharmony_ci			} else {
1177d4afb5ceSopenharmony_ci				/*
1178d4afb5ceSopenharmony_ci				 * Convert name using existing parser,
1179d4afb5ceSopenharmony_ci			 	 * If h2n->unknown_header == 0, result is
1180d4afb5ceSopenharmony_ci				 * in wsi->parser_state
1181d4afb5ceSopenharmony_ci			 	 * using WSI_TOKEN_GET_URI.
1182d4afb5ceSopenharmony_ci			 	 *
1183d4afb5ceSopenharmony_ci			 	 * If unknown header h2n->unknown_header
1184d4afb5ceSopenharmony_ci			 	 * will be set.
1185d4afb5ceSopenharmony_ci			 	 */
1186d4afb5ceSopenharmony_ci				h2n->hpack_hdr_len++;
1187d4afb5ceSopenharmony_ci				if (h2n->is_first_header_char) {
1188d4afb5ceSopenharmony_ci					h2n->is_first_header_char = 0;
1189d4afb5ceSopenharmony_ci					h2n->first_hdr_char = (char)c1;
1190d4afb5ceSopenharmony_ci				}
1191d4afb5ceSopenharmony_ci				lwsl_header("parser: %c\n", c1);
1192d4afb5ceSopenharmony_ci				/* uppercase header names illegal */
1193d4afb5ceSopenharmony_ci				if (c1 >= 'A' && c1 <= 'Z') {
1194d4afb5ceSopenharmony_ci					lws_h2_goaway(nwsi,
1195d4afb5ceSopenharmony_ci						H2_ERR_COMPRESSION_ERROR,
1196d4afb5ceSopenharmony_ci						"Uppercase literal hpack hdr");
1197d4afb5ceSopenharmony_ci					return 1;
1198d4afb5ceSopenharmony_ci				}
1199d4afb5ceSopenharmony_ci				plen = 1;
1200d4afb5ceSopenharmony_ci				if (!h2n->unknown_header &&
1201d4afb5ceSopenharmony_ci				    lws_parse(wsi, &c1, &plen))
1202d4afb5ceSopenharmony_ci					h2n->unknown_header = 1;
1203d4afb5ceSopenharmony_ci			}
1204d4afb5ceSopenharmony_ciswallow:
1205d4afb5ceSopenharmony_ci			(void)n;
1206d4afb5ceSopenharmony_ci		} // for n
1207d4afb5ceSopenharmony_ci
1208d4afb5ceSopenharmony_ci		if (--h2n->hpack_len)
1209d4afb5ceSopenharmony_ci			break;
1210d4afb5ceSopenharmony_ci
1211d4afb5ceSopenharmony_ci		/*
1212d4afb5ceSopenharmony_ci		 * The header (h2n->value = 0) or the payload (h2n->value = 1)
1213d4afb5ceSopenharmony_ci		 * is complete.
1214d4afb5ceSopenharmony_ci		 */
1215d4afb5ceSopenharmony_ci
1216d4afb5ceSopenharmony_ci		if (h2n->huff && (h2n->huff_pad > 7 ||
1217d4afb5ceSopenharmony_ci		    (h2n->zero_huff_padding && h2n->huff_pad))) {
1218d4afb5ceSopenharmony_ci			lwsl_info("zero_huff_padding: %d huff_pad: %d\n",
1219d4afb5ceSopenharmony_ci				    h2n->zero_huff_padding, h2n->huff_pad);
1220d4afb5ceSopenharmony_ci			lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
1221d4afb5ceSopenharmony_ci				      "Huffman padding excessive or wrong");
1222d4afb5ceSopenharmony_ci			return 1;
1223d4afb5ceSopenharmony_ci		}
1224d4afb5ceSopenharmony_cifin:
1225d4afb5ceSopenharmony_ci		if (!h2n->value && (
1226d4afb5ceSopenharmony_ci		    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE ||
1227d4afb5ceSopenharmony_ci		    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR ||
1228d4afb5ceSopenharmony_ci		    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER)) {
1229d4afb5ceSopenharmony_ci			h2n->hdr_idx = LWS_HPACK_IGNORE_ENTRY;
1230d4afb5ceSopenharmony_ci			lwsl_header("wsi->parser_state: %d\n",
1231d4afb5ceSopenharmony_ci					ah->parser_state);
1232d4afb5ceSopenharmony_ci
1233d4afb5ceSopenharmony_ci			if (ah->parser_state == WSI_TOKEN_NAME_PART) {
1234d4afb5ceSopenharmony_ci				/* h2 headers come without the colon */
1235d4afb5ceSopenharmony_ci				c1 = ':';
1236d4afb5ceSopenharmony_ci				plen = 1;
1237d4afb5ceSopenharmony_ci				n = lws_parse(wsi, &c1, &plen);
1238d4afb5ceSopenharmony_ci				(void)n;
1239d4afb5ceSopenharmony_ci			}
1240d4afb5ceSopenharmony_ci
1241d4afb5ceSopenharmony_ci			if (ah->parser_state == WSI_TOKEN_NAME_PART ||
1242d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CUSTOM_HEADERS)
1243d4afb5ceSopenharmony_ci			    ah->parser_state == WSI_TOKEN_UNKNOWN_VALUE_PART ||
1244d4afb5ceSopenharmony_ci#endif
1245d4afb5ceSopenharmony_ci			    ah->parser_state == WSI_TOKEN_SKIPPING) {
1246d4afb5ceSopenharmony_ci				h2n->unknown_header = 1;
1247d4afb5ceSopenharmony_ci				ah->parser_state = 0xff;
1248d4afb5ceSopenharmony_ci				wsi->seen_nonpseudoheader = 1;
1249d4afb5ceSopenharmony_ci			}
1250d4afb5ceSopenharmony_ci		}
1251d4afb5ceSopenharmony_ci
1252d4afb5ceSopenharmony_ci		/* we have the header */
1253d4afb5ceSopenharmony_ci		if (!h2n->value) {
1254d4afb5ceSopenharmony_ci			h2n->value = 1;
1255d4afb5ceSopenharmony_ci			h2n->hpack = HPKS_HLEN;
1256d4afb5ceSopenharmony_ci			h2n->huff_pad = 0;
1257d4afb5ceSopenharmony_ci			h2n->zero_huff_padding = 0;
1258d4afb5ceSopenharmony_ci			h2n->ext_count = 0;
1259d4afb5ceSopenharmony_ci			break;
1260d4afb5ceSopenharmony_ci		}
1261d4afb5ceSopenharmony_ci
1262d4afb5ceSopenharmony_ci		/*
1263d4afb5ceSopenharmony_ci		 * we have got both the header and value
1264d4afb5ceSopenharmony_ci		 */
1265d4afb5ceSopenharmony_ci
1266d4afb5ceSopenharmony_ci		m = -1;
1267d4afb5ceSopenharmony_ci		switch (h2n->hpack_type) {
1268d4afb5ceSopenharmony_ci		/*
1269d4afb5ceSopenharmony_ci		 * These are the only two that insert to the dyntable
1270d4afb5ceSopenharmony_ci		 */
1271d4afb5ceSopenharmony_ci		/* NEW indexed hdr with value */
1272d4afb5ceSopenharmony_ci		case HPKT_INDEXED_HDR_6_VALUE_INCR:
1273d4afb5ceSopenharmony_ci			/* header length is determined by known index */
1274d4afb5ceSopenharmony_ci			m = lws_token_from_index(wsi, (int)h2n->hdr_idx, NULL, NULL,
1275d4afb5ceSopenharmony_ci					&h2n->hpack_hdr_len);
1276d4afb5ceSopenharmony_ci			if (m < 0)
1277d4afb5ceSopenharmony_ci				/*
1278d4afb5ceSopenharmony_ci				 * The peer may only send known 6-bit indexes,
1279d4afb5ceSopenharmony_ci				 * there's still the possibility it sends an unset
1280d4afb5ceSopenharmony_ci				 * dynamic index that we can't succeed to look up
1281d4afb5ceSopenharmony_ci				 */
1282d4afb5ceSopenharmony_ci				return 1;
1283d4afb5ceSopenharmony_ci			goto add_it;
1284d4afb5ceSopenharmony_ci		/* NEW literal hdr with value */
1285d4afb5ceSopenharmony_ci		case HPKT_LITERAL_HDR_VALUE_INCR:
1286d4afb5ceSopenharmony_ci			/*
1287d4afb5ceSopenharmony_ci			 * hdr is a new literal, so length is already in
1288d4afb5ceSopenharmony_ci			 * h2n->hpack_hdr_len
1289d4afb5ceSopenharmony_ci			 */
1290d4afb5ceSopenharmony_ci			m = ah->parser_state;
1291d4afb5ceSopenharmony_ci			if (h2n->unknown_header ||
1292d4afb5ceSopenharmony_ci			    ah->parser_state == WSI_TOKEN_NAME_PART ||
1293d4afb5ceSopenharmony_ci			    ah->parser_state == WSI_TOKEN_SKIPPING) {
1294d4afb5ceSopenharmony_ci				if (h2n->first_hdr_char == ':') {
1295d4afb5ceSopenharmony_ci					lwsl_info("HPKT_LITERAL_HDR_VALUE_INCR:"
1296d4afb5ceSopenharmony_ci						  " end state %d unk hdr %d\n",
1297d4afb5ceSopenharmony_ci						  ah->parser_state,
1298d4afb5ceSopenharmony_ci						h2n->unknown_header);
1299d4afb5ceSopenharmony_ci					/* unknown pseudoheaders are illegal */
1300d4afb5ceSopenharmony_ci					lws_h2_goaway(nwsi,
1301d4afb5ceSopenharmony_ci						      H2_ERR_PROTOCOL_ERROR,
1302d4afb5ceSopenharmony_ci						      "Unknown pseudoheader");
1303d4afb5ceSopenharmony_ci					return 1;
1304d4afb5ceSopenharmony_ci				}
1305d4afb5ceSopenharmony_ci				m = LWS_HPACK_IGNORE_ENTRY;
1306d4afb5ceSopenharmony_ci			}
1307d4afb5ceSopenharmony_ciadd_it:
1308d4afb5ceSopenharmony_ci			/*
1309d4afb5ceSopenharmony_ci			 * mark us as having been set at the time of dynamic
1310d4afb5ceSopenharmony_ci			 * token insertion.
1311d4afb5ceSopenharmony_ci			 */
1312d4afb5ceSopenharmony_ci			ah->frags[ah->nfrag].flags |= 1;
1313d4afb5ceSopenharmony_ci
1314d4afb5ceSopenharmony_ci			if (lws_dynamic_token_insert(wsi, (int)h2n->hpack_hdr_len, m,
1315d4afb5ceSopenharmony_ci					&ah->data[ah->frags[ah->nfrag].offset],
1316d4afb5ceSopenharmony_ci					ah->frags[ah->nfrag].len)) {
1317d4afb5ceSopenharmony_ci				lwsl_notice("%s: tok_insert fail\n", __func__);
1318d4afb5ceSopenharmony_ci				return 1;
1319d4afb5ceSopenharmony_ci			}
1320d4afb5ceSopenharmony_ci			break;
1321d4afb5ceSopenharmony_ci
1322d4afb5ceSopenharmony_ci		default:
1323d4afb5ceSopenharmony_ci			break;
1324d4afb5ceSopenharmony_ci		}
1325d4afb5ceSopenharmony_ci
1326d4afb5ceSopenharmony_ci		if (h2n->hdr_idx != LWS_HPACK_IGNORE_ENTRY && lws_frag_end(wsi))
1327d4afb5ceSopenharmony_ci			return 1;
1328d4afb5ceSopenharmony_ci
1329d4afb5ceSopenharmony_ci		if (h2n->hpack_type != HPKT_INDEXED_HDR_6_VALUE_INCR) {
1330d4afb5ceSopenharmony_ci
1331d4afb5ceSopenharmony_ci			if (h2n->hpack_type == HPKT_LITERAL_HDR_VALUE ||
1332d4afb5ceSopenharmony_ci			    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR ||
1333d4afb5ceSopenharmony_ci			    h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER) {
1334d4afb5ceSopenharmony_ci				m = ah->parser_state;
1335d4afb5ceSopenharmony_ci				if (m == 255)
1336d4afb5ceSopenharmony_ci					m = -1;
1337d4afb5ceSopenharmony_ci			} else
1338d4afb5ceSopenharmony_ci				m = lws_token_from_index(wsi, (int)h2n->hdr_idx,
1339d4afb5ceSopenharmony_ci							 NULL, NULL, NULL);
1340d4afb5ceSopenharmony_ci		}
1341d4afb5ceSopenharmony_ci
1342d4afb5ceSopenharmony_ci		if (m != -1 && m != LWS_HPACK_IGNORE_ENTRY)
1343d4afb5ceSopenharmony_ci			lws_dump_header(wsi, m);
1344d4afb5ceSopenharmony_ci
1345d4afb5ceSopenharmony_ci		if (lws_hpack_handle_pseudo_rules(nwsi, wsi, m))
1346d4afb5ceSopenharmony_ci			return 1;
1347d4afb5ceSopenharmony_ci
1348d4afb5ceSopenharmony_ci		h2n->is_first_header_char = 1;
1349d4afb5ceSopenharmony_ci		h2n->hpack = HPKS_TYPE;
1350d4afb5ceSopenharmony_ci		break;
1351d4afb5ceSopenharmony_ci	}
1352d4afb5ceSopenharmony_ci
1353d4afb5ceSopenharmony_ci	return 0;
1354d4afb5ceSopenharmony_ci}
1355d4afb5ceSopenharmony_ci
1356d4afb5ceSopenharmony_ci
1357d4afb5ceSopenharmony_ci
1358d4afb5ceSopenharmony_cistatic unsigned int
1359d4afb5ceSopenharmony_cilws_h2_num_start(int starting_bits, unsigned long num)
1360d4afb5ceSopenharmony_ci{
1361d4afb5ceSopenharmony_ci	unsigned int mask = (unsigned int)((1 << starting_bits) - 1);
1362d4afb5ceSopenharmony_ci
1363d4afb5ceSopenharmony_ci	if (num < mask)
1364d4afb5ceSopenharmony_ci		return (unsigned int)num;
1365d4afb5ceSopenharmony_ci
1366d4afb5ceSopenharmony_ci	return mask;
1367d4afb5ceSopenharmony_ci}
1368d4afb5ceSopenharmony_ci
1369d4afb5ceSopenharmony_cistatic int
1370d4afb5ceSopenharmony_cilws_h2_num(int starting_bits, unsigned long num,
1371d4afb5ceSopenharmony_ci			 unsigned char **p, unsigned char *end)
1372d4afb5ceSopenharmony_ci{
1373d4afb5ceSopenharmony_ci	unsigned int mask = (unsigned int)((1 << starting_bits) - 1);
1374d4afb5ceSopenharmony_ci
1375d4afb5ceSopenharmony_ci	if (num < mask)
1376d4afb5ceSopenharmony_ci		return 0;
1377d4afb5ceSopenharmony_ci
1378d4afb5ceSopenharmony_ci	num -= mask;
1379d4afb5ceSopenharmony_ci	do {
1380d4afb5ceSopenharmony_ci		if (num > 127)
1381d4afb5ceSopenharmony_ci			*((*p)++) = (uint8_t)(0x80 | (num & 0x7f));
1382d4afb5ceSopenharmony_ci		else
1383d4afb5ceSopenharmony_ci			*((*p)++) = (uint8_t)(0x00 | (num & 0x7f));
1384d4afb5ceSopenharmony_ci		if (*p >= end)
1385d4afb5ceSopenharmony_ci			return 1;
1386d4afb5ceSopenharmony_ci		num >>= 7;
1387d4afb5ceSopenharmony_ci	} while (num);
1388d4afb5ceSopenharmony_ci
1389d4afb5ceSopenharmony_ci	return 0;
1390d4afb5ceSopenharmony_ci}
1391d4afb5ceSopenharmony_ci
1392d4afb5ceSopenharmony_ciint lws_add_http2_header_by_name(struct lws *wsi, const unsigned char *name,
1393d4afb5ceSopenharmony_ci				 const unsigned char *value, int length,
1394d4afb5ceSopenharmony_ci				 unsigned char **p, unsigned char *end)
1395d4afb5ceSopenharmony_ci{
1396d4afb5ceSopenharmony_ci	int len;
1397d4afb5ceSopenharmony_ci
1398d4afb5ceSopenharmony_ci#if defined(_DEBUG)
1399d4afb5ceSopenharmony_ci	/* value does not have to be NUL-terminated... %.*s not available on
1400d4afb5ceSopenharmony_ci	 * all platforms */
1401d4afb5ceSopenharmony_ci	if (value) {
1402d4afb5ceSopenharmony_ci		lws_strnncpy((char *)*p, (const char *)value, length,
1403d4afb5ceSopenharmony_ci				lws_ptr_diff(end, (*p)));
1404d4afb5ceSopenharmony_ci
1405d4afb5ceSopenharmony_ci		lwsl_header("%s: %p  %s:%s (len %d)\n", __func__, *p, name,
1406d4afb5ceSopenharmony_ci				(const char *)*p, length);
1407d4afb5ceSopenharmony_ci	} else {
1408d4afb5ceSopenharmony_ci		lwsl_err("%s: %p dummy copy %s (len %d)\n", __func__, *p, name, length);
1409d4afb5ceSopenharmony_ci	}
1410d4afb5ceSopenharmony_ci#endif
1411d4afb5ceSopenharmony_ci
1412d4afb5ceSopenharmony_ci	len = (int)strlen((char *)name);
1413d4afb5ceSopenharmony_ci	if (len)
1414d4afb5ceSopenharmony_ci		if (name[len - 1] == ':')
1415d4afb5ceSopenharmony_ci			len--;
1416d4afb5ceSopenharmony_ci
1417d4afb5ceSopenharmony_ci	if (wsi->mux_substream && !strncmp((const char *)name,
1418d4afb5ceSopenharmony_ci					     "transfer-encoding", (unsigned int)len)) {
1419d4afb5ceSopenharmony_ci		lwsl_header("rejecting %s\n", name);
1420d4afb5ceSopenharmony_ci
1421d4afb5ceSopenharmony_ci		return 0;
1422d4afb5ceSopenharmony_ci	}
1423d4afb5ceSopenharmony_ci
1424d4afb5ceSopenharmony_ci	if (end - *p < len + length + 8)
1425d4afb5ceSopenharmony_ci		return 1;
1426d4afb5ceSopenharmony_ci
1427d4afb5ceSopenharmony_ci	*((*p)++) = 0; /* literal hdr, literal name,  */
1428d4afb5ceSopenharmony_ci
1429d4afb5ceSopenharmony_ci	*((*p)++) = (uint8_t)(0 | (uint8_t)lws_h2_num_start(7, (unsigned long)len)); /* non-HUF */
1430d4afb5ceSopenharmony_ci	if (lws_h2_num(7, (unsigned long)len, p, end))
1431d4afb5ceSopenharmony_ci		return 1;
1432d4afb5ceSopenharmony_ci
1433d4afb5ceSopenharmony_ci	/* upper-case header names are verboten in h2, but OK on h1, so
1434d4afb5ceSopenharmony_ci	 * they're not illegal per se.  Silently convert them for h2... */
1435d4afb5ceSopenharmony_ci
1436d4afb5ceSopenharmony_ci	while(len--)
1437d4afb5ceSopenharmony_ci		*((*p)++) = (uint8_t)tolower((int)*name++);
1438d4afb5ceSopenharmony_ci
1439d4afb5ceSopenharmony_ci	*((*p)++) = (uint8_t)(0 | (uint8_t)lws_h2_num_start(7, (unsigned long)length)); /* non-HUF */
1440d4afb5ceSopenharmony_ci	if (lws_h2_num(7, (unsigned long)length, p, end))
1441d4afb5ceSopenharmony_ci		return 1;
1442d4afb5ceSopenharmony_ci
1443d4afb5ceSopenharmony_ci	if (value)
1444d4afb5ceSopenharmony_ci		memcpy(*p, value, (unsigned int)length);
1445d4afb5ceSopenharmony_ci	*p += length;
1446d4afb5ceSopenharmony_ci
1447d4afb5ceSopenharmony_ci	return 0;
1448d4afb5ceSopenharmony_ci}
1449d4afb5ceSopenharmony_ci
1450d4afb5ceSopenharmony_ciint lws_add_http2_header_by_token(struct lws *wsi, enum lws_token_indexes token,
1451d4afb5ceSopenharmony_ci				  const unsigned char *value, int length,
1452d4afb5ceSopenharmony_ci				  unsigned char **p, unsigned char *end)
1453d4afb5ceSopenharmony_ci{
1454d4afb5ceSopenharmony_ci	const unsigned char *name;
1455d4afb5ceSopenharmony_ci
1456d4afb5ceSopenharmony_ci	name = lws_token_to_string(token);
1457d4afb5ceSopenharmony_ci	if (!name)
1458d4afb5ceSopenharmony_ci		return 1;
1459d4afb5ceSopenharmony_ci
1460d4afb5ceSopenharmony_ci	return lws_add_http2_header_by_name(wsi, name, value, length, p, end);
1461d4afb5ceSopenharmony_ci}
1462d4afb5ceSopenharmony_ci
1463d4afb5ceSopenharmony_ciint lws_add_http2_header_status(struct lws *wsi, unsigned int code,
1464d4afb5ceSopenharmony_ci				unsigned char **p, unsigned char *end)
1465d4afb5ceSopenharmony_ci{
1466d4afb5ceSopenharmony_ci	unsigned char status[10];
1467d4afb5ceSopenharmony_ci	int n;
1468d4afb5ceSopenharmony_ci
1469d4afb5ceSopenharmony_ci	wsi->h2.send_END_STREAM = 0; // !!(code >= 400);
1470d4afb5ceSopenharmony_ci
1471d4afb5ceSopenharmony_ci	n = sprintf((char *)status, "%u", code);
1472d4afb5ceSopenharmony_ci	if (lws_add_http2_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_STATUS,
1473d4afb5ceSopenharmony_ci					  status, n, p, end))
1474d4afb5ceSopenharmony_ci
1475d4afb5ceSopenharmony_ci		return 1;
1476d4afb5ceSopenharmony_ci
1477d4afb5ceSopenharmony_ci	return 0;
1478d4afb5ceSopenharmony_ci}
1479