12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2013 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "nghttp2_frame.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#include <string.h> 282c593315Sopenharmony_ci#include <assert.h> 292c593315Sopenharmony_ci#include <stdio.h> 302c593315Sopenharmony_ci#include <errno.h> 312c593315Sopenharmony_ci 322c593315Sopenharmony_ci#include "nghttp2_helper.h" 332c593315Sopenharmony_ci#include "nghttp2_net.h" 342c593315Sopenharmony_ci#include "nghttp2_priority_spec.h" 352c593315Sopenharmony_ci#include "nghttp2_debug.h" 362c593315Sopenharmony_ci 372c593315Sopenharmony_civoid nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) { 382c593315Sopenharmony_ci nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8)); 392c593315Sopenharmony_ci buf[3] = hd->type; 402c593315Sopenharmony_ci buf[4] = hd->flags; 412c593315Sopenharmony_ci nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id); 422c593315Sopenharmony_ci /* ignore hd->reserved for now */ 432c593315Sopenharmony_ci} 442c593315Sopenharmony_ci 452c593315Sopenharmony_civoid nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf) { 462c593315Sopenharmony_ci hd->length = nghttp2_get_uint32(&buf[0]) >> 8; 472c593315Sopenharmony_ci hd->type = buf[3]; 482c593315Sopenharmony_ci hd->flags = buf[4]; 492c593315Sopenharmony_ci hd->stream_id = nghttp2_get_uint32(&buf[5]) & NGHTTP2_STREAM_ID_MASK; 502c593315Sopenharmony_ci hd->reserved = 0; 512c593315Sopenharmony_ci} 522c593315Sopenharmony_ci 532c593315Sopenharmony_civoid nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type, 542c593315Sopenharmony_ci uint8_t flags, int32_t stream_id) { 552c593315Sopenharmony_ci hd->length = length; 562c593315Sopenharmony_ci hd->type = type; 572c593315Sopenharmony_ci hd->flags = flags; 582c593315Sopenharmony_ci hd->stream_id = stream_id; 592c593315Sopenharmony_ci hd->reserved = 0; 602c593315Sopenharmony_ci} 612c593315Sopenharmony_ci 622c593315Sopenharmony_civoid nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags, 632c593315Sopenharmony_ci int32_t stream_id, nghttp2_headers_category cat, 642c593315Sopenharmony_ci const nghttp2_priority_spec *pri_spec, 652c593315Sopenharmony_ci nghttp2_nv *nva, size_t nvlen) { 662c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_HEADERS, flags, stream_id); 672c593315Sopenharmony_ci frame->padlen = 0; 682c593315Sopenharmony_ci frame->nva = nva; 692c593315Sopenharmony_ci frame->nvlen = nvlen; 702c593315Sopenharmony_ci frame->cat = cat; 712c593315Sopenharmony_ci 722c593315Sopenharmony_ci if (pri_spec) { 732c593315Sopenharmony_ci frame->pri_spec = *pri_spec; 742c593315Sopenharmony_ci } else { 752c593315Sopenharmony_ci nghttp2_priority_spec_default_init(&frame->pri_spec); 762c593315Sopenharmony_ci } 772c593315Sopenharmony_ci} 782c593315Sopenharmony_ci 792c593315Sopenharmony_civoid nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem) { 802c593315Sopenharmony_ci nghttp2_nv_array_del(frame->nva, mem); 812c593315Sopenharmony_ci} 822c593315Sopenharmony_ci 832c593315Sopenharmony_civoid nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id, 842c593315Sopenharmony_ci const nghttp2_priority_spec *pri_spec) { 852c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, NGHTTP2_PRIORITY_SPECLEN, NGHTTP2_PRIORITY, 862c593315Sopenharmony_ci NGHTTP2_FLAG_NONE, stream_id); 872c593315Sopenharmony_ci frame->pri_spec = *pri_spec; 882c593315Sopenharmony_ci} 892c593315Sopenharmony_ci 902c593315Sopenharmony_civoid nghttp2_frame_priority_free(nghttp2_priority *frame) { (void)frame; } 912c593315Sopenharmony_ci 922c593315Sopenharmony_civoid nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id, 932c593315Sopenharmony_ci uint32_t error_code) { 942c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 952c593315Sopenharmony_ci stream_id); 962c593315Sopenharmony_ci frame->error_code = error_code; 972c593315Sopenharmony_ci} 982c593315Sopenharmony_ci 992c593315Sopenharmony_civoid nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame) { (void)frame; } 1002c593315Sopenharmony_ci 1012c593315Sopenharmony_civoid nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags, 1022c593315Sopenharmony_ci nghttp2_settings_entry *iv, size_t niv) { 1032c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH, 1042c593315Sopenharmony_ci NGHTTP2_SETTINGS, flags, 0); 1052c593315Sopenharmony_ci frame->niv = niv; 1062c593315Sopenharmony_ci frame->iv = iv; 1072c593315Sopenharmony_ci} 1082c593315Sopenharmony_ci 1092c593315Sopenharmony_civoid nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem) { 1102c593315Sopenharmony_ci nghttp2_mem_free(mem, frame->iv); 1112c593315Sopenharmony_ci} 1122c593315Sopenharmony_ci 1132c593315Sopenharmony_civoid nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags, 1142c593315Sopenharmony_ci int32_t stream_id, 1152c593315Sopenharmony_ci int32_t promised_stream_id, 1162c593315Sopenharmony_ci nghttp2_nv *nva, size_t nvlen) { 1172c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_PUSH_PROMISE, flags, stream_id); 1182c593315Sopenharmony_ci frame->padlen = 0; 1192c593315Sopenharmony_ci frame->nva = nva; 1202c593315Sopenharmony_ci frame->nvlen = nvlen; 1212c593315Sopenharmony_ci frame->promised_stream_id = promised_stream_id; 1222c593315Sopenharmony_ci frame->reserved = 0; 1232c593315Sopenharmony_ci} 1242c593315Sopenharmony_ci 1252c593315Sopenharmony_civoid nghttp2_frame_push_promise_free(nghttp2_push_promise *frame, 1262c593315Sopenharmony_ci nghttp2_mem *mem) { 1272c593315Sopenharmony_ci nghttp2_nv_array_del(frame->nva, mem); 1282c593315Sopenharmony_ci} 1292c593315Sopenharmony_ci 1302c593315Sopenharmony_civoid nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags, 1312c593315Sopenharmony_ci const uint8_t *opaque_data) { 1322c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 8, NGHTTP2_PING, flags, 0); 1332c593315Sopenharmony_ci if (opaque_data) { 1342c593315Sopenharmony_ci memcpy(frame->opaque_data, opaque_data, sizeof(frame->opaque_data)); 1352c593315Sopenharmony_ci } else { 1362c593315Sopenharmony_ci memset(frame->opaque_data, 0, sizeof(frame->opaque_data)); 1372c593315Sopenharmony_ci } 1382c593315Sopenharmony_ci} 1392c593315Sopenharmony_ci 1402c593315Sopenharmony_civoid nghttp2_frame_ping_free(nghttp2_ping *frame) { (void)frame; } 1412c593315Sopenharmony_ci 1422c593315Sopenharmony_civoid nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id, 1432c593315Sopenharmony_ci uint32_t error_code, uint8_t *opaque_data, 1442c593315Sopenharmony_ci size_t opaque_data_len) { 1452c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 8 + opaque_data_len, NGHTTP2_GOAWAY, 1462c593315Sopenharmony_ci NGHTTP2_FLAG_NONE, 0); 1472c593315Sopenharmony_ci frame->last_stream_id = last_stream_id; 1482c593315Sopenharmony_ci frame->error_code = error_code; 1492c593315Sopenharmony_ci frame->opaque_data = opaque_data; 1502c593315Sopenharmony_ci frame->opaque_data_len = opaque_data_len; 1512c593315Sopenharmony_ci frame->reserved = 0; 1522c593315Sopenharmony_ci} 1532c593315Sopenharmony_ci 1542c593315Sopenharmony_civoid nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem) { 1552c593315Sopenharmony_ci nghttp2_mem_free(mem, frame->opaque_data); 1562c593315Sopenharmony_ci} 1572c593315Sopenharmony_ci 1582c593315Sopenharmony_civoid nghttp2_frame_window_update_init(nghttp2_window_update *frame, 1592c593315Sopenharmony_ci uint8_t flags, int32_t stream_id, 1602c593315Sopenharmony_ci int32_t window_size_increment) { 1612c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags, stream_id); 1622c593315Sopenharmony_ci frame->window_size_increment = window_size_increment; 1632c593315Sopenharmony_ci frame->reserved = 0; 1642c593315Sopenharmony_ci} 1652c593315Sopenharmony_ci 1662c593315Sopenharmony_civoid nghttp2_frame_window_update_free(nghttp2_window_update *frame) { 1672c593315Sopenharmony_ci (void)frame; 1682c593315Sopenharmony_ci} 1692c593315Sopenharmony_ci 1702c593315Sopenharmony_cisize_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) { 1712c593315Sopenharmony_ci /* We have iframe->padlen == 0, but iframe->frame.hd.flags may have 1722c593315Sopenharmony_ci NGHTTP2_FLAG_PADDED set. This happens when receiving 1732c593315Sopenharmony_ci CONTINUATION frame, since we don't reset flags after HEADERS was 1742c593315Sopenharmony_ci received. */ 1752c593315Sopenharmony_ci if (padlen == 0) { 1762c593315Sopenharmony_ci return 0; 1772c593315Sopenharmony_ci } 1782c593315Sopenharmony_ci return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0); 1792c593315Sopenharmony_ci} 1802c593315Sopenharmony_ci 1812c593315Sopenharmony_civoid nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags, 1822c593315Sopenharmony_ci int32_t stream_id) { 1832c593315Sopenharmony_ci /* At this moment, the length of DATA frame is unknown */ 1842c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id); 1852c593315Sopenharmony_ci frame->padlen = 0; 1862c593315Sopenharmony_ci} 1872c593315Sopenharmony_ci 1882c593315Sopenharmony_civoid nghttp2_frame_data_free(nghttp2_data *frame) { (void)frame; } 1892c593315Sopenharmony_ci 1902c593315Sopenharmony_civoid nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type, 1912c593315Sopenharmony_ci uint8_t flags, int32_t stream_id, 1922c593315Sopenharmony_ci void *payload) { 1932c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id); 1942c593315Sopenharmony_ci frame->payload = payload; 1952c593315Sopenharmony_ci} 1962c593315Sopenharmony_ci 1972c593315Sopenharmony_civoid nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; } 1982c593315Sopenharmony_ci 1992c593315Sopenharmony_civoid nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id, 2002c593315Sopenharmony_ci uint8_t *origin, size_t origin_len, 2012c593315Sopenharmony_ci uint8_t *field_value, size_t field_value_len) { 2022c593315Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 2032c593315Sopenharmony_ci 2042c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len, 2052c593315Sopenharmony_ci NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id); 2062c593315Sopenharmony_ci 2072c593315Sopenharmony_ci altsvc = frame->payload; 2082c593315Sopenharmony_ci altsvc->origin = origin; 2092c593315Sopenharmony_ci altsvc->origin_len = origin_len; 2102c593315Sopenharmony_ci altsvc->field_value = field_value; 2112c593315Sopenharmony_ci altsvc->field_value_len = field_value_len; 2122c593315Sopenharmony_ci} 2132c593315Sopenharmony_ci 2142c593315Sopenharmony_civoid nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) { 2152c593315Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 2162c593315Sopenharmony_ci 2172c593315Sopenharmony_ci altsvc = frame->payload; 2182c593315Sopenharmony_ci if (altsvc == NULL) { 2192c593315Sopenharmony_ci return; 2202c593315Sopenharmony_ci } 2212c593315Sopenharmony_ci /* We use the same buffer for altsvc->origin and 2222c593315Sopenharmony_ci altsvc->field_value. */ 2232c593315Sopenharmony_ci nghttp2_mem_free(mem, altsvc->origin); 2242c593315Sopenharmony_ci} 2252c593315Sopenharmony_ci 2262c593315Sopenharmony_civoid nghttp2_frame_origin_init(nghttp2_extension *frame, 2272c593315Sopenharmony_ci nghttp2_origin_entry *ov, size_t nov) { 2282c593315Sopenharmony_ci nghttp2_ext_origin *origin; 2292c593315Sopenharmony_ci size_t payloadlen = 0; 2302c593315Sopenharmony_ci size_t i; 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci for (i = 0; i < nov; ++i) { 2332c593315Sopenharmony_ci payloadlen += 2 + ov[i].origin_len; 2342c593315Sopenharmony_ci } 2352c593315Sopenharmony_ci 2362c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, payloadlen, NGHTTP2_ORIGIN, 2372c593315Sopenharmony_ci NGHTTP2_FLAG_NONE, 0); 2382c593315Sopenharmony_ci 2392c593315Sopenharmony_ci origin = frame->payload; 2402c593315Sopenharmony_ci origin->ov = ov; 2412c593315Sopenharmony_ci origin->nov = nov; 2422c593315Sopenharmony_ci} 2432c593315Sopenharmony_ci 2442c593315Sopenharmony_civoid nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem) { 2452c593315Sopenharmony_ci nghttp2_ext_origin *origin; 2462c593315Sopenharmony_ci 2472c593315Sopenharmony_ci origin = frame->payload; 2482c593315Sopenharmony_ci if (origin == NULL) { 2492c593315Sopenharmony_ci return; 2502c593315Sopenharmony_ci } 2512c593315Sopenharmony_ci /* We use the same buffer for all resources pointed by the field of 2522c593315Sopenharmony_ci origin directly or indirectly. */ 2532c593315Sopenharmony_ci nghttp2_mem_free(mem, origin->ov); 2542c593315Sopenharmony_ci} 2552c593315Sopenharmony_ci 2562c593315Sopenharmony_civoid nghttp2_frame_priority_update_init(nghttp2_extension *frame, 2572c593315Sopenharmony_ci int32_t stream_id, uint8_t *field_value, 2582c593315Sopenharmony_ci size_t field_value_len) { 2592c593315Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 2602c593315Sopenharmony_ci 2612c593315Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 4 + field_value_len, 2622c593315Sopenharmony_ci NGHTTP2_PRIORITY_UPDATE, NGHTTP2_FLAG_NONE, 0); 2632c593315Sopenharmony_ci 2642c593315Sopenharmony_ci priority_update = frame->payload; 2652c593315Sopenharmony_ci priority_update->stream_id = stream_id; 2662c593315Sopenharmony_ci priority_update->field_value = field_value; 2672c593315Sopenharmony_ci priority_update->field_value_len = field_value_len; 2682c593315Sopenharmony_ci} 2692c593315Sopenharmony_ci 2702c593315Sopenharmony_civoid nghttp2_frame_priority_update_free(nghttp2_extension *frame, 2712c593315Sopenharmony_ci nghttp2_mem *mem) { 2722c593315Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 2732c593315Sopenharmony_ci 2742c593315Sopenharmony_ci priority_update = frame->payload; 2752c593315Sopenharmony_ci if (priority_update == NULL) { 2762c593315Sopenharmony_ci return; 2772c593315Sopenharmony_ci } 2782c593315Sopenharmony_ci nghttp2_mem_free(mem, priority_update->field_value); 2792c593315Sopenharmony_ci} 2802c593315Sopenharmony_ci 2812c593315Sopenharmony_cisize_t nghttp2_frame_priority_len(uint8_t flags) { 2822c593315Sopenharmony_ci if (flags & NGHTTP2_FLAG_PRIORITY) { 2832c593315Sopenharmony_ci return NGHTTP2_PRIORITY_SPECLEN; 2842c593315Sopenharmony_ci } 2852c593315Sopenharmony_ci 2862c593315Sopenharmony_ci return 0; 2872c593315Sopenharmony_ci} 2882c593315Sopenharmony_ci 2892c593315Sopenharmony_cisize_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) { 2902c593315Sopenharmony_ci return nghttp2_frame_priority_len(frame->hd.flags); 2912c593315Sopenharmony_ci} 2922c593315Sopenharmony_ci 2932c593315Sopenharmony_ci/* 2942c593315Sopenharmony_ci * Call this function after payload was serialized, but not before 2952c593315Sopenharmony_ci * changing buf->pos and serializing frame header. 2962c593315Sopenharmony_ci * 2972c593315Sopenharmony_ci * This function assumes bufs->cur points to the last buf chain of the 2982c593315Sopenharmony_ci * frame(s). 2992c593315Sopenharmony_ci * 3002c593315Sopenharmony_ci * This function serializes frame header for HEADERS/PUSH_PROMISE and 3012c593315Sopenharmony_ci * handles their successive CONTINUATION frames. 3022c593315Sopenharmony_ci * 3032c593315Sopenharmony_ci * We don't process any padding here. 3042c593315Sopenharmony_ci */ 3052c593315Sopenharmony_cistatic int frame_pack_headers_shared(nghttp2_bufs *bufs, 3062c593315Sopenharmony_ci nghttp2_frame_hd *frame_hd) { 3072c593315Sopenharmony_ci nghttp2_buf *buf; 3082c593315Sopenharmony_ci nghttp2_buf_chain *ci, *ce; 3092c593315Sopenharmony_ci nghttp2_frame_hd hd; 3102c593315Sopenharmony_ci 3112c593315Sopenharmony_ci buf = &bufs->head->buf; 3122c593315Sopenharmony_ci 3132c593315Sopenharmony_ci hd = *frame_hd; 3142c593315Sopenharmony_ci hd.length = nghttp2_buf_len(buf); 3152c593315Sopenharmony_ci 3162c593315Sopenharmony_ci DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length); 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_ci /* We have multiple frame buffers, which means one or more 3192c593315Sopenharmony_ci CONTINUATION frame is involved. Remove END_HEADERS flag from the 3202c593315Sopenharmony_ci first frame. */ 3212c593315Sopenharmony_ci if (bufs->head != bufs->cur) { 3222c593315Sopenharmony_ci hd.flags = (uint8_t)(hd.flags & ~NGHTTP2_FLAG_END_HEADERS); 3232c593315Sopenharmony_ci } 3242c593315Sopenharmony_ci 3252c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 3262c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &hd); 3272c593315Sopenharmony_ci 3282c593315Sopenharmony_ci if (bufs->head != bufs->cur) { 3292c593315Sopenharmony_ci /* 2nd and later frames are CONTINUATION frames. */ 3302c593315Sopenharmony_ci hd.type = NGHTTP2_CONTINUATION; 3312c593315Sopenharmony_ci /* We don't have no flags except for last CONTINUATION */ 3322c593315Sopenharmony_ci hd.flags = NGHTTP2_FLAG_NONE; 3332c593315Sopenharmony_ci 3342c593315Sopenharmony_ci ce = bufs->cur; 3352c593315Sopenharmony_ci 3362c593315Sopenharmony_ci for (ci = bufs->head->next; ci != ce; ci = ci->next) { 3372c593315Sopenharmony_ci buf = &ci->buf; 3382c593315Sopenharmony_ci 3392c593315Sopenharmony_ci hd.length = nghttp2_buf_len(buf); 3402c593315Sopenharmony_ci 3412c593315Sopenharmony_ci DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length); 3422c593315Sopenharmony_ci 3432c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 3442c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &hd); 3452c593315Sopenharmony_ci } 3462c593315Sopenharmony_ci 3472c593315Sopenharmony_ci buf = &ci->buf; 3482c593315Sopenharmony_ci hd.length = nghttp2_buf_len(buf); 3492c593315Sopenharmony_ci /* Set END_HEADERS flag for last CONTINUATION */ 3502c593315Sopenharmony_ci hd.flags = NGHTTP2_FLAG_END_HEADERS; 3512c593315Sopenharmony_ci 3522c593315Sopenharmony_ci DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length); 3532c593315Sopenharmony_ci 3542c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 3552c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &hd); 3562c593315Sopenharmony_ci } 3572c593315Sopenharmony_ci 3582c593315Sopenharmony_ci return 0; 3592c593315Sopenharmony_ci} 3602c593315Sopenharmony_ci 3612c593315Sopenharmony_ciint nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame, 3622c593315Sopenharmony_ci nghttp2_hd_deflater *deflater) { 3632c593315Sopenharmony_ci size_t nv_offset; 3642c593315Sopenharmony_ci int rv; 3652c593315Sopenharmony_ci nghttp2_buf *buf; 3662c593315Sopenharmony_ci 3672c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 3682c593315Sopenharmony_ci 3692c593315Sopenharmony_ci nv_offset = nghttp2_frame_headers_payload_nv_offset(frame); 3702c593315Sopenharmony_ci 3712c593315Sopenharmony_ci buf = &bufs->cur->buf; 3722c593315Sopenharmony_ci 3732c593315Sopenharmony_ci buf->pos += nv_offset; 3742c593315Sopenharmony_ci buf->last = buf->pos; 3752c593315Sopenharmony_ci 3762c593315Sopenharmony_ci /* This call will adjust buf->last to the correct position */ 3772c593315Sopenharmony_ci rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen); 3782c593315Sopenharmony_ci 3792c593315Sopenharmony_ci if (rv == NGHTTP2_ERR_BUFFER_ERROR) { 3802c593315Sopenharmony_ci rv = NGHTTP2_ERR_HEADER_COMP; 3812c593315Sopenharmony_ci } 3822c593315Sopenharmony_ci 3832c593315Sopenharmony_ci buf->pos -= nv_offset; 3842c593315Sopenharmony_ci 3852c593315Sopenharmony_ci if (rv != 0) { 3862c593315Sopenharmony_ci return rv; 3872c593315Sopenharmony_ci } 3882c593315Sopenharmony_ci 3892c593315Sopenharmony_ci if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { 3902c593315Sopenharmony_ci nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec); 3912c593315Sopenharmony_ci } 3922c593315Sopenharmony_ci 3932c593315Sopenharmony_ci frame->padlen = 0; 3942c593315Sopenharmony_ci frame->hd.length = nghttp2_bufs_len(bufs); 3952c593315Sopenharmony_ci 3962c593315Sopenharmony_ci return frame_pack_headers_shared(bufs, &frame->hd); 3972c593315Sopenharmony_ci} 3982c593315Sopenharmony_ci 3992c593315Sopenharmony_civoid nghttp2_frame_pack_priority_spec(uint8_t *buf, 4002c593315Sopenharmony_ci const nghttp2_priority_spec *pri_spec) { 4012c593315Sopenharmony_ci nghttp2_put_uint32be(buf, (uint32_t)pri_spec->stream_id); 4022c593315Sopenharmony_ci if (pri_spec->exclusive) { 4032c593315Sopenharmony_ci buf[0] |= 0x80; 4042c593315Sopenharmony_ci } 4052c593315Sopenharmony_ci buf[4] = (uint8_t)(pri_spec->weight - 1); 4062c593315Sopenharmony_ci} 4072c593315Sopenharmony_ci 4082c593315Sopenharmony_civoid nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec, 4092c593315Sopenharmony_ci const uint8_t *payload) { 4102c593315Sopenharmony_ci int32_t dep_stream_id; 4112c593315Sopenharmony_ci uint8_t exclusive; 4122c593315Sopenharmony_ci int32_t weight; 4132c593315Sopenharmony_ci 4142c593315Sopenharmony_ci dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 4152c593315Sopenharmony_ci exclusive = (payload[0] & 0x80) > 0; 4162c593315Sopenharmony_ci weight = payload[4] + 1; 4172c593315Sopenharmony_ci 4182c593315Sopenharmony_ci nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive); 4192c593315Sopenharmony_ci} 4202c593315Sopenharmony_ci 4212c593315Sopenharmony_civoid nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame, 4222c593315Sopenharmony_ci const uint8_t *payload) { 4232c593315Sopenharmony_ci if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { 4242c593315Sopenharmony_ci nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload); 4252c593315Sopenharmony_ci } else { 4262c593315Sopenharmony_ci nghttp2_priority_spec_default_init(&frame->pri_spec); 4272c593315Sopenharmony_ci } 4282c593315Sopenharmony_ci 4292c593315Sopenharmony_ci frame->nva = NULL; 4302c593315Sopenharmony_ci frame->nvlen = 0; 4312c593315Sopenharmony_ci} 4322c593315Sopenharmony_ci 4332c593315Sopenharmony_civoid nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) { 4342c593315Sopenharmony_ci nghttp2_buf *buf; 4352c593315Sopenharmony_ci 4362c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 4372c593315Sopenharmony_ci 4382c593315Sopenharmony_ci buf = &bufs->head->buf; 4392c593315Sopenharmony_ci 4402c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= NGHTTP2_PRIORITY_SPECLEN); 4412c593315Sopenharmony_ci 4422c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 4432c593315Sopenharmony_ci 4442c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 4452c593315Sopenharmony_ci 4462c593315Sopenharmony_ci nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec); 4472c593315Sopenharmony_ci 4482c593315Sopenharmony_ci buf->last += NGHTTP2_PRIORITY_SPECLEN; 4492c593315Sopenharmony_ci} 4502c593315Sopenharmony_ci 4512c593315Sopenharmony_civoid nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame, 4522c593315Sopenharmony_ci const uint8_t *payload) { 4532c593315Sopenharmony_ci nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload); 4542c593315Sopenharmony_ci} 4552c593315Sopenharmony_ci 4562c593315Sopenharmony_civoid nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs, 4572c593315Sopenharmony_ci nghttp2_rst_stream *frame) { 4582c593315Sopenharmony_ci nghttp2_buf *buf; 4592c593315Sopenharmony_ci 4602c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 4612c593315Sopenharmony_ci 4622c593315Sopenharmony_ci buf = &bufs->head->buf; 4632c593315Sopenharmony_ci 4642c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 4); 4652c593315Sopenharmony_ci 4662c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 4672c593315Sopenharmony_ci 4682c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 4692c593315Sopenharmony_ci 4702c593315Sopenharmony_ci nghttp2_put_uint32be(buf->last, frame->error_code); 4712c593315Sopenharmony_ci buf->last += 4; 4722c593315Sopenharmony_ci} 4732c593315Sopenharmony_ci 4742c593315Sopenharmony_civoid nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame, 4752c593315Sopenharmony_ci const uint8_t *payload) { 4762c593315Sopenharmony_ci frame->error_code = nghttp2_get_uint32(payload); 4772c593315Sopenharmony_ci} 4782c593315Sopenharmony_ci 4792c593315Sopenharmony_ciint nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) { 4802c593315Sopenharmony_ci nghttp2_buf *buf; 4812c593315Sopenharmony_ci 4822c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 4832c593315Sopenharmony_ci 4842c593315Sopenharmony_ci buf = &bufs->head->buf; 4852c593315Sopenharmony_ci 4862c593315Sopenharmony_ci if (nghttp2_buf_avail(buf) < frame->hd.length) { 4872c593315Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 4882c593315Sopenharmony_ci } 4892c593315Sopenharmony_ci 4902c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 4912c593315Sopenharmony_ci 4922c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 4932c593315Sopenharmony_ci 4942c593315Sopenharmony_ci buf->last += 4952c593315Sopenharmony_ci nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv); 4962c593315Sopenharmony_ci 4972c593315Sopenharmony_ci return 0; 4982c593315Sopenharmony_ci} 4992c593315Sopenharmony_ci 5002c593315Sopenharmony_cisize_t nghttp2_frame_pack_settings_payload(uint8_t *buf, 5012c593315Sopenharmony_ci const nghttp2_settings_entry *iv, 5022c593315Sopenharmony_ci size_t niv) { 5032c593315Sopenharmony_ci size_t i; 5042c593315Sopenharmony_ci for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) { 5052c593315Sopenharmony_ci nghttp2_put_uint16be(buf, (uint16_t)iv[i].settings_id); 5062c593315Sopenharmony_ci nghttp2_put_uint32be(buf + 2, iv[i].value); 5072c593315Sopenharmony_ci } 5082c593315Sopenharmony_ci return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv; 5092c593315Sopenharmony_ci} 5102c593315Sopenharmony_ci 5112c593315Sopenharmony_civoid nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, 5122c593315Sopenharmony_ci nghttp2_settings_entry *iv, 5132c593315Sopenharmony_ci size_t niv) { 5142c593315Sopenharmony_ci frame->iv = iv; 5152c593315Sopenharmony_ci frame->niv = niv; 5162c593315Sopenharmony_ci} 5172c593315Sopenharmony_ci 5182c593315Sopenharmony_civoid nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv, 5192c593315Sopenharmony_ci const uint8_t *payload) { 5202c593315Sopenharmony_ci iv->settings_id = nghttp2_get_uint16(&payload[0]); 5212c593315Sopenharmony_ci iv->value = nghttp2_get_uint32(&payload[2]); 5222c593315Sopenharmony_ci} 5232c593315Sopenharmony_ci 5242c593315Sopenharmony_ciint nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr, 5252c593315Sopenharmony_ci size_t *niv_ptr, 5262c593315Sopenharmony_ci const uint8_t *payload, 5272c593315Sopenharmony_ci size_t payloadlen, 5282c593315Sopenharmony_ci nghttp2_mem *mem) { 5292c593315Sopenharmony_ci size_t i; 5302c593315Sopenharmony_ci 5312c593315Sopenharmony_ci *niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH; 5322c593315Sopenharmony_ci 5332c593315Sopenharmony_ci if (*niv_ptr == 0) { 5342c593315Sopenharmony_ci *iv_ptr = NULL; 5352c593315Sopenharmony_ci 5362c593315Sopenharmony_ci return 0; 5372c593315Sopenharmony_ci } 5382c593315Sopenharmony_ci 5392c593315Sopenharmony_ci *iv_ptr = 5402c593315Sopenharmony_ci nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry)); 5412c593315Sopenharmony_ci 5422c593315Sopenharmony_ci if (*iv_ptr == NULL) { 5432c593315Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 5442c593315Sopenharmony_ci } 5452c593315Sopenharmony_ci 5462c593315Sopenharmony_ci for (i = 0; i < *niv_ptr; ++i) { 5472c593315Sopenharmony_ci size_t off = i * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH; 5482c593315Sopenharmony_ci nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]); 5492c593315Sopenharmony_ci } 5502c593315Sopenharmony_ci 5512c593315Sopenharmony_ci return 0; 5522c593315Sopenharmony_ci} 5532c593315Sopenharmony_ci 5542c593315Sopenharmony_ciint nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs, 5552c593315Sopenharmony_ci nghttp2_push_promise *frame, 5562c593315Sopenharmony_ci nghttp2_hd_deflater *deflater) { 5572c593315Sopenharmony_ci size_t nv_offset = 4; 5582c593315Sopenharmony_ci int rv; 5592c593315Sopenharmony_ci nghttp2_buf *buf; 5602c593315Sopenharmony_ci 5612c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 5622c593315Sopenharmony_ci 5632c593315Sopenharmony_ci buf = &bufs->cur->buf; 5642c593315Sopenharmony_ci 5652c593315Sopenharmony_ci buf->pos += nv_offset; 5662c593315Sopenharmony_ci buf->last = buf->pos; 5672c593315Sopenharmony_ci 5682c593315Sopenharmony_ci /* This call will adjust buf->last to the correct position */ 5692c593315Sopenharmony_ci rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen); 5702c593315Sopenharmony_ci 5712c593315Sopenharmony_ci if (rv == NGHTTP2_ERR_BUFFER_ERROR) { 5722c593315Sopenharmony_ci rv = NGHTTP2_ERR_HEADER_COMP; 5732c593315Sopenharmony_ci } 5742c593315Sopenharmony_ci 5752c593315Sopenharmony_ci buf->pos -= nv_offset; 5762c593315Sopenharmony_ci 5772c593315Sopenharmony_ci if (rv != 0) { 5782c593315Sopenharmony_ci return rv; 5792c593315Sopenharmony_ci } 5802c593315Sopenharmony_ci 5812c593315Sopenharmony_ci nghttp2_put_uint32be(buf->pos, (uint32_t)frame->promised_stream_id); 5822c593315Sopenharmony_ci 5832c593315Sopenharmony_ci frame->padlen = 0; 5842c593315Sopenharmony_ci frame->hd.length = nghttp2_bufs_len(bufs); 5852c593315Sopenharmony_ci 5862c593315Sopenharmony_ci return frame_pack_headers_shared(bufs, &frame->hd); 5872c593315Sopenharmony_ci} 5882c593315Sopenharmony_ci 5892c593315Sopenharmony_civoid nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame, 5902c593315Sopenharmony_ci const uint8_t *payload) { 5912c593315Sopenharmony_ci frame->promised_stream_id = 5922c593315Sopenharmony_ci nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 5932c593315Sopenharmony_ci frame->nva = NULL; 5942c593315Sopenharmony_ci frame->nvlen = 0; 5952c593315Sopenharmony_ci} 5962c593315Sopenharmony_ci 5972c593315Sopenharmony_civoid nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) { 5982c593315Sopenharmony_ci nghttp2_buf *buf; 5992c593315Sopenharmony_ci 6002c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 6012c593315Sopenharmony_ci 6022c593315Sopenharmony_ci buf = &bufs->head->buf; 6032c593315Sopenharmony_ci 6042c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 8); 6052c593315Sopenharmony_ci 6062c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 6072c593315Sopenharmony_ci 6082c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 6092c593315Sopenharmony_ci 6102c593315Sopenharmony_ci buf->last = 6112c593315Sopenharmony_ci nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data)); 6122c593315Sopenharmony_ci} 6132c593315Sopenharmony_ci 6142c593315Sopenharmony_civoid nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame, 6152c593315Sopenharmony_ci const uint8_t *payload) { 6162c593315Sopenharmony_ci memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data)); 6172c593315Sopenharmony_ci} 6182c593315Sopenharmony_ci 6192c593315Sopenharmony_ciint nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) { 6202c593315Sopenharmony_ci int rv; 6212c593315Sopenharmony_ci nghttp2_buf *buf; 6222c593315Sopenharmony_ci 6232c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 6242c593315Sopenharmony_ci 6252c593315Sopenharmony_ci buf = &bufs->head->buf; 6262c593315Sopenharmony_ci 6272c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 6282c593315Sopenharmony_ci 6292c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 6302c593315Sopenharmony_ci 6312c593315Sopenharmony_ci nghttp2_put_uint32be(buf->last, (uint32_t)frame->last_stream_id); 6322c593315Sopenharmony_ci buf->last += 4; 6332c593315Sopenharmony_ci 6342c593315Sopenharmony_ci nghttp2_put_uint32be(buf->last, frame->error_code); 6352c593315Sopenharmony_ci buf->last += 4; 6362c593315Sopenharmony_ci 6372c593315Sopenharmony_ci rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len); 6382c593315Sopenharmony_ci 6392c593315Sopenharmony_ci if (rv == NGHTTP2_ERR_BUFFER_ERROR) { 6402c593315Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 6412c593315Sopenharmony_ci } 6422c593315Sopenharmony_ci 6432c593315Sopenharmony_ci if (rv != 0) { 6442c593315Sopenharmony_ci return rv; 6452c593315Sopenharmony_ci } 6462c593315Sopenharmony_ci 6472c593315Sopenharmony_ci return 0; 6482c593315Sopenharmony_ci} 6492c593315Sopenharmony_ci 6502c593315Sopenharmony_civoid nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame, 6512c593315Sopenharmony_ci const uint8_t *payload, 6522c593315Sopenharmony_ci uint8_t *var_gift_payload, 6532c593315Sopenharmony_ci size_t var_gift_payloadlen) { 6542c593315Sopenharmony_ci frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 6552c593315Sopenharmony_ci frame->error_code = nghttp2_get_uint32(payload + 4); 6562c593315Sopenharmony_ci 6572c593315Sopenharmony_ci frame->opaque_data = var_gift_payload; 6582c593315Sopenharmony_ci frame->opaque_data_len = var_gift_payloadlen; 6592c593315Sopenharmony_ci} 6602c593315Sopenharmony_ci 6612c593315Sopenharmony_ciint nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, 6622c593315Sopenharmony_ci const uint8_t *payload, 6632c593315Sopenharmony_ci size_t payloadlen, nghttp2_mem *mem) { 6642c593315Sopenharmony_ci uint8_t *var_gift_payload; 6652c593315Sopenharmony_ci size_t var_gift_payloadlen; 6662c593315Sopenharmony_ci 6672c593315Sopenharmony_ci if (payloadlen > 8) { 6682c593315Sopenharmony_ci var_gift_payloadlen = payloadlen - 8; 6692c593315Sopenharmony_ci } else { 6702c593315Sopenharmony_ci var_gift_payloadlen = 0; 6712c593315Sopenharmony_ci } 6722c593315Sopenharmony_ci 6732c593315Sopenharmony_ci if (!var_gift_payloadlen) { 6742c593315Sopenharmony_ci var_gift_payload = NULL; 6752c593315Sopenharmony_ci } else { 6762c593315Sopenharmony_ci var_gift_payload = nghttp2_mem_malloc(mem, var_gift_payloadlen); 6772c593315Sopenharmony_ci 6782c593315Sopenharmony_ci if (var_gift_payload == NULL) { 6792c593315Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 6802c593315Sopenharmony_ci } 6812c593315Sopenharmony_ci 6822c593315Sopenharmony_ci memcpy(var_gift_payload, payload + 8, var_gift_payloadlen); 6832c593315Sopenharmony_ci } 6842c593315Sopenharmony_ci 6852c593315Sopenharmony_ci nghttp2_frame_unpack_goaway_payload(frame, payload, var_gift_payload, 6862c593315Sopenharmony_ci var_gift_payloadlen); 6872c593315Sopenharmony_ci 6882c593315Sopenharmony_ci return 0; 6892c593315Sopenharmony_ci} 6902c593315Sopenharmony_ci 6912c593315Sopenharmony_civoid nghttp2_frame_pack_window_update(nghttp2_bufs *bufs, 6922c593315Sopenharmony_ci nghttp2_window_update *frame) { 6932c593315Sopenharmony_ci nghttp2_buf *buf; 6942c593315Sopenharmony_ci 6952c593315Sopenharmony_ci assert(bufs->head == bufs->cur); 6962c593315Sopenharmony_ci 6972c593315Sopenharmony_ci buf = &bufs->head->buf; 6982c593315Sopenharmony_ci 6992c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 4); 7002c593315Sopenharmony_ci 7012c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 7022c593315Sopenharmony_ci 7032c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 7042c593315Sopenharmony_ci 7052c593315Sopenharmony_ci nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment); 7062c593315Sopenharmony_ci buf->last += 4; 7072c593315Sopenharmony_ci} 7082c593315Sopenharmony_ci 7092c593315Sopenharmony_civoid nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame, 7102c593315Sopenharmony_ci const uint8_t *payload) { 7112c593315Sopenharmony_ci frame->window_size_increment = 7122c593315Sopenharmony_ci nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK; 7132c593315Sopenharmony_ci} 7142c593315Sopenharmony_ci 7152c593315Sopenharmony_civoid nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) { 7162c593315Sopenharmony_ci int rv; 7172c593315Sopenharmony_ci nghttp2_buf *buf; 7182c593315Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 7192c593315Sopenharmony_ci 7202c593315Sopenharmony_ci /* This is required with --disable-assert. */ 7212c593315Sopenharmony_ci (void)rv; 7222c593315Sopenharmony_ci 7232c593315Sopenharmony_ci altsvc = frame->payload; 7242c593315Sopenharmony_ci 7252c593315Sopenharmony_ci buf = &bufs->head->buf; 7262c593315Sopenharmony_ci 7272c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 7282c593315Sopenharmony_ci 2 + altsvc->origin_len + altsvc->field_value_len); 7292c593315Sopenharmony_ci 7302c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 7312c593315Sopenharmony_ci 7322c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 7332c593315Sopenharmony_ci 7342c593315Sopenharmony_ci nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len); 7352c593315Sopenharmony_ci buf->last += 2; 7362c593315Sopenharmony_ci 7372c593315Sopenharmony_ci rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len); 7382c593315Sopenharmony_ci 7392c593315Sopenharmony_ci assert(rv == 0); 7402c593315Sopenharmony_ci 7412c593315Sopenharmony_ci rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len); 7422c593315Sopenharmony_ci 7432c593315Sopenharmony_ci assert(rv == 0); 7442c593315Sopenharmony_ci} 7452c593315Sopenharmony_ci 7462c593315Sopenharmony_civoid nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, 7472c593315Sopenharmony_ci size_t origin_len, uint8_t *payload, 7482c593315Sopenharmony_ci size_t payloadlen) { 7492c593315Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 7502c593315Sopenharmony_ci uint8_t *p; 7512c593315Sopenharmony_ci 7522c593315Sopenharmony_ci altsvc = frame->payload; 7532c593315Sopenharmony_ci p = payload; 7542c593315Sopenharmony_ci 7552c593315Sopenharmony_ci altsvc->origin = p; 7562c593315Sopenharmony_ci 7572c593315Sopenharmony_ci p += origin_len; 7582c593315Sopenharmony_ci 7592c593315Sopenharmony_ci altsvc->origin_len = origin_len; 7602c593315Sopenharmony_ci 7612c593315Sopenharmony_ci altsvc->field_value = p; 7622c593315Sopenharmony_ci altsvc->field_value_len = (size_t)(payload + payloadlen - p); 7632c593315Sopenharmony_ci} 7642c593315Sopenharmony_ci 7652c593315Sopenharmony_ciint nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame, 7662c593315Sopenharmony_ci const uint8_t *payload, 7672c593315Sopenharmony_ci size_t payloadlen, nghttp2_mem *mem) { 7682c593315Sopenharmony_ci uint8_t *buf; 7692c593315Sopenharmony_ci size_t origin_len; 7702c593315Sopenharmony_ci 7712c593315Sopenharmony_ci if (payloadlen < 2) { 7722c593315Sopenharmony_ci return NGHTTP2_FRAME_SIZE_ERROR; 7732c593315Sopenharmony_ci } 7742c593315Sopenharmony_ci 7752c593315Sopenharmony_ci origin_len = nghttp2_get_uint16(payload); 7762c593315Sopenharmony_ci 7772c593315Sopenharmony_ci buf = nghttp2_mem_malloc(mem, payloadlen - 2); 7782c593315Sopenharmony_ci if (!buf) { 7792c593315Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 7802c593315Sopenharmony_ci } 7812c593315Sopenharmony_ci 7822c593315Sopenharmony_ci nghttp2_cpymem(buf, payload + 2, payloadlen - 2); 7832c593315Sopenharmony_ci 7842c593315Sopenharmony_ci nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2); 7852c593315Sopenharmony_ci 7862c593315Sopenharmony_ci return 0; 7872c593315Sopenharmony_ci} 7882c593315Sopenharmony_ci 7892c593315Sopenharmony_ciint nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *frame) { 7902c593315Sopenharmony_ci nghttp2_buf *buf; 7912c593315Sopenharmony_ci nghttp2_ext_origin *origin; 7922c593315Sopenharmony_ci nghttp2_origin_entry *orig; 7932c593315Sopenharmony_ci size_t i; 7942c593315Sopenharmony_ci 7952c593315Sopenharmony_ci origin = frame->payload; 7962c593315Sopenharmony_ci 7972c593315Sopenharmony_ci buf = &bufs->head->buf; 7982c593315Sopenharmony_ci 7992c593315Sopenharmony_ci if (nghttp2_buf_avail(buf) < frame->hd.length) { 8002c593315Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 8012c593315Sopenharmony_ci } 8022c593315Sopenharmony_ci 8032c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 8042c593315Sopenharmony_ci 8052c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 8062c593315Sopenharmony_ci 8072c593315Sopenharmony_ci for (i = 0; i < origin->nov; ++i) { 8082c593315Sopenharmony_ci orig = &origin->ov[i]; 8092c593315Sopenharmony_ci nghttp2_put_uint16be(buf->last, (uint16_t)orig->origin_len); 8102c593315Sopenharmony_ci buf->last += 2; 8112c593315Sopenharmony_ci buf->last = nghttp2_cpymem(buf->last, orig->origin, orig->origin_len); 8122c593315Sopenharmony_ci } 8132c593315Sopenharmony_ci 8142c593315Sopenharmony_ci assert(nghttp2_buf_len(buf) == NGHTTP2_FRAME_HDLEN + frame->hd.length); 8152c593315Sopenharmony_ci 8162c593315Sopenharmony_ci return 0; 8172c593315Sopenharmony_ci} 8182c593315Sopenharmony_ci 8192c593315Sopenharmony_ciint nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame, 8202c593315Sopenharmony_ci const uint8_t *payload, 8212c593315Sopenharmony_ci size_t payloadlen, nghttp2_mem *mem) { 8222c593315Sopenharmony_ci nghttp2_ext_origin *origin; 8232c593315Sopenharmony_ci const uint8_t *p, *end; 8242c593315Sopenharmony_ci uint8_t *dst; 8252c593315Sopenharmony_ci size_t originlen; 8262c593315Sopenharmony_ci nghttp2_origin_entry *ov; 8272c593315Sopenharmony_ci size_t nov = 0; 8282c593315Sopenharmony_ci size_t len = 0; 8292c593315Sopenharmony_ci 8302c593315Sopenharmony_ci origin = frame->payload; 8312c593315Sopenharmony_ci p = end = payload; 8322c593315Sopenharmony_ci if (payloadlen) { 8332c593315Sopenharmony_ci end += payloadlen; 8342c593315Sopenharmony_ci } 8352c593315Sopenharmony_ci 8362c593315Sopenharmony_ci for (; p != end;) { 8372c593315Sopenharmony_ci if (end - p < 2) { 8382c593315Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 8392c593315Sopenharmony_ci } 8402c593315Sopenharmony_ci originlen = nghttp2_get_uint16(p); 8412c593315Sopenharmony_ci p += 2; 8422c593315Sopenharmony_ci if (originlen == 0) { 8432c593315Sopenharmony_ci continue; 8442c593315Sopenharmony_ci } 8452c593315Sopenharmony_ci if (originlen > (size_t)(end - p)) { 8462c593315Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 8472c593315Sopenharmony_ci } 8482c593315Sopenharmony_ci p += originlen; 8492c593315Sopenharmony_ci /* 1 for terminal NULL */ 8502c593315Sopenharmony_ci len += originlen + 1; 8512c593315Sopenharmony_ci ++nov; 8522c593315Sopenharmony_ci } 8532c593315Sopenharmony_ci 8542c593315Sopenharmony_ci if (nov == 0) { 8552c593315Sopenharmony_ci origin->ov = NULL; 8562c593315Sopenharmony_ci origin->nov = 0; 8572c593315Sopenharmony_ci 8582c593315Sopenharmony_ci return 0; 8592c593315Sopenharmony_ci } 8602c593315Sopenharmony_ci 8612c593315Sopenharmony_ci len += nov * sizeof(nghttp2_origin_entry); 8622c593315Sopenharmony_ci 8632c593315Sopenharmony_ci ov = nghttp2_mem_malloc(mem, len); 8642c593315Sopenharmony_ci if (ov == NULL) { 8652c593315Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 8662c593315Sopenharmony_ci } 8672c593315Sopenharmony_ci 8682c593315Sopenharmony_ci origin->ov = ov; 8692c593315Sopenharmony_ci origin->nov = nov; 8702c593315Sopenharmony_ci 8712c593315Sopenharmony_ci dst = (uint8_t *)ov + nov * sizeof(nghttp2_origin_entry); 8722c593315Sopenharmony_ci p = payload; 8732c593315Sopenharmony_ci 8742c593315Sopenharmony_ci for (; p != end;) { 8752c593315Sopenharmony_ci originlen = nghttp2_get_uint16(p); 8762c593315Sopenharmony_ci p += 2; 8772c593315Sopenharmony_ci if (originlen == 0) { 8782c593315Sopenharmony_ci continue; 8792c593315Sopenharmony_ci } 8802c593315Sopenharmony_ci ov->origin = dst; 8812c593315Sopenharmony_ci ov->origin_len = originlen; 8822c593315Sopenharmony_ci dst = nghttp2_cpymem(dst, p, originlen); 8832c593315Sopenharmony_ci *dst++ = '\0'; 8842c593315Sopenharmony_ci p += originlen; 8852c593315Sopenharmony_ci ++ov; 8862c593315Sopenharmony_ci } 8872c593315Sopenharmony_ci 8882c593315Sopenharmony_ci return 0; 8892c593315Sopenharmony_ci} 8902c593315Sopenharmony_ci 8912c593315Sopenharmony_civoid nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs, 8922c593315Sopenharmony_ci nghttp2_extension *frame) { 8932c593315Sopenharmony_ci int rv; 8942c593315Sopenharmony_ci nghttp2_buf *buf; 8952c593315Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 8962c593315Sopenharmony_ci 8972c593315Sopenharmony_ci /* This is required with --disable-assert. */ 8982c593315Sopenharmony_ci (void)rv; 8992c593315Sopenharmony_ci 9002c593315Sopenharmony_ci priority_update = frame->payload; 9012c593315Sopenharmony_ci 9022c593315Sopenharmony_ci buf = &bufs->head->buf; 9032c593315Sopenharmony_ci 9042c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 4 + priority_update->field_value_len); 9052c593315Sopenharmony_ci 9062c593315Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 9072c593315Sopenharmony_ci 9082c593315Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 9092c593315Sopenharmony_ci 9102c593315Sopenharmony_ci nghttp2_put_uint32be(buf->last, (uint32_t)priority_update->stream_id); 9112c593315Sopenharmony_ci buf->last += 4; 9122c593315Sopenharmony_ci 9132c593315Sopenharmony_ci rv = nghttp2_bufs_add(bufs, priority_update->field_value, 9142c593315Sopenharmony_ci priority_update->field_value_len); 9152c593315Sopenharmony_ci 9162c593315Sopenharmony_ci assert(rv == 0); 9172c593315Sopenharmony_ci} 9182c593315Sopenharmony_ci 9192c593315Sopenharmony_civoid nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame, 9202c593315Sopenharmony_ci uint8_t *payload, 9212c593315Sopenharmony_ci size_t payloadlen) { 9222c593315Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 9232c593315Sopenharmony_ci 9242c593315Sopenharmony_ci assert(payloadlen >= 4); 9252c593315Sopenharmony_ci 9262c593315Sopenharmony_ci priority_update = frame->payload; 9272c593315Sopenharmony_ci 9282c593315Sopenharmony_ci priority_update->stream_id = 9292c593315Sopenharmony_ci nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 9302c593315Sopenharmony_ci 9312c593315Sopenharmony_ci if (payloadlen > 4) { 9322c593315Sopenharmony_ci priority_update->field_value = payload + 4; 9332c593315Sopenharmony_ci priority_update->field_value_len = payloadlen - 4; 9342c593315Sopenharmony_ci } else { 9352c593315Sopenharmony_ci priority_update->field_value = NULL; 9362c593315Sopenharmony_ci priority_update->field_value_len = 0; 9372c593315Sopenharmony_ci } 9382c593315Sopenharmony_ci} 9392c593315Sopenharmony_ci 9402c593315Sopenharmony_cinghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv, 9412c593315Sopenharmony_ci size_t niv, nghttp2_mem *mem) { 9422c593315Sopenharmony_ci nghttp2_settings_entry *iv_copy; 9432c593315Sopenharmony_ci size_t len = niv * sizeof(nghttp2_settings_entry); 9442c593315Sopenharmony_ci 9452c593315Sopenharmony_ci if (len == 0) { 9462c593315Sopenharmony_ci return NULL; 9472c593315Sopenharmony_ci } 9482c593315Sopenharmony_ci 9492c593315Sopenharmony_ci iv_copy = nghttp2_mem_malloc(mem, len); 9502c593315Sopenharmony_ci 9512c593315Sopenharmony_ci if (iv_copy == NULL) { 9522c593315Sopenharmony_ci return NULL; 9532c593315Sopenharmony_ci } 9542c593315Sopenharmony_ci 9552c593315Sopenharmony_ci memcpy(iv_copy, iv, len); 9562c593315Sopenharmony_ci 9572c593315Sopenharmony_ci return iv_copy; 9582c593315Sopenharmony_ci} 9592c593315Sopenharmony_ci 9602c593315Sopenharmony_ciint nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b) { 9612c593315Sopenharmony_ci if (a->namelen != b->namelen || a->valuelen != b->valuelen) { 9622c593315Sopenharmony_ci return 0; 9632c593315Sopenharmony_ci } 9642c593315Sopenharmony_ci 9652c593315Sopenharmony_ci if (a->name == NULL || b->name == NULL) { 9662c593315Sopenharmony_ci assert(a->namelen == 0); 9672c593315Sopenharmony_ci assert(b->namelen == 0); 9682c593315Sopenharmony_ci } else if (memcmp(a->name, b->name, a->namelen) != 0) { 9692c593315Sopenharmony_ci return 0; 9702c593315Sopenharmony_ci } 9712c593315Sopenharmony_ci 9722c593315Sopenharmony_ci if (a->value == NULL || b->value == NULL) { 9732c593315Sopenharmony_ci assert(a->valuelen == 0); 9742c593315Sopenharmony_ci assert(b->valuelen == 0); 9752c593315Sopenharmony_ci } else if (memcmp(a->value, b->value, a->valuelen) != 0) { 9762c593315Sopenharmony_ci return 0; 9772c593315Sopenharmony_ci } 9782c593315Sopenharmony_ci 9792c593315Sopenharmony_ci return 1; 9802c593315Sopenharmony_ci} 9812c593315Sopenharmony_ci 9822c593315Sopenharmony_civoid nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem) { 9832c593315Sopenharmony_ci nghttp2_mem_free(mem, nva); 9842c593315Sopenharmony_ci} 9852c593315Sopenharmony_ci 9862c593315Sopenharmony_cistatic int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b, 9872c593315Sopenharmony_ci size_t blen) { 9882c593315Sopenharmony_ci int rv; 9892c593315Sopenharmony_ci 9902c593315Sopenharmony_ci if (alen == blen) { 9912c593315Sopenharmony_ci return memcmp(a, b, alen); 9922c593315Sopenharmony_ci } 9932c593315Sopenharmony_ci 9942c593315Sopenharmony_ci if (alen < blen) { 9952c593315Sopenharmony_ci rv = memcmp(a, b, alen); 9962c593315Sopenharmony_ci 9972c593315Sopenharmony_ci if (rv == 0) { 9982c593315Sopenharmony_ci return -1; 9992c593315Sopenharmony_ci } 10002c593315Sopenharmony_ci 10012c593315Sopenharmony_ci return rv; 10022c593315Sopenharmony_ci } 10032c593315Sopenharmony_ci 10042c593315Sopenharmony_ci rv = memcmp(a, b, blen); 10052c593315Sopenharmony_ci 10062c593315Sopenharmony_ci if (rv == 0) { 10072c593315Sopenharmony_ci return 1; 10082c593315Sopenharmony_ci } 10092c593315Sopenharmony_ci 10102c593315Sopenharmony_ci return rv; 10112c593315Sopenharmony_ci} 10122c593315Sopenharmony_ci 10132c593315Sopenharmony_ciint nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) { 10142c593315Sopenharmony_ci return bytes_compar(lhs->name, lhs->namelen, rhs->name, rhs->namelen); 10152c593315Sopenharmony_ci} 10162c593315Sopenharmony_ci 10172c593315Sopenharmony_cistatic int nv_compar(const void *lhs, const void *rhs) { 10182c593315Sopenharmony_ci const nghttp2_nv *a = (const nghttp2_nv *)lhs; 10192c593315Sopenharmony_ci const nghttp2_nv *b = (const nghttp2_nv *)rhs; 10202c593315Sopenharmony_ci int rv; 10212c593315Sopenharmony_ci 10222c593315Sopenharmony_ci rv = bytes_compar(a->name, a->namelen, b->name, b->namelen); 10232c593315Sopenharmony_ci 10242c593315Sopenharmony_ci if (rv == 0) { 10252c593315Sopenharmony_ci return bytes_compar(a->value, a->valuelen, b->value, b->valuelen); 10262c593315Sopenharmony_ci } 10272c593315Sopenharmony_ci 10282c593315Sopenharmony_ci return rv; 10292c593315Sopenharmony_ci} 10302c593315Sopenharmony_ci 10312c593315Sopenharmony_civoid nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) { 10322c593315Sopenharmony_ci qsort(nva, nvlen, sizeof(nghttp2_nv), nv_compar); 10332c593315Sopenharmony_ci} 10342c593315Sopenharmony_ci 10352c593315Sopenharmony_ciint nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva, 10362c593315Sopenharmony_ci size_t nvlen, nghttp2_mem *mem) { 10372c593315Sopenharmony_ci size_t i; 10382c593315Sopenharmony_ci uint8_t *data = NULL; 10392c593315Sopenharmony_ci size_t buflen = 0; 10402c593315Sopenharmony_ci nghttp2_nv *p; 10412c593315Sopenharmony_ci 10422c593315Sopenharmony_ci if (nvlen == 0) { 10432c593315Sopenharmony_ci *nva_ptr = NULL; 10442c593315Sopenharmony_ci 10452c593315Sopenharmony_ci return 0; 10462c593315Sopenharmony_ci } 10472c593315Sopenharmony_ci 10482c593315Sopenharmony_ci for (i = 0; i < nvlen; ++i) { 10492c593315Sopenharmony_ci /* + 1 for null-termination */ 10502c593315Sopenharmony_ci if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) { 10512c593315Sopenharmony_ci buflen += nva[i].namelen + 1; 10522c593315Sopenharmony_ci } 10532c593315Sopenharmony_ci if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) { 10542c593315Sopenharmony_ci buflen += nva[i].valuelen + 1; 10552c593315Sopenharmony_ci } 10562c593315Sopenharmony_ci } 10572c593315Sopenharmony_ci 10582c593315Sopenharmony_ci buflen += sizeof(nghttp2_nv) * nvlen; 10592c593315Sopenharmony_ci 10602c593315Sopenharmony_ci *nva_ptr = nghttp2_mem_malloc(mem, buflen); 10612c593315Sopenharmony_ci 10622c593315Sopenharmony_ci if (*nva_ptr == NULL) { 10632c593315Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 10642c593315Sopenharmony_ci } 10652c593315Sopenharmony_ci 10662c593315Sopenharmony_ci p = *nva_ptr; 10672c593315Sopenharmony_ci data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen; 10682c593315Sopenharmony_ci 10692c593315Sopenharmony_ci for (i = 0; i < nvlen; ++i) { 10702c593315Sopenharmony_ci p->flags = nva[i].flags; 10712c593315Sopenharmony_ci 10722c593315Sopenharmony_ci if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) { 10732c593315Sopenharmony_ci p->name = nva[i].name; 10742c593315Sopenharmony_ci p->namelen = nva[i].namelen; 10752c593315Sopenharmony_ci } else { 10762c593315Sopenharmony_ci if (nva[i].namelen) { 10772c593315Sopenharmony_ci memcpy(data, nva[i].name, nva[i].namelen); 10782c593315Sopenharmony_ci } 10792c593315Sopenharmony_ci p->name = data; 10802c593315Sopenharmony_ci p->namelen = nva[i].namelen; 10812c593315Sopenharmony_ci data[p->namelen] = '\0'; 10822c593315Sopenharmony_ci nghttp2_downcase(p->name, p->namelen); 10832c593315Sopenharmony_ci data += nva[i].namelen + 1; 10842c593315Sopenharmony_ci } 10852c593315Sopenharmony_ci 10862c593315Sopenharmony_ci if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) { 10872c593315Sopenharmony_ci p->value = nva[i].value; 10882c593315Sopenharmony_ci p->valuelen = nva[i].valuelen; 10892c593315Sopenharmony_ci } else { 10902c593315Sopenharmony_ci if (nva[i].valuelen) { 10912c593315Sopenharmony_ci memcpy(data, nva[i].value, nva[i].valuelen); 10922c593315Sopenharmony_ci } 10932c593315Sopenharmony_ci p->value = data; 10942c593315Sopenharmony_ci p->valuelen = nva[i].valuelen; 10952c593315Sopenharmony_ci data[p->valuelen] = '\0'; 10962c593315Sopenharmony_ci data += nva[i].valuelen + 1; 10972c593315Sopenharmony_ci } 10982c593315Sopenharmony_ci 10992c593315Sopenharmony_ci ++p; 11002c593315Sopenharmony_ci } 11012c593315Sopenharmony_ci return 0; 11022c593315Sopenharmony_ci} 11032c593315Sopenharmony_ci 11042c593315Sopenharmony_ciint nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) { 11052c593315Sopenharmony_ci size_t i; 11062c593315Sopenharmony_ci for (i = 0; i < niv; ++i) { 11072c593315Sopenharmony_ci switch (iv[i].settings_id) { 11082c593315Sopenharmony_ci case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: 11092c593315Sopenharmony_ci break; 11102c593315Sopenharmony_ci case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: 11112c593315Sopenharmony_ci break; 11122c593315Sopenharmony_ci case NGHTTP2_SETTINGS_ENABLE_PUSH: 11132c593315Sopenharmony_ci if (iv[i].value != 0 && iv[i].value != 1) { 11142c593315Sopenharmony_ci return 0; 11152c593315Sopenharmony_ci } 11162c593315Sopenharmony_ci break; 11172c593315Sopenharmony_ci case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: 11182c593315Sopenharmony_ci if (iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) { 11192c593315Sopenharmony_ci return 0; 11202c593315Sopenharmony_ci } 11212c593315Sopenharmony_ci break; 11222c593315Sopenharmony_ci case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: 11232c593315Sopenharmony_ci if (iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN || 11242c593315Sopenharmony_ci iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) { 11252c593315Sopenharmony_ci return 0; 11262c593315Sopenharmony_ci } 11272c593315Sopenharmony_ci break; 11282c593315Sopenharmony_ci case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: 11292c593315Sopenharmony_ci break; 11302c593315Sopenharmony_ci case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: 11312c593315Sopenharmony_ci if (iv[i].value != 0 && iv[i].value != 1) { 11322c593315Sopenharmony_ci return 0; 11332c593315Sopenharmony_ci } 11342c593315Sopenharmony_ci break; 11352c593315Sopenharmony_ci case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES: 11362c593315Sopenharmony_ci if (iv[i].value != 0 && iv[i].value != 1) { 11372c593315Sopenharmony_ci return 0; 11382c593315Sopenharmony_ci } 11392c593315Sopenharmony_ci break; 11402c593315Sopenharmony_ci } 11412c593315Sopenharmony_ci } 11422c593315Sopenharmony_ci return 1; 11432c593315Sopenharmony_ci} 11442c593315Sopenharmony_ci 11452c593315Sopenharmony_cistatic void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) { 11462c593315Sopenharmony_ci size_t trail_padlen; 11472c593315Sopenharmony_ci size_t newlen; 11482c593315Sopenharmony_ci 11492c593315Sopenharmony_ci DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen); 11502c593315Sopenharmony_ci 11512c593315Sopenharmony_ci memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN); 11522c593315Sopenharmony_ci 11532c593315Sopenharmony_ci --buf->pos; 11542c593315Sopenharmony_ci 11552c593315Sopenharmony_ci buf->pos[4] |= NGHTTP2_FLAG_PADDED; 11562c593315Sopenharmony_ci 11572c593315Sopenharmony_ci newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen; 11582c593315Sopenharmony_ci nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3])); 11592c593315Sopenharmony_ci 11602c593315Sopenharmony_ci if (framehd_only) { 11612c593315Sopenharmony_ci return; 11622c593315Sopenharmony_ci } 11632c593315Sopenharmony_ci 11642c593315Sopenharmony_ci trail_padlen = padlen - 1; 11652c593315Sopenharmony_ci buf->pos[NGHTTP2_FRAME_HDLEN] = (uint8_t)trail_padlen; 11662c593315Sopenharmony_ci 11672c593315Sopenharmony_ci /* zero out padding */ 11682c593315Sopenharmony_ci memset(buf->last, 0, trail_padlen); 11692c593315Sopenharmony_ci /* extend buffers trail_padlen bytes, since we ate previous padlen - 11702c593315Sopenharmony_ci trail_padlen byte(s) */ 11712c593315Sopenharmony_ci buf->last += trail_padlen; 11722c593315Sopenharmony_ci} 11732c593315Sopenharmony_ci 11742c593315Sopenharmony_civoid nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, 11752c593315Sopenharmony_ci size_t padlen, int framehd_only) { 11762c593315Sopenharmony_ci nghttp2_buf *buf; 11772c593315Sopenharmony_ci 11782c593315Sopenharmony_ci if (padlen == 0) { 11792c593315Sopenharmony_ci DEBUGF("send: padlen = 0, nothing to do\n"); 11802c593315Sopenharmony_ci 11812c593315Sopenharmony_ci return; 11822c593315Sopenharmony_ci } 11832c593315Sopenharmony_ci 11842c593315Sopenharmony_ci /* 11852c593315Sopenharmony_ci * We have arranged bufs like this: 11862c593315Sopenharmony_ci * 11872c593315Sopenharmony_ci * 0 1 2 3 11882c593315Sopenharmony_ci * 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 11892c593315Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11902c593315Sopenharmony_ci * | |Frame header | Frame payload... : 11912c593315Sopenharmony_ci * +-+-----------------+-------------------------------------------+ 11922c593315Sopenharmony_ci * | |Frame header | Frame payload... : 11932c593315Sopenharmony_ci * +-+-----------------+-------------------------------------------+ 11942c593315Sopenharmony_ci * | |Frame header | Frame payload... : 11952c593315Sopenharmony_ci * +-+-----------------+-------------------------------------------+ 11962c593315Sopenharmony_ci * 11972c593315Sopenharmony_ci * We arranged padding so that it is included in the first frame 11982c593315Sopenharmony_ci * completely. For padded frame, we are going to adjust buf->pos of 11992c593315Sopenharmony_ci * frame which includes padding and serialize (memmove) frame header 12002c593315Sopenharmony_ci * in the correct position. Also extends buf->last to include 12012c593315Sopenharmony_ci * padding. 12022c593315Sopenharmony_ci */ 12032c593315Sopenharmony_ci 12042c593315Sopenharmony_ci buf = &bufs->head->buf; 12052c593315Sopenharmony_ci 12062c593315Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= padlen - 1); 12072c593315Sopenharmony_ci 12082c593315Sopenharmony_ci frame_set_pad(buf, padlen, framehd_only); 12092c593315Sopenharmony_ci 12102c593315Sopenharmony_ci hd->length += padlen; 12112c593315Sopenharmony_ci hd->flags |= NGHTTP2_FLAG_PADDED; 12122c593315Sopenharmony_ci 12132c593315Sopenharmony_ci DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen); 12142c593315Sopenharmony_ci} 1215