hpack.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /*
  2. * lib/hpack.c
  3. *
  4. * Copyright (C) 2014 Andy Green <andy@warmcat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. */
  21. #include "private-libwebsockets.h"
  22. /*
  23. * Official static header table for HPACK
  24. * +-------+-----------------------------+---------------+
  25. | 1 | :authority | |
  26. | 2 | :method | GET |
  27. | 3 | :method | POST |
  28. | 4 | :path | / |
  29. | 5 | :path | /index.html |
  30. | 6 | :scheme | http |
  31. | 7 | :scheme | https |
  32. | 8 | :status | 200 |
  33. | 9 | :status | 204 |
  34. | 10 | :status | 206 |
  35. | 11 | :status | 304 |
  36. | 12 | :status | 400 |
  37. | 13 | :status | 404 |
  38. | 14 | :status | 500 |
  39. | 15 | accept-charset | |
  40. | 16 | accept-encoding | gzip, deflate |
  41. | 17 | accept-language | |
  42. | 18 | accept-ranges | |
  43. | 19 | accept | |
  44. | 20 | access-control-allow-origin | |
  45. | 21 | age | |
  46. | 22 | allow | |
  47. | 23 | authorization | |
  48. | 24 | cache-control | |
  49. | 25 | content-disposition | |
  50. | 26 | content-encoding | |
  51. | 27 | content-language | |
  52. | 28 | content-length | |
  53. | 29 | content-location | |
  54. | 30 | content-range | |
  55. | 31 | content-type | |
  56. | 32 | cookie | |
  57. | 33 | date | |
  58. | 34 | etag | |
  59. | 35 | expect | |
  60. | 36 | expires | |
  61. | 37 | from | |
  62. | 38 | host | |
  63. | 39 | if-match | |
  64. | 40 | if-modified-since | |
  65. | 41 | if-none-match | |
  66. | 42 | if-range | |
  67. | 43 | if-unmodified-since | |
  68. | 44 | last-modified | |
  69. | 45 | link | |
  70. | 46 | location | |
  71. | 47 | max-forwards | |
  72. | 48 | proxy-authenticate | |
  73. | 49 | proxy-authorization | |
  74. | 50 | range | |
  75. | 51 | referer | |
  76. | 52 | refresh | |
  77. | 53 | retry-after | |
  78. | 54 | server | |
  79. | 55 | set-cookie | |
  80. | 56 | strict-transport-security | |
  81. | 57 | transfer-encoding | |
  82. | 58 | user-agent | |
  83. | 59 | vary | |
  84. | 60 | via | |
  85. | 61 | www-authenticate | |
  86. +-------+-----------------------------+---------------+
  87. */
  88. static const unsigned char static_token[] = {
  89. 0,
  90. WSI_TOKEN_HTTP_COLON_AUTHORITY,
  91. WSI_TOKEN_HTTP_COLON_METHOD,
  92. WSI_TOKEN_HTTP_COLON_METHOD,
  93. WSI_TOKEN_HTTP_COLON_PATH,
  94. WSI_TOKEN_HTTP_COLON_PATH,
  95. WSI_TOKEN_HTTP_COLON_SCHEME,
  96. WSI_TOKEN_HTTP_COLON_SCHEME,
  97. WSI_TOKEN_HTTP_COLON_STATUS,
  98. WSI_TOKEN_HTTP_COLON_STATUS,
  99. WSI_TOKEN_HTTP_COLON_STATUS,
  100. WSI_TOKEN_HTTP_COLON_STATUS,
  101. WSI_TOKEN_HTTP_COLON_STATUS,
  102. WSI_TOKEN_HTTP_COLON_STATUS,
  103. WSI_TOKEN_HTTP_COLON_STATUS,
  104. WSI_TOKEN_HTTP_ACCEPT_CHARSET,
  105. WSI_TOKEN_HTTP_ACCEPT_ENCODING,
  106. WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
  107. WSI_TOKEN_HTTP_ACCEPT_RANGES,
  108. WSI_TOKEN_HTTP_ACCEPT,
  109. WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
  110. WSI_TOKEN_HTTP_AGE,
  111. WSI_TOKEN_HTTP_ALLOW,
  112. WSI_TOKEN_HTTP_AUTHORIZATION,
  113. WSI_TOKEN_HTTP_CACHE_CONTROL,
  114. WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
  115. WSI_TOKEN_HTTP_CONTENT_ENCODING,
  116. WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
  117. WSI_TOKEN_HTTP_CONTENT_LENGTH,
  118. WSI_TOKEN_HTTP_CONTENT_LOCATION,
  119. WSI_TOKEN_HTTP_CONTENT_RANGE,
  120. WSI_TOKEN_HTTP_CONTENT_TYPE,
  121. WSI_TOKEN_HTTP_COOKIE,
  122. WSI_TOKEN_HTTP_DATE,
  123. WSI_TOKEN_HTTP_ETAG,
  124. WSI_TOKEN_HTTP_EXPECT,
  125. WSI_TOKEN_HTTP_EXPIRES,
  126. WSI_TOKEN_HTTP_FROM,
  127. WSI_TOKEN_HOST,
  128. WSI_TOKEN_HTTP_IF_MATCH,
  129. WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
  130. WSI_TOKEN_HTTP_IF_NONE_MATCH,
  131. WSI_TOKEN_HTTP_IF_RANGE,
  132. WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
  133. WSI_TOKEN_HTTP_LAST_MODIFIED,
  134. WSI_TOKEN_HTTP_LINK,
  135. WSI_TOKEN_HTTP_LOCATION,
  136. WSI_TOKEN_HTTP_MAX_FORWARDS,
  137. WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
  138. WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
  139. WSI_TOKEN_HTTP_RANGE,
  140. WSI_TOKEN_HTTP_REFERER,
  141. WSI_TOKEN_HTTP_REFRESH,
  142. WSI_TOKEN_HTTP_RETRY_AFTER,
  143. WSI_TOKEN_HTTP_SERVER,
  144. WSI_TOKEN_HTTP_SET_COOKIE,
  145. WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
  146. WSI_TOKEN_HTTP_TRANSFER_ENCODING,
  147. WSI_TOKEN_HTTP_USER_AGENT,
  148. WSI_TOKEN_HTTP_VARY,
  149. WSI_TOKEN_HTTP_VIA,
  150. WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
  151. };
  152. /* some of the entries imply values as well as header names */
  153. static const char * const http2_canned[] = {
  154. "",
  155. "",
  156. "GET",
  157. "POST",
  158. "/",
  159. "/index.html",
  160. "http",
  161. "https",
  162. "200",
  163. "204",
  164. "206",
  165. "304",
  166. "400",
  167. "404",
  168. "500",
  169. "",
  170. "gzip, deflate"
  171. };
  172. /* see minihuf.c */
  173. #include "huftable.h"
  174. static int huftable_decode(int pos, char c)
  175. {
  176. int q = pos + !!c;
  177. if (lextable_terms[q >> 3] & (1 << (q & 7))) /* terminal */
  178. return lextable[q] | 0x8000;
  179. return pos + (lextable[q] << 1);
  180. }
  181. static int lws_hpack_update_table_size(struct lws *wsi, int idx)
  182. {
  183. lwsl_info("hpack set table size %d\n", idx);
  184. return 0;
  185. }
  186. static int lws_frag_start(struct lws *wsi, int hdr_token_idx)
  187. {
  188. struct allocated_headers * ah = wsi->u.http2.http.ah;
  189. if (!hdr_token_idx) {
  190. lwsl_err("%s: zero hdr_token_idx\n", __func__);
  191. return 1;
  192. }
  193. if (ah->nfrag >= ARRAY_SIZE(ah->frag_index)) {
  194. lwsl_err("%s: frag index %d too big\n", __func__, ah->nfrag);
  195. return 1;
  196. }
  197. ah->frags[ah->nfrag].offset = ah->pos;
  198. ah->frags[ah->nfrag].len = 0;
  199. ah->frags[ah->nfrag].nfrag = 0;
  200. ah->frag_index[hdr_token_idx] = ah->nfrag;
  201. return 0;
  202. }
  203. static int lws_frag_append(struct lws *wsi, unsigned char c)
  204. {
  205. struct allocated_headers * ah = wsi->u.http2.http.ah;
  206. ah->data[ah->pos++] = c;
  207. ah->frags[ah->nfrag].len++;
  208. return ah->pos >= wsi->context->max_http_header_data;
  209. }
  210. static int lws_frag_end(struct lws *wsi)
  211. {
  212. if (lws_frag_append(wsi, 0))
  213. return 1;
  214. wsi->u.http2.http.ah->nfrag++;
  215. return 0;
  216. }
  217. static void lws_dump_header(struct lws *wsi, int hdr)
  218. {
  219. char s[200];
  220. int len = lws_hdr_copy(wsi, s, sizeof(s) - 1, hdr);
  221. s[len] = '\0';
  222. lwsl_info(" hdr tok %d (%s) = '%s'\n", hdr, lws_token_to_string(hdr), s);
  223. }
  224. static int
  225. lws_token_from_index(struct lws *wsi, int index, char **arg, int *len)
  226. {
  227. struct hpack_dynamic_table *dyn;
  228. /* dynamic table only belongs to network wsi */
  229. wsi = lws_http2_get_network_wsi(wsi);
  230. dyn = wsi->u.http2.hpack_dyn_table;
  231. if (index < ARRAY_SIZE(static_token))
  232. return static_token[index];
  233. if (!dyn)
  234. return 0;
  235. index -= ARRAY_SIZE(static_token);
  236. if (index >= dyn->num_entries)
  237. return 0;
  238. if (arg && len) {
  239. *arg = dyn->args + dyn->entries[index].arg_offset;
  240. *len = dyn->entries[index].arg_len;
  241. }
  242. return dyn->entries[index].token;
  243. }
  244. static int
  245. lws_hpack_add_dynamic_header(struct lws *wsi, int token, char *arg, int len)
  246. {
  247. struct hpack_dynamic_table *dyn;
  248. int ret = 1;
  249. wsi = lws_http2_get_network_wsi(wsi);
  250. dyn = wsi->u.http2.hpack_dyn_table;
  251. if (!dyn) {
  252. dyn = lws_zalloc(sizeof(*dyn));
  253. if (!dyn)
  254. return 1;
  255. wsi->u.http2.hpack_dyn_table = dyn;
  256. dyn->args = lws_malloc(1024);
  257. if (!dyn->args)
  258. goto bail1;
  259. dyn->args_length = 1024;
  260. dyn->entries = lws_malloc(sizeof(dyn->entries[0]) * 20);
  261. if (!dyn->entries)
  262. goto bail2;
  263. dyn->num_entries = 20;
  264. }
  265. if (dyn->next == dyn->num_entries)
  266. return 1;
  267. if (dyn->args_length - dyn->pos < len)
  268. return 1;
  269. dyn->entries[dyn->next].token = token;
  270. dyn->entries[dyn->next].arg_offset = dyn->pos;
  271. if (len)
  272. memcpy(dyn->args + dyn->pos, arg, len);
  273. dyn->entries[dyn->next].arg_len = len;
  274. lwsl_info("%s: added dynamic hdr %d, token %d (%s), len %d\n",
  275. __func__, dyn->next, token, lws_token_to_string(token), len);
  276. dyn->pos += len;
  277. dyn->next++;
  278. return 0;
  279. bail2:
  280. lws_free(dyn->args);
  281. bail1:
  282. lws_free(dyn);
  283. wsi->u.http2.hpack_dyn_table = NULL;
  284. return ret;
  285. }
  286. static int lws_write_indexed_hdr(struct lws *wsi, int idx)
  287. {
  288. const char *p;
  289. int tok = lws_token_from_index(wsi, idx, NULL, 0);
  290. lwsl_info("writing indexed hdr %d (tok %d '%s')\n", idx, tok,
  291. lws_token_to_string(tok));
  292. if (lws_frag_start(wsi, tok))
  293. return 1;
  294. if (idx < ARRAY_SIZE(http2_canned)) {
  295. p = http2_canned[idx];
  296. while (*p)
  297. if (lws_frag_append(wsi, *p++))
  298. return 1;
  299. }
  300. if (lws_frag_end(wsi))
  301. return 1;
  302. lws_dump_header(wsi, tok);
  303. return 0;
  304. }
  305. int lws_hpack_interpret(struct lws *wsi, unsigned char c)
  306. {
  307. unsigned int prev;
  308. unsigned char c1;
  309. int n;
  310. lwsl_debug(" state %d\n", wsi->u.http2.hpack);
  311. switch (wsi->u.http2.hpack) {
  312. case HPKS_OPT_PADDING:
  313. wsi->u.http2.padding = c;
  314. lwsl_info("padding %d\n", c);
  315. if (wsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
  316. wsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
  317. wsi->u.http2.hpack_m = 4;
  318. } else
  319. wsi->u.http2.hpack = HPKS_TYPE;
  320. break;
  321. case HKPS_OPT_E_DEPENDENCY:
  322. wsi->u.http2.hpack_e_dep <<= 8;
  323. wsi->u.http2.hpack_e_dep |= c;
  324. if (! --wsi->u.http2.hpack_m) {
  325. lwsl_info("hpack_e_dep = 0x%x\n", wsi->u.http2.hpack_e_dep);
  326. wsi->u.http2.hpack = HKPS_OPT_WEIGHT;
  327. }
  328. break;
  329. case HKPS_OPT_WEIGHT:
  330. /* weight */
  331. wsi->u.http2.hpack = HPKS_TYPE;
  332. break;
  333. case HPKS_TYPE:
  334. if (wsi->u.http2.count > (wsi->u.http2.length - wsi->u.http2.padding)) {
  335. lwsl_info("padding eat\n");
  336. break;
  337. }
  338. if (c & 0x80) { /* indexed header field only */
  339. /* just a possibly-extended integer */
  340. wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_7;
  341. lwsl_debug("HKPS_TYPE setting header_index %d\n", c & 0x7f);
  342. wsi->u.http2.header_index = c & 0x7f;
  343. if ((c & 0x7f) == 0x7f) {
  344. wsi->u.http2.hpack_len = c & 0x7f;
  345. wsi->u.http2.hpack_m = 0;
  346. wsi->u.http2.hpack = HPKS_IDX_EXT;
  347. break;
  348. }
  349. lwsl_debug("HKPS_TYPE: %d\n", c & 0x7f);
  350. if (lws_write_indexed_hdr(wsi, c & 0x7f))
  351. return 1;
  352. /* stay at same state */
  353. break;
  354. }
  355. if (c & 0x40) { /* literal header incr idx */
  356. /*
  357. * [possibly-extended hdr idx (6) | new literal hdr name]
  358. * H + possibly-extended value length
  359. * literal value
  360. */
  361. lwsl_debug("HKPS_TYPE 2 setting header_index %d\n", 0);
  362. wsi->u.http2.header_index = 0;
  363. if (c == 0x40) { /* literal name */
  364. wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE_INCR;
  365. wsi->u.http2.value = 0;
  366. wsi->u.http2.hpack = HPKS_HLEN;
  367. break;
  368. }
  369. /* indexed name */
  370. wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_6_VALUE_INCR;
  371. if ((c & 0x3f) == 0x3f) {
  372. wsi->u.http2.hpack_len = c & 0x3f;
  373. wsi->u.http2.hpack_m = 0;
  374. wsi->u.http2.hpack = HPKS_IDX_EXT;
  375. break;
  376. }
  377. lwsl_debug("HKPS_TYPE 3 setting header_index %d\n", c & 0x3f);
  378. wsi->u.http2.header_index = c & 0x3f;
  379. wsi->u.http2.value = 1;
  380. wsi->u.http2.hpack = HPKS_HLEN;
  381. break;
  382. }
  383. switch(c & 0xf0) {
  384. case 0x10: /* literal header never index */
  385. case 0: /* literal header without indexing */
  386. /*
  387. * follows 0x40 except 4-bit hdr idx
  388. * and don't add to index
  389. */
  390. if (c == 0) { /* literal name */
  391. wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE;
  392. wsi->u.http2.hpack = HPKS_HLEN;
  393. wsi->u.http2.value = 0;
  394. break;
  395. }
  396. //lwsl_debug("indexed\n");
  397. /* indexed name */
  398. wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_4_VALUE;
  399. wsi->u.http2.header_index = 0;
  400. if ((c & 0xf) == 0xf) {
  401. wsi->u.http2.hpack_len = c & 0xf;
  402. wsi->u.http2.hpack_m = 0;
  403. wsi->u.http2.hpack = HPKS_IDX_EXT;
  404. break;
  405. }
  406. //lwsl_err("HKPS_TYPE 5 setting header_index %d\n", c & 0xf);
  407. wsi->u.http2.header_index = c & 0xf;
  408. wsi->u.http2.value = 1;
  409. wsi->u.http2.hpack = HPKS_HLEN;
  410. break;
  411. case 0x20:
  412. case 0x30: /* header table size update */
  413. /* possibly-extended size value (5) */
  414. wsi->u.http2.hpack_type = HPKT_SIZE_5;
  415. if ((c & 0x1f) == 0x1f) {
  416. wsi->u.http2.hpack_len = c & 0x1f;
  417. wsi->u.http2.hpack_m = 0;
  418. wsi->u.http2.hpack = HPKS_IDX_EXT;
  419. break;
  420. }
  421. lws_hpack_update_table_size(wsi, c & 0x1f);
  422. /* stay at HPKS_TYPE state */
  423. break;
  424. }
  425. break;
  426. case HPKS_IDX_EXT:
  427. wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m;
  428. wsi->u.http2.hpack_m += 7;
  429. if (!(c & 0x80)) {
  430. switch (wsi->u.http2.hpack_type) {
  431. case HPKT_INDEXED_HDR_7:
  432. //lwsl_err("HKPS_IDX_EXT hdr idx %d\n", wsi->u.http2.hpack_len);
  433. if (lws_write_indexed_hdr(wsi, wsi->u.http2.hpack_len))
  434. return 1;
  435. wsi->u.http2.hpack = HPKS_TYPE;
  436. break;
  437. default:
  438. // lwsl_err("HKPS_IDX_EXT setting header_index %d\n",
  439. // wsi->u.http2.hpack_len);
  440. wsi->u.http2.header_index = wsi->u.http2.hpack_len;
  441. wsi->u.http2.value = 1;
  442. wsi->u.http2.hpack = HPKS_HLEN;
  443. break;
  444. }
  445. }
  446. break;
  447. case HPKS_HLEN: /* [ H | 7+ ] */
  448. wsi->u.http2.huff = !!(c & 0x80);
  449. wsi->u.http2.hpack_pos = 0;
  450. wsi->u.http2.hpack_len = c & 0x7f;
  451. if (wsi->u.http2.hpack_len < 0x7f) {
  452. pre_data:
  453. if (wsi->u.http2.value) {
  454. if (wsi->u.http2.header_index)
  455. if (lws_frag_start(wsi, lws_token_from_index(wsi,
  456. wsi->u.http2.header_index,
  457. NULL, NULL))) {
  458. // lwsl_notice("%s: hlen failed\n", __func__);
  459. return 1;
  460. }
  461. } else
  462. wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
  463. wsi->u.http2.hpack = HPKS_DATA;
  464. break;
  465. }
  466. wsi->u.http2.hpack_m = 0;
  467. wsi->u.http2.hpack = HPKS_HLEN_EXT;
  468. break;
  469. case HPKS_HLEN_EXT:
  470. wsi->u.http2.hpack_len += (c & 0x7f) <<
  471. wsi->u.http2.hpack_m;
  472. wsi->u.http2.hpack_m += 7;
  473. if (!(c & 0x80))
  474. goto pre_data;
  475. break;
  476. case HPKS_DATA:
  477. for (n = 0; n < 8; n++) {
  478. if (wsi->u.http2.huff) {
  479. prev = wsi->u.http2.hpack_pos;
  480. wsi->u.http2.hpack_pos = huftable_decode(
  481. wsi->u.http2.hpack_pos,
  482. (c >> 7) & 1);
  483. c <<= 1;
  484. if (wsi->u.http2.hpack_pos == 0xffff)
  485. return 1;
  486. if (!(wsi->u.http2.hpack_pos & 0x8000))
  487. continue;
  488. c1 = wsi->u.http2.hpack_pos & 0x7fff;
  489. wsi->u.http2.hpack_pos = 0;
  490. if (!c1 && prev == HUFTABLE_0x100_PREV)
  491. ; /* EOT */
  492. } else {
  493. n = 8;
  494. c1 = c;
  495. }
  496. if (wsi->u.http2.value) { /* value */
  497. if (wsi->u.http2.header_index)
  498. if (lws_frag_append(wsi, c1))
  499. return 1;
  500. } else { /* name */
  501. if (lws_parse(wsi, c1))
  502. return 1;
  503. }
  504. }
  505. if (--wsi->u.http2.hpack_len == 0) {
  506. switch (wsi->u.http2.hpack_type) {
  507. case HPKT_LITERAL_HDR_VALUE_INCR:
  508. case HPKT_INDEXED_HDR_6_VALUE_INCR: // !!!
  509. if (lws_hpack_add_dynamic_header(wsi,
  510. lws_token_from_index(wsi,
  511. wsi->u.http2.header_index,
  512. NULL, NULL), NULL, 0))
  513. return 1;
  514. break;
  515. default:
  516. break;
  517. }
  518. n = 8;
  519. if (wsi->u.http2.value) {
  520. if (lws_frag_end(wsi))
  521. return 1;
  522. // lwsl_err("data\n");
  523. lws_dump_header(wsi, lws_token_from_index(
  524. wsi, wsi->u.http2.header_index,
  525. NULL, NULL));
  526. if (wsi->u.http2.count + wsi->u.http2.padding ==
  527. wsi->u.http2.length)
  528. wsi->u.http2.hpack = HKPS_OPT_DISCARD_PADDING;
  529. else
  530. wsi->u.http2.hpack = HPKS_TYPE;
  531. } else { /* name */
  532. //if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT)
  533. wsi->u.http2.value = 1;
  534. wsi->u.http2.hpack = HPKS_HLEN;
  535. }
  536. }
  537. break;
  538. case HKPS_OPT_DISCARD_PADDING:
  539. lwsl_info("eating padding %x\n", c);
  540. if (! --wsi->u.http2.padding)
  541. wsi->u.http2.hpack = HPKS_TYPE;
  542. break;
  543. }
  544. return 0;
  545. }
  546. static int lws_http2_num(int starting_bits, unsigned long num,
  547. unsigned char **p, unsigned char *end)
  548. {
  549. int mask = (1 << starting_bits) - 1;
  550. if (num < mask) {
  551. *((*p)++) |= num;
  552. return *p >= end;
  553. }
  554. *((*p)++) |= mask;
  555. if (*p >= end)
  556. return 1;
  557. num -= mask;
  558. while (num >= 128) {
  559. *((*p)++) = 0x80 | (num & 0x7f);
  560. if (*p >= end)
  561. return 1;
  562. num >>= 7;
  563. }
  564. return 0;
  565. }
  566. int lws_add_http2_header_by_name(struct lws *wsi,
  567. const unsigned char *name,
  568. const unsigned char *value, int length,
  569. unsigned char **p, unsigned char *end)
  570. {
  571. int len;
  572. lwsl_info("%s: %p %s:%s\n", __func__, *p, name, value);
  573. len = strlen((char *)name);
  574. if (len)
  575. if (name[len - 1] == ':')
  576. len--;
  577. if (end - *p < len + length + 8)
  578. return 1;
  579. *((*p)++) = 0; /* not indexed, literal name */
  580. **p = 0; /* non-HUF */
  581. if (lws_http2_num(7, len, p, end))
  582. return 1;
  583. memcpy(*p, name, len);
  584. *p += len;
  585. *(*p) = 0; /* non-HUF */
  586. if (lws_http2_num(7, length, p, end))
  587. return 1;
  588. memcpy(*p, value, length);
  589. *p += length;
  590. return 0;
  591. }
  592. int lws_add_http2_header_by_token(struct lws *wsi, enum lws_token_indexes token,
  593. const unsigned char *value, int length,
  594. unsigned char **p, unsigned char *end)
  595. {
  596. const unsigned char *name;
  597. name = lws_token_to_string(token);
  598. if (!name)
  599. return 1;
  600. return lws_add_http2_header_by_name(wsi, name, value, length, p, end);
  601. }
  602. int lws_add_http2_header_status(struct lws *wsi,
  603. unsigned int code, unsigned char **p,
  604. unsigned char *end)
  605. {
  606. unsigned char status[10];
  607. int n;
  608. wsi->u.http2.send_END_STREAM = !!(code >= 400);
  609. n = sprintf((char *)status, "%u", code);
  610. if (lws_add_http2_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_STATUS,
  611. status, n, p, end))
  612. return 1;
  613. return 0;
  614. }