nghttp2_frame.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. /*
  2. * Copyright (C) 2015-2018 Alibaba Group Holding Limited
  3. */
  4. #include "nghttp2_frame.h"
  5. #include <string.h>
  6. #include <assert.h>
  7. #include <stdio.h>
  8. #include <errno.h>
  9. #include "nghttp2_helper.h"
  10. #include "nghttp2_net.h"
  11. #include "nghttp2_priority_spec.h"
  12. #include "nghttp2_debug.h"
  13. void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) {
  14. nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
  15. buf[3] = hd->type;
  16. buf[4] = hd->flags;
  17. nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id);
  18. /* ignore hd->reserved for now */
  19. }
  20. void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf) {
  21. hd->length = nghttp2_get_uint32(&buf[0]) >> 8;
  22. hd->type = buf[3];
  23. hd->flags = buf[4];
  24. hd->stream_id = nghttp2_get_uint32(&buf[5]) & NGHTTP2_STREAM_ID_MASK;
  25. hd->reserved = 0;
  26. }
  27. void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
  28. uint8_t flags, int32_t stream_id) {
  29. hd->length = length;
  30. hd->type = type;
  31. hd->flags = flags;
  32. hd->stream_id = stream_id;
  33. hd->reserved = 0;
  34. }
  35. void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
  36. int32_t stream_id, nghttp2_headers_category cat,
  37. const nghttp2_priority_spec *pri_spec,
  38. nghttp2_nv *nva, size_t nvlen) {
  39. nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_HEADERS, flags, stream_id);
  40. frame->padlen = 0;
  41. frame->nva = nva;
  42. frame->nvlen = nvlen;
  43. frame->cat = cat;
  44. if (pri_spec) {
  45. frame->pri_spec = *pri_spec;
  46. } else {
  47. nghttp2_priority_spec_default_init(&frame->pri_spec);
  48. }
  49. }
  50. void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem) {
  51. nghttp2_nv_array_del(frame->nva, mem);
  52. }
  53. void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
  54. const nghttp2_priority_spec *pri_spec) {
  55. nghttp2_frame_hd_init(&frame->hd, NGHTTP2_PRIORITY_SPECLEN, NGHTTP2_PRIORITY,
  56. NGHTTP2_FLAG_NONE, stream_id);
  57. frame->pri_spec = *pri_spec;
  58. }
  59. void nghttp2_frame_priority_free(nghttp2_priority *frame) { (void)frame; }
  60. void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
  61. uint32_t error_code) {
  62. nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE,
  63. stream_id);
  64. frame->error_code = error_code;
  65. }
  66. void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame) { (void)frame; }
  67. void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
  68. nghttp2_settings_entry *iv, size_t niv) {
  69. nghttp2_frame_hd_init(&frame->hd, niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH,
  70. NGHTTP2_SETTINGS, flags, 0);
  71. frame->niv = niv;
  72. frame->iv = iv;
  73. }
  74. void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem) {
  75. nghttp2_mem_free(mem, frame->iv);
  76. }
  77. void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
  78. int32_t stream_id,
  79. int32_t promised_stream_id,
  80. nghttp2_nv *nva, size_t nvlen) {
  81. nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_PUSH_PROMISE, flags, stream_id);
  82. frame->padlen = 0;
  83. frame->nva = nva;
  84. frame->nvlen = nvlen;
  85. frame->promised_stream_id = promised_stream_id;
  86. frame->reserved = 0;
  87. }
  88. void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame,
  89. nghttp2_mem *mem) {
  90. nghttp2_nv_array_del(frame->nva, mem);
  91. }
  92. void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
  93. const uint8_t *opaque_data) {
  94. nghttp2_frame_hd_init(&frame->hd, 8, NGHTTP2_PING, flags, 0);
  95. if (opaque_data) {
  96. memcpy(frame->opaque_data, opaque_data, sizeof(frame->opaque_data));
  97. } else {
  98. memset(frame->opaque_data, 0, sizeof(frame->opaque_data));
  99. }
  100. }
  101. void nghttp2_frame_ping_free(nghttp2_ping *frame) { (void)frame; }
  102. void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
  103. uint32_t error_code, uint8_t *opaque_data,
  104. size_t opaque_data_len) {
  105. nghttp2_frame_hd_init(&frame->hd, 8 + opaque_data_len, NGHTTP2_GOAWAY,
  106. NGHTTP2_FLAG_NONE, 0);
  107. frame->last_stream_id = last_stream_id;
  108. frame->error_code = error_code;
  109. frame->opaque_data = opaque_data;
  110. frame->opaque_data_len = opaque_data_len;
  111. frame->reserved = 0;
  112. }
  113. void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem) {
  114. nghttp2_mem_free(mem, frame->opaque_data);
  115. }
  116. void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
  117. uint8_t flags, int32_t stream_id,
  118. int32_t window_size_increment) {
  119. nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags, stream_id);
  120. frame->window_size_increment = window_size_increment;
  121. frame->reserved = 0;
  122. }
  123. void nghttp2_frame_window_update_free(nghttp2_window_update *frame) {
  124. (void)frame;
  125. }
  126. size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) {
  127. /* We have iframe->padlen == 0, but iframe->frame.hd.flags may have
  128. NGHTTP2_FLAG_PADDED set. This happens when receiving
  129. CONTINUATION frame, since we don't reset flags after HEADERS was
  130. received. */
  131. if (padlen == 0) {
  132. return 0;
  133. }
  134. return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0);
  135. }
  136. void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
  137. int32_t stream_id) {
  138. /* At this moment, the length of DATA frame is unknown */
  139. nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id);
  140. frame->padlen = 0;
  141. }
  142. void nghttp2_frame_data_free(nghttp2_data *frame) { (void)frame; }
  143. void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
  144. uint8_t flags, int32_t stream_id,
  145. void *payload) {
  146. nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id);
  147. frame->payload = payload;
  148. }
  149. void nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; }
  150. void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
  151. uint8_t *origin, size_t origin_len,
  152. uint8_t *field_value, size_t field_value_len) {
  153. nghttp2_ext_altsvc *altsvc;
  154. nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len,
  155. NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id);
  156. altsvc = frame->payload;
  157. altsvc->origin = origin;
  158. altsvc->origin_len = origin_len;
  159. altsvc->field_value = field_value;
  160. altsvc->field_value_len = field_value_len;
  161. }
  162. void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
  163. nghttp2_ext_altsvc *altsvc;
  164. altsvc = frame->payload;
  165. /* We use the same buffer for altsvc->origin and
  166. altsvc->field_value. */
  167. nghttp2_mem_free(mem, altsvc->origin);
  168. }
  169. size_t nghttp2_frame_priority_len(uint8_t flags) {
  170. if (flags & NGHTTP2_FLAG_PRIORITY) {
  171. return NGHTTP2_PRIORITY_SPECLEN;
  172. }
  173. return 0;
  174. }
  175. size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) {
  176. return nghttp2_frame_priority_len(frame->hd.flags);
  177. }
  178. /*
  179. * Call this function after payload was serialized, but not before
  180. * changing buf->pos and serializing frame header.
  181. *
  182. * This function assumes bufs->cur points to the last buf chain of the
  183. * frame(s).
  184. *
  185. * This function serializes frame header for HEADERS/PUSH_PROMISE and
  186. * handles their successive CONTINUATION frames.
  187. *
  188. * We don't process any padding here.
  189. */
  190. static int frame_pack_headers_shared(nghttp2_bufs *bufs,
  191. nghttp2_frame_hd *frame_hd) {
  192. nghttp2_buf *buf;
  193. nghttp2_buf_chain *ci, *ce;
  194. nghttp2_frame_hd hd;
  195. buf = &bufs->head->buf;
  196. hd = *frame_hd;
  197. hd.length = nghttp2_buf_len(buf);
  198. DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length);
  199. /* We have multiple frame buffers, which means one or more
  200. CONTINUATION frame is involved. Remove END_HEADERS flag from the
  201. first frame. */
  202. if (bufs->head != bufs->cur) {
  203. hd.flags = (uint8_t)(hd.flags & ~NGHTTP2_FLAG_END_HEADERS);
  204. }
  205. buf->pos -= NGHTTP2_FRAME_HDLEN;
  206. nghttp2_frame_pack_frame_hd(buf->pos, &hd);
  207. if (bufs->head != bufs->cur) {
  208. /* 2nd and later frames are CONTINUATION frames. */
  209. hd.type = NGHTTP2_CONTINUATION;
  210. /* We don't have no flags except for last CONTINUATION */
  211. hd.flags = NGHTTP2_FLAG_NONE;
  212. ce = bufs->cur;
  213. for (ci = bufs->head->next; ci != ce; ci = ci->next) {
  214. buf = &ci->buf;
  215. hd.length = nghttp2_buf_len(buf);
  216. DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length);
  217. buf->pos -= NGHTTP2_FRAME_HDLEN;
  218. nghttp2_frame_pack_frame_hd(buf->pos, &hd);
  219. }
  220. buf = &ci->buf;
  221. hd.length = nghttp2_buf_len(buf);
  222. /* Set END_HEADERS flag for last CONTINUATION */
  223. hd.flags = NGHTTP2_FLAG_END_HEADERS;
  224. DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length);
  225. buf->pos -= NGHTTP2_FRAME_HDLEN;
  226. nghttp2_frame_pack_frame_hd(buf->pos, &hd);
  227. }
  228. return 0;
  229. }
  230. int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
  231. nghttp2_hd_deflater *deflater) {
  232. size_t nv_offset;
  233. int rv;
  234. nghttp2_buf *buf;
  235. assert(bufs->head == bufs->cur);
  236. nv_offset = nghttp2_frame_headers_payload_nv_offset(frame);
  237. buf = &bufs->cur->buf;
  238. buf->pos += nv_offset;
  239. buf->last = buf->pos;
  240. /* This call will adjust buf->last to the correct position */
  241. rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
  242. if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
  243. rv = NGHTTP2_ERR_HEADER_COMP;
  244. }
  245. buf->pos -= nv_offset;
  246. if (rv != 0) {
  247. return rv;
  248. }
  249. if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
  250. nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec);
  251. }
  252. frame->padlen = 0;
  253. frame->hd.length = nghttp2_bufs_len(bufs);
  254. return frame_pack_headers_shared(bufs, &frame->hd);
  255. }
  256. void nghttp2_frame_pack_priority_spec(uint8_t *buf,
  257. const nghttp2_priority_spec *pri_spec) {
  258. nghttp2_put_uint32be(buf, (uint32_t)pri_spec->stream_id);
  259. if (pri_spec->exclusive) {
  260. buf[0] |= 0x80;
  261. }
  262. buf[4] = (uint8_t)(pri_spec->weight - 1);
  263. }
  264. void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
  265. const uint8_t *payload) {
  266. int32_t dep_stream_id;
  267. uint8_t exclusive;
  268. int32_t weight;
  269. dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
  270. exclusive = (payload[0] & 0x80) > 0;
  271. weight = payload[4] + 1;
  272. nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive);
  273. }
  274. int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
  275. const uint8_t *payload) {
  276. if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
  277. nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
  278. } else {
  279. nghttp2_priority_spec_default_init(&frame->pri_spec);
  280. }
  281. frame->nva = NULL;
  282. frame->nvlen = 0;
  283. return 0;
  284. }
  285. int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
  286. nghttp2_buf *buf;
  287. assert(bufs->head == bufs->cur);
  288. buf = &bufs->head->buf;
  289. assert(nghttp2_buf_avail(buf) >= NGHTTP2_PRIORITY_SPECLEN);
  290. buf->pos -= NGHTTP2_FRAME_HDLEN;
  291. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  292. nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec);
  293. buf->last += NGHTTP2_PRIORITY_SPECLEN;
  294. return 0;
  295. }
  296. void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
  297. const uint8_t *payload) {
  298. nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
  299. }
  300. int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
  301. nghttp2_rst_stream *frame) {
  302. nghttp2_buf *buf;
  303. assert(bufs->head == bufs->cur);
  304. buf = &bufs->head->buf;
  305. assert(nghttp2_buf_avail(buf) >= 4);
  306. buf->pos -= NGHTTP2_FRAME_HDLEN;
  307. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  308. nghttp2_put_uint32be(buf->last, frame->error_code);
  309. buf->last += 4;
  310. return 0;
  311. }
  312. void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
  313. const uint8_t *payload) {
  314. frame->error_code = nghttp2_get_uint32(payload);
  315. }
  316. int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) {
  317. nghttp2_buf *buf;
  318. assert(bufs->head == bufs->cur);
  319. buf = &bufs->head->buf;
  320. if (nghttp2_buf_avail(buf) < frame->hd.length) {
  321. return NGHTTP2_ERR_FRAME_SIZE_ERROR;
  322. }
  323. buf->pos -= NGHTTP2_FRAME_HDLEN;
  324. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  325. buf->last +=
  326. nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv);
  327. return 0;
  328. }
  329. size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
  330. const nghttp2_settings_entry *iv,
  331. size_t niv) {
  332. size_t i;
  333. for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
  334. nghttp2_put_uint16be(buf, (uint16_t)iv[i].settings_id);
  335. nghttp2_put_uint32be(buf + 2, iv[i].value);
  336. }
  337. return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv;
  338. }
  339. void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
  340. nghttp2_settings_entry *iv,
  341. size_t niv) {
  342. frame->iv = iv;
  343. frame->niv = niv;
  344. }
  345. void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
  346. const uint8_t *payload) {
  347. iv->settings_id = nghttp2_get_uint16(&payload[0]);
  348. iv->value = nghttp2_get_uint32(&payload[2]);
  349. }
  350. int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
  351. size_t *niv_ptr,
  352. const uint8_t *payload,
  353. size_t payloadlen,
  354. nghttp2_mem *mem) {
  355. size_t i;
  356. *niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
  357. if (*niv_ptr == 0) {
  358. *iv_ptr = NULL;
  359. return 0;
  360. }
  361. *iv_ptr =
  362. nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry));
  363. if (*iv_ptr == NULL) {
  364. return NGHTTP2_ERR_NOMEM;
  365. }
  366. for (i = 0; i < *niv_ptr; ++i) {
  367. size_t off = i * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
  368. nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]);
  369. }
  370. return 0;
  371. }
  372. int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
  373. nghttp2_push_promise *frame,
  374. nghttp2_hd_deflater *deflater) {
  375. size_t nv_offset = 4;
  376. int rv;
  377. nghttp2_buf *buf;
  378. assert(bufs->head == bufs->cur);
  379. buf = &bufs->cur->buf;
  380. buf->pos += nv_offset;
  381. buf->last = buf->pos;
  382. /* This call will adjust buf->last to the correct position */
  383. rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
  384. if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
  385. rv = NGHTTP2_ERR_HEADER_COMP;
  386. }
  387. buf->pos -= nv_offset;
  388. if (rv != 0) {
  389. return rv;
  390. }
  391. nghttp2_put_uint32be(buf->pos, (uint32_t)frame->promised_stream_id);
  392. frame->padlen = 0;
  393. frame->hd.length = nghttp2_bufs_len(bufs);
  394. return frame_pack_headers_shared(bufs, &frame->hd);
  395. }
  396. int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
  397. const uint8_t *payload) {
  398. frame->promised_stream_id =
  399. nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
  400. frame->nva = NULL;
  401. frame->nvlen = 0;
  402. return 0;
  403. }
  404. int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
  405. nghttp2_buf *buf;
  406. assert(bufs->head == bufs->cur);
  407. buf = &bufs->head->buf;
  408. assert(nghttp2_buf_avail(buf) >= 8);
  409. buf->pos -= NGHTTP2_FRAME_HDLEN;
  410. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  411. buf->last =
  412. nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
  413. return 0;
  414. }
  415. void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
  416. const uint8_t *payload) {
  417. memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
  418. }
  419. int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) {
  420. int rv;
  421. nghttp2_buf *buf;
  422. assert(bufs->head == bufs->cur);
  423. buf = &bufs->head->buf;
  424. buf->pos -= NGHTTP2_FRAME_HDLEN;
  425. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  426. nghttp2_put_uint32be(buf->last, (uint32_t)frame->last_stream_id);
  427. buf->last += 4;
  428. nghttp2_put_uint32be(buf->last, frame->error_code);
  429. buf->last += 4;
  430. rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len);
  431. if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
  432. return NGHTTP2_ERR_FRAME_SIZE_ERROR;
  433. }
  434. if (rv != 0) {
  435. return rv;
  436. }
  437. return 0;
  438. }
  439. void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
  440. const uint8_t *payload,
  441. uint8_t *var_gift_payload,
  442. size_t var_gift_payloadlen) {
  443. frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
  444. frame->error_code = nghttp2_get_uint32(payload + 4);
  445. frame->opaque_data = var_gift_payload;
  446. frame->opaque_data_len = var_gift_payloadlen;
  447. }
  448. int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
  449. const uint8_t *payload,
  450. size_t payloadlen, nghttp2_mem *mem) {
  451. uint8_t *var_gift_payload;
  452. size_t var_gift_payloadlen;
  453. if (payloadlen > 8) {
  454. var_gift_payloadlen = payloadlen - 8;
  455. } else {
  456. var_gift_payloadlen = 0;
  457. }
  458. payloadlen -= var_gift_payloadlen;
  459. if (!var_gift_payloadlen) {
  460. var_gift_payload = NULL;
  461. } else {
  462. var_gift_payload = nghttp2_mem_malloc(mem, var_gift_payloadlen);
  463. if (var_gift_payload == NULL) {
  464. return NGHTTP2_ERR_NOMEM;
  465. }
  466. memcpy(var_gift_payload, payload + 8, var_gift_payloadlen);
  467. }
  468. nghttp2_frame_unpack_goaway_payload(frame, payload, var_gift_payload,
  469. var_gift_payloadlen);
  470. return 0;
  471. }
  472. int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
  473. nghttp2_window_update *frame) {
  474. nghttp2_buf *buf;
  475. assert(bufs->head == bufs->cur);
  476. buf = &bufs->head->buf;
  477. assert(nghttp2_buf_avail(buf) >= 4);
  478. buf->pos -= NGHTTP2_FRAME_HDLEN;
  479. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  480. nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment);
  481. buf->last += 4;
  482. return 0;
  483. }
  484. void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
  485. const uint8_t *payload) {
  486. frame->window_size_increment =
  487. nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
  488. }
  489. int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
  490. int rv;
  491. nghttp2_buf *buf;
  492. nghttp2_ext_altsvc *altsvc;
  493. /* This is required with --disable-assert. */
  494. (void)rv;
  495. altsvc = frame->payload;
  496. buf = &bufs->head->buf;
  497. assert(nghttp2_buf_avail(buf) >=
  498. 2 + altsvc->origin_len + altsvc->field_value_len);
  499. buf->pos -= NGHTTP2_FRAME_HDLEN;
  500. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  501. nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len);
  502. buf->last += 2;
  503. rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len);
  504. assert(rv == 0);
  505. rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len);
  506. assert(rv == 0);
  507. return 0;
  508. }
  509. void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
  510. size_t origin_len, uint8_t *payload,
  511. size_t payloadlen) {
  512. nghttp2_ext_altsvc *altsvc;
  513. uint8_t *p;
  514. altsvc = frame->payload;
  515. p = payload;
  516. altsvc->origin = p;
  517. p += origin_len;
  518. altsvc->origin_len = origin_len;
  519. altsvc->field_value = p;
  520. altsvc->field_value_len = (size_t)(payload + payloadlen - p);
  521. }
  522. int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
  523. const uint8_t *payload,
  524. size_t payloadlen, nghttp2_mem *mem) {
  525. uint8_t *buf;
  526. size_t origin_len;
  527. if (payloadlen < 2) {
  528. return NGHTTP2_FRAME_SIZE_ERROR;
  529. }
  530. origin_len = nghttp2_get_uint16(payload);
  531. buf = nghttp2_mem_malloc(mem, payloadlen - 2);
  532. if (!buf) {
  533. return NGHTTP2_ERR_NOMEM;
  534. }
  535. nghttp2_cpymem(buf, payload + 2, payloadlen - 2);
  536. nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2);
  537. return 0;
  538. }
  539. nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
  540. size_t niv, nghttp2_mem *mem) {
  541. nghttp2_settings_entry *iv_copy;
  542. size_t len = niv * sizeof(nghttp2_settings_entry);
  543. if (len == 0) {
  544. return NULL;
  545. }
  546. iv_copy = nghttp2_mem_malloc(mem, len);
  547. if (iv_copy == NULL) {
  548. return NULL;
  549. }
  550. memcpy(iv_copy, iv, len);
  551. return iv_copy;
  552. }
  553. int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b) {
  554. return a->namelen == b->namelen && a->valuelen == b->valuelen &&
  555. memcmp(a->name, b->name, a->namelen) == 0 &&
  556. memcmp(a->value, b->value, a->valuelen) == 0;
  557. }
  558. void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem) {
  559. nghttp2_mem_free(mem, nva);
  560. }
  561. static int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b,
  562. size_t blen) {
  563. int rv;
  564. if (alen == blen) {
  565. return memcmp(a, b, alen);
  566. }
  567. if (alen < blen) {
  568. rv = memcmp(a, b, alen);
  569. if (rv == 0) {
  570. return -1;
  571. }
  572. return rv;
  573. }
  574. rv = memcmp(a, b, blen);
  575. if (rv == 0) {
  576. return 1;
  577. }
  578. return rv;
  579. }
  580. int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) {
  581. return bytes_compar(lhs->name, lhs->namelen, rhs->name, rhs->namelen);
  582. }
  583. static int nv_compar(const void *lhs, const void *rhs) {
  584. const nghttp2_nv *a = (const nghttp2_nv *)lhs;
  585. const nghttp2_nv *b = (const nghttp2_nv *)rhs;
  586. int rv;
  587. rv = bytes_compar(a->name, a->namelen, b->name, b->namelen);
  588. if (rv == 0) {
  589. return bytes_compar(a->value, a->valuelen, b->value, b->valuelen);
  590. }
  591. return rv;
  592. }
  593. void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) {
  594. qsort(nva, nvlen, sizeof(nghttp2_nv), nv_compar);
  595. }
  596. int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
  597. size_t nvlen, nghttp2_mem *mem) {
  598. size_t i;
  599. uint8_t *data = NULL;
  600. size_t buflen = 0;
  601. nghttp2_nv *p;
  602. if (nvlen == 0) {
  603. *nva_ptr = NULL;
  604. return 0;
  605. }
  606. for (i = 0; i < nvlen; ++i) {
  607. /* + 1 for null-termination */
  608. if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) {
  609. buflen += nva[i].namelen + 1;
  610. }
  611. if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) {
  612. buflen += nva[i].valuelen + 1;
  613. }
  614. }
  615. buflen += sizeof(nghttp2_nv) * nvlen;
  616. *nva_ptr = nghttp2_mem_malloc(mem, buflen);
  617. if (*nva_ptr == NULL) {
  618. return NGHTTP2_ERR_NOMEM;
  619. }
  620. p = *nva_ptr;
  621. data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
  622. for (i = 0; i < nvlen; ++i) {
  623. p->flags = nva[i].flags;
  624. if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) {
  625. p->name = nva[i].name;
  626. p->namelen = nva[i].namelen;
  627. } else {
  628. if (nva[i].namelen) {
  629. memcpy(data, nva[i].name, nva[i].namelen);
  630. }
  631. p->name = data;
  632. p->namelen = nva[i].namelen;
  633. data[p->namelen] = '\0';
  634. nghttp2_downcase(p->name, p->namelen);
  635. data += nva[i].namelen + 1;
  636. }
  637. if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) {
  638. p->value = nva[i].value;
  639. p->valuelen = nva[i].valuelen;
  640. } else {
  641. if (nva[i].valuelen) {
  642. memcpy(data, nva[i].value, nva[i].valuelen);
  643. }
  644. p->value = data;
  645. p->valuelen = nva[i].valuelen;
  646. data[p->valuelen] = '\0';
  647. data += nva[i].valuelen + 1;
  648. }
  649. ++p;
  650. }
  651. return 0;
  652. }
  653. int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
  654. size_t i;
  655. for (i = 0; i < niv; ++i) {
  656. switch (iv[i].settings_id) {
  657. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  658. break;
  659. case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
  660. break;
  661. case NGHTTP2_SETTINGS_ENABLE_PUSH:
  662. if (iv[i].value != 0 && iv[i].value != 1) {
  663. return 0;
  664. }
  665. break;
  666. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  667. if (iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) {
  668. return 0;
  669. }
  670. break;
  671. case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
  672. if (iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
  673. iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
  674. return 0;
  675. }
  676. break;
  677. case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
  678. break;
  679. }
  680. }
  681. return 1;
  682. }
  683. static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
  684. size_t trail_padlen;
  685. size_t newlen;
  686. DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen);
  687. memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN);
  688. --buf->pos;
  689. buf->pos[4] |= NGHTTP2_FLAG_PADDED;
  690. newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen;
  691. nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3]));
  692. if (framehd_only) {
  693. return;
  694. }
  695. trail_padlen = padlen - 1;
  696. buf->pos[NGHTTP2_FRAME_HDLEN] = (uint8_t)trail_padlen;
  697. /* zero out padding */
  698. memset(buf->last, 0, trail_padlen);
  699. /* extend buffers trail_padlen bytes, since we ate previous padlen -
  700. trail_padlen byte(s) */
  701. buf->last += trail_padlen;
  702. }
  703. int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
  704. size_t padlen, int framehd_only) {
  705. nghttp2_buf *buf;
  706. if (padlen == 0) {
  707. DEBUGF("send: padlen = 0, nothing to do\n");
  708. return 0;
  709. }
  710. /*
  711. * We have arranged bufs like this:
  712. *
  713. * 0 1 2 3
  714. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  715. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  716. * | |Frame header | Frame payload... :
  717. * +-+-----------------+-------------------------------------------+
  718. * | |Frame header | Frame payload... :
  719. * +-+-----------------+-------------------------------------------+
  720. * | |Frame header | Frame payload... :
  721. * +-+-----------------+-------------------------------------------+
  722. *
  723. * We arranged padding so that it is included in the first frame
  724. * completely. For padded frame, we are going to adjust buf->pos of
  725. * frame which includes padding and serialize (memmove) frame header
  726. * in the correct position. Also extends buf->last to include
  727. * padding.
  728. */
  729. buf = &bufs->head->buf;
  730. assert(nghttp2_buf_avail(buf) >= padlen - 1);
  731. frame_set_pad(buf, padlen, framehd_only);
  732. hd->length += padlen;
  733. hd->flags |= NGHTTP2_FLAG_PADDED;
  734. DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen);
  735. return 0;
  736. }