nghttp2_frame.c 28 KB

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