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