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