11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * nghttp2 - HTTP/2 C Library 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Copyright (c) 2013 Tatsuhiro Tsujikawa 51cb0ef41Sopenharmony_ci * 61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 71cb0ef41Sopenharmony_ci * a copy of this software and associated documentation files (the 81cb0ef41Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 91cb0ef41Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 101cb0ef41Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 111cb0ef41Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 121cb0ef41Sopenharmony_ci * the following conditions: 131cb0ef41Sopenharmony_ci * 141cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be 151cb0ef41Sopenharmony_ci * included in all copies or substantial portions of the Software. 161cb0ef41Sopenharmony_ci * 171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 181cb0ef41Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 191cb0ef41Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 201cb0ef41Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 211cb0ef41Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 221cb0ef41Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 231cb0ef41Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 241cb0ef41Sopenharmony_ci */ 251cb0ef41Sopenharmony_ci#include "nghttp2_frame.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci#include <string.h> 281cb0ef41Sopenharmony_ci#include <assert.h> 291cb0ef41Sopenharmony_ci#include <stdio.h> 301cb0ef41Sopenharmony_ci#include <errno.h> 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci#include "nghttp2_helper.h" 331cb0ef41Sopenharmony_ci#include "nghttp2_net.h" 341cb0ef41Sopenharmony_ci#include "nghttp2_priority_spec.h" 351cb0ef41Sopenharmony_ci#include "nghttp2_debug.h" 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_civoid nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) { 381cb0ef41Sopenharmony_ci nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8)); 391cb0ef41Sopenharmony_ci buf[3] = hd->type; 401cb0ef41Sopenharmony_ci buf[4] = hd->flags; 411cb0ef41Sopenharmony_ci nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id); 421cb0ef41Sopenharmony_ci /* ignore hd->reserved for now */ 431cb0ef41Sopenharmony_ci} 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf) { 461cb0ef41Sopenharmony_ci hd->length = nghttp2_get_uint32(&buf[0]) >> 8; 471cb0ef41Sopenharmony_ci hd->type = buf[3]; 481cb0ef41Sopenharmony_ci hd->flags = buf[4]; 491cb0ef41Sopenharmony_ci hd->stream_id = nghttp2_get_uint32(&buf[5]) & NGHTTP2_STREAM_ID_MASK; 501cb0ef41Sopenharmony_ci hd->reserved = 0; 511cb0ef41Sopenharmony_ci} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_civoid nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type, 541cb0ef41Sopenharmony_ci uint8_t flags, int32_t stream_id) { 551cb0ef41Sopenharmony_ci hd->length = length; 561cb0ef41Sopenharmony_ci hd->type = type; 571cb0ef41Sopenharmony_ci hd->flags = flags; 581cb0ef41Sopenharmony_ci hd->stream_id = stream_id; 591cb0ef41Sopenharmony_ci hd->reserved = 0; 601cb0ef41Sopenharmony_ci} 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_civoid nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags, 631cb0ef41Sopenharmony_ci int32_t stream_id, nghttp2_headers_category cat, 641cb0ef41Sopenharmony_ci const nghttp2_priority_spec *pri_spec, 651cb0ef41Sopenharmony_ci nghttp2_nv *nva, size_t nvlen) { 661cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_HEADERS, flags, stream_id); 671cb0ef41Sopenharmony_ci frame->padlen = 0; 681cb0ef41Sopenharmony_ci frame->nva = nva; 691cb0ef41Sopenharmony_ci frame->nvlen = nvlen; 701cb0ef41Sopenharmony_ci frame->cat = cat; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci if (pri_spec) { 731cb0ef41Sopenharmony_ci frame->pri_spec = *pri_spec; 741cb0ef41Sopenharmony_ci } else { 751cb0ef41Sopenharmony_ci nghttp2_priority_spec_default_init(&frame->pri_spec); 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci} 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_civoid nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem) { 801cb0ef41Sopenharmony_ci nghttp2_nv_array_del(frame->nva, mem); 811cb0ef41Sopenharmony_ci} 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_civoid nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id, 841cb0ef41Sopenharmony_ci const nghttp2_priority_spec *pri_spec) { 851cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, NGHTTP2_PRIORITY_SPECLEN, NGHTTP2_PRIORITY, 861cb0ef41Sopenharmony_ci NGHTTP2_FLAG_NONE, stream_id); 871cb0ef41Sopenharmony_ci frame->pri_spec = *pri_spec; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_civoid nghttp2_frame_priority_free(nghttp2_priority *frame) { (void)frame; } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_civoid nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id, 931cb0ef41Sopenharmony_ci uint32_t error_code) { 941cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 951cb0ef41Sopenharmony_ci stream_id); 961cb0ef41Sopenharmony_ci frame->error_code = error_code; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_civoid nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame) { (void)frame; } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_civoid nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags, 1021cb0ef41Sopenharmony_ci nghttp2_settings_entry *iv, size_t niv) { 1031cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH, 1041cb0ef41Sopenharmony_ci NGHTTP2_SETTINGS, flags, 0); 1051cb0ef41Sopenharmony_ci frame->niv = niv; 1061cb0ef41Sopenharmony_ci frame->iv = iv; 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_civoid nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem) { 1101cb0ef41Sopenharmony_ci nghttp2_mem_free(mem, frame->iv); 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_civoid nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags, 1141cb0ef41Sopenharmony_ci int32_t stream_id, 1151cb0ef41Sopenharmony_ci int32_t promised_stream_id, 1161cb0ef41Sopenharmony_ci nghttp2_nv *nva, size_t nvlen) { 1171cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_PUSH_PROMISE, flags, stream_id); 1181cb0ef41Sopenharmony_ci frame->padlen = 0; 1191cb0ef41Sopenharmony_ci frame->nva = nva; 1201cb0ef41Sopenharmony_ci frame->nvlen = nvlen; 1211cb0ef41Sopenharmony_ci frame->promised_stream_id = promised_stream_id; 1221cb0ef41Sopenharmony_ci frame->reserved = 0; 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_civoid nghttp2_frame_push_promise_free(nghttp2_push_promise *frame, 1261cb0ef41Sopenharmony_ci nghttp2_mem *mem) { 1271cb0ef41Sopenharmony_ci nghttp2_nv_array_del(frame->nva, mem); 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_civoid nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags, 1311cb0ef41Sopenharmony_ci const uint8_t *opaque_data) { 1321cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 8, NGHTTP2_PING, flags, 0); 1331cb0ef41Sopenharmony_ci if (opaque_data) { 1341cb0ef41Sopenharmony_ci memcpy(frame->opaque_data, opaque_data, sizeof(frame->opaque_data)); 1351cb0ef41Sopenharmony_ci } else { 1361cb0ef41Sopenharmony_ci memset(frame->opaque_data, 0, sizeof(frame->opaque_data)); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci} 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_civoid nghttp2_frame_ping_free(nghttp2_ping *frame) { (void)frame; } 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_civoid nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id, 1431cb0ef41Sopenharmony_ci uint32_t error_code, uint8_t *opaque_data, 1441cb0ef41Sopenharmony_ci size_t opaque_data_len) { 1451cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 8 + opaque_data_len, NGHTTP2_GOAWAY, 1461cb0ef41Sopenharmony_ci NGHTTP2_FLAG_NONE, 0); 1471cb0ef41Sopenharmony_ci frame->last_stream_id = last_stream_id; 1481cb0ef41Sopenharmony_ci frame->error_code = error_code; 1491cb0ef41Sopenharmony_ci frame->opaque_data = opaque_data; 1501cb0ef41Sopenharmony_ci frame->opaque_data_len = opaque_data_len; 1511cb0ef41Sopenharmony_ci frame->reserved = 0; 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_civoid nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem) { 1551cb0ef41Sopenharmony_ci nghttp2_mem_free(mem, frame->opaque_data); 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_civoid nghttp2_frame_window_update_init(nghttp2_window_update *frame, 1591cb0ef41Sopenharmony_ci uint8_t flags, int32_t stream_id, 1601cb0ef41Sopenharmony_ci int32_t window_size_increment) { 1611cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags, stream_id); 1621cb0ef41Sopenharmony_ci frame->window_size_increment = window_size_increment; 1631cb0ef41Sopenharmony_ci frame->reserved = 0; 1641cb0ef41Sopenharmony_ci} 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_civoid nghttp2_frame_window_update_free(nghttp2_window_update *frame) { 1671cb0ef41Sopenharmony_ci (void)frame; 1681cb0ef41Sopenharmony_ci} 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_cisize_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) { 1711cb0ef41Sopenharmony_ci /* We have iframe->padlen == 0, but iframe->frame.hd.flags may have 1721cb0ef41Sopenharmony_ci NGHTTP2_FLAG_PADDED set. This happens when receiving 1731cb0ef41Sopenharmony_ci CONTINUATION frame, since we don't reset flags after HEADERS was 1741cb0ef41Sopenharmony_ci received. */ 1751cb0ef41Sopenharmony_ci if (padlen == 0) { 1761cb0ef41Sopenharmony_ci return 0; 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0); 1791cb0ef41Sopenharmony_ci} 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_civoid nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags, 1821cb0ef41Sopenharmony_ci int32_t stream_id) { 1831cb0ef41Sopenharmony_ci /* At this moment, the length of DATA frame is unknown */ 1841cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id); 1851cb0ef41Sopenharmony_ci frame->padlen = 0; 1861cb0ef41Sopenharmony_ci} 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_civoid nghttp2_frame_data_free(nghttp2_data *frame) { (void)frame; } 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_civoid nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type, 1911cb0ef41Sopenharmony_ci uint8_t flags, int32_t stream_id, 1921cb0ef41Sopenharmony_ci void *payload) { 1931cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id); 1941cb0ef41Sopenharmony_ci frame->payload = payload; 1951cb0ef41Sopenharmony_ci} 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_civoid nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; } 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_civoid nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id, 2001cb0ef41Sopenharmony_ci uint8_t *origin, size_t origin_len, 2011cb0ef41Sopenharmony_ci uint8_t *field_value, size_t field_value_len) { 2021cb0ef41Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len, 2051cb0ef41Sopenharmony_ci NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id); 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci altsvc = frame->payload; 2081cb0ef41Sopenharmony_ci altsvc->origin = origin; 2091cb0ef41Sopenharmony_ci altsvc->origin_len = origin_len; 2101cb0ef41Sopenharmony_ci altsvc->field_value = field_value; 2111cb0ef41Sopenharmony_ci altsvc->field_value_len = field_value_len; 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_civoid nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) { 2151cb0ef41Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci altsvc = frame->payload; 2181cb0ef41Sopenharmony_ci if (altsvc == NULL) { 2191cb0ef41Sopenharmony_ci return; 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci /* We use the same buffer for altsvc->origin and 2221cb0ef41Sopenharmony_ci altsvc->field_value. */ 2231cb0ef41Sopenharmony_ci nghttp2_mem_free(mem, altsvc->origin); 2241cb0ef41Sopenharmony_ci} 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_civoid nghttp2_frame_origin_init(nghttp2_extension *frame, 2271cb0ef41Sopenharmony_ci nghttp2_origin_entry *ov, size_t nov) { 2281cb0ef41Sopenharmony_ci nghttp2_ext_origin *origin; 2291cb0ef41Sopenharmony_ci size_t payloadlen = 0; 2301cb0ef41Sopenharmony_ci size_t i; 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci for (i = 0; i < nov; ++i) { 2331cb0ef41Sopenharmony_ci payloadlen += 2 + ov[i].origin_len; 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, payloadlen, NGHTTP2_ORIGIN, 2371cb0ef41Sopenharmony_ci NGHTTP2_FLAG_NONE, 0); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci origin = frame->payload; 2401cb0ef41Sopenharmony_ci origin->ov = ov; 2411cb0ef41Sopenharmony_ci origin->nov = nov; 2421cb0ef41Sopenharmony_ci} 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_civoid nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem) { 2451cb0ef41Sopenharmony_ci nghttp2_ext_origin *origin; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci origin = frame->payload; 2481cb0ef41Sopenharmony_ci if (origin == NULL) { 2491cb0ef41Sopenharmony_ci return; 2501cb0ef41Sopenharmony_ci } 2511cb0ef41Sopenharmony_ci /* We use the same buffer for all resources pointed by the field of 2521cb0ef41Sopenharmony_ci origin directly or indirectly. */ 2531cb0ef41Sopenharmony_ci nghttp2_mem_free(mem, origin->ov); 2541cb0ef41Sopenharmony_ci} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_civoid nghttp2_frame_priority_update_init(nghttp2_extension *frame, 2571cb0ef41Sopenharmony_ci int32_t stream_id, uint8_t *field_value, 2581cb0ef41Sopenharmony_ci size_t field_value_len) { 2591cb0ef41Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci nghttp2_frame_hd_init(&frame->hd, 4 + field_value_len, 2621cb0ef41Sopenharmony_ci NGHTTP2_PRIORITY_UPDATE, NGHTTP2_FLAG_NONE, 0); 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci priority_update = frame->payload; 2651cb0ef41Sopenharmony_ci priority_update->stream_id = stream_id; 2661cb0ef41Sopenharmony_ci priority_update->field_value = field_value; 2671cb0ef41Sopenharmony_ci priority_update->field_value_len = field_value_len; 2681cb0ef41Sopenharmony_ci} 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_civoid nghttp2_frame_priority_update_free(nghttp2_extension *frame, 2711cb0ef41Sopenharmony_ci nghttp2_mem *mem) { 2721cb0ef41Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci priority_update = frame->payload; 2751cb0ef41Sopenharmony_ci if (priority_update == NULL) { 2761cb0ef41Sopenharmony_ci return; 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci nghttp2_mem_free(mem, priority_update->field_value); 2791cb0ef41Sopenharmony_ci} 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_cisize_t nghttp2_frame_priority_len(uint8_t flags) { 2821cb0ef41Sopenharmony_ci if (flags & NGHTTP2_FLAG_PRIORITY) { 2831cb0ef41Sopenharmony_ci return NGHTTP2_PRIORITY_SPECLEN; 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci return 0; 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_cisize_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) { 2901cb0ef41Sopenharmony_ci return nghttp2_frame_priority_len(frame->hd.flags); 2911cb0ef41Sopenharmony_ci} 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci/* 2941cb0ef41Sopenharmony_ci * Call this function after payload was serialized, but not before 2951cb0ef41Sopenharmony_ci * changing buf->pos and serializing frame header. 2961cb0ef41Sopenharmony_ci * 2971cb0ef41Sopenharmony_ci * This function assumes bufs->cur points to the last buf chain of the 2981cb0ef41Sopenharmony_ci * frame(s). 2991cb0ef41Sopenharmony_ci * 3001cb0ef41Sopenharmony_ci * This function serializes frame header for HEADERS/PUSH_PROMISE and 3011cb0ef41Sopenharmony_ci * handles their successive CONTINUATION frames. 3021cb0ef41Sopenharmony_ci * 3031cb0ef41Sopenharmony_ci * We don't process any padding here. 3041cb0ef41Sopenharmony_ci */ 3051cb0ef41Sopenharmony_cistatic int frame_pack_headers_shared(nghttp2_bufs *bufs, 3061cb0ef41Sopenharmony_ci nghttp2_frame_hd *frame_hd) { 3071cb0ef41Sopenharmony_ci nghttp2_buf *buf; 3081cb0ef41Sopenharmony_ci nghttp2_buf_chain *ci, *ce; 3091cb0ef41Sopenharmony_ci nghttp2_frame_hd hd; 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci hd = *frame_hd; 3141cb0ef41Sopenharmony_ci hd.length = nghttp2_buf_len(buf); 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length); 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci /* We have multiple frame buffers, which means one or more 3191cb0ef41Sopenharmony_ci CONTINUATION frame is involved. Remove END_HEADERS flag from the 3201cb0ef41Sopenharmony_ci first frame. */ 3211cb0ef41Sopenharmony_ci if (bufs->head != bufs->cur) { 3221cb0ef41Sopenharmony_ci hd.flags = (uint8_t)(hd.flags & ~NGHTTP2_FLAG_END_HEADERS); 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 3261cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &hd); 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci if (bufs->head != bufs->cur) { 3291cb0ef41Sopenharmony_ci /* 2nd and later frames are CONTINUATION frames. */ 3301cb0ef41Sopenharmony_ci hd.type = NGHTTP2_CONTINUATION; 3311cb0ef41Sopenharmony_ci /* We don't have no flags except for last CONTINUATION */ 3321cb0ef41Sopenharmony_ci hd.flags = NGHTTP2_FLAG_NONE; 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci ce = bufs->cur; 3351cb0ef41Sopenharmony_ci 3361cb0ef41Sopenharmony_ci for (ci = bufs->head->next; ci != ce; ci = ci->next) { 3371cb0ef41Sopenharmony_ci buf = &ci->buf; 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci hd.length = nghttp2_buf_len(buf); 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length); 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 3441cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &hd); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci buf = &ci->buf; 3481cb0ef41Sopenharmony_ci hd.length = nghttp2_buf_len(buf); 3491cb0ef41Sopenharmony_ci /* Set END_HEADERS flag for last CONTINUATION */ 3501cb0ef41Sopenharmony_ci hd.flags = NGHTTP2_FLAG_END_HEADERS; 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ci DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length); 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 3551cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &hd); 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci return 0; 3591cb0ef41Sopenharmony_ci} 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ciint nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame, 3621cb0ef41Sopenharmony_ci nghttp2_hd_deflater *deflater) { 3631cb0ef41Sopenharmony_ci size_t nv_offset; 3641cb0ef41Sopenharmony_ci int rv; 3651cb0ef41Sopenharmony_ci nghttp2_buf *buf; 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci nv_offset = nghttp2_frame_headers_payload_nv_offset(frame); 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci buf = &bufs->cur->buf; 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci buf->pos += nv_offset; 3741cb0ef41Sopenharmony_ci buf->last = buf->pos; 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci /* This call will adjust buf->last to the correct position */ 3771cb0ef41Sopenharmony_ci rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen); 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci if (rv == NGHTTP2_ERR_BUFFER_ERROR) { 3801cb0ef41Sopenharmony_ci rv = NGHTTP2_ERR_HEADER_COMP; 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci buf->pos -= nv_offset; 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci if (rv != 0) { 3861cb0ef41Sopenharmony_ci return rv; 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { 3901cb0ef41Sopenharmony_ci nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec); 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci frame->padlen = 0; 3941cb0ef41Sopenharmony_ci frame->hd.length = nghttp2_bufs_len(bufs); 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci return frame_pack_headers_shared(bufs, &frame->hd); 3971cb0ef41Sopenharmony_ci} 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_civoid nghttp2_frame_pack_priority_spec(uint8_t *buf, 4001cb0ef41Sopenharmony_ci const nghttp2_priority_spec *pri_spec) { 4011cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf, (uint32_t)pri_spec->stream_id); 4021cb0ef41Sopenharmony_ci if (pri_spec->exclusive) { 4031cb0ef41Sopenharmony_ci buf[0] |= 0x80; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci buf[4] = (uint8_t)(pri_spec->weight - 1); 4061cb0ef41Sopenharmony_ci} 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec, 4091cb0ef41Sopenharmony_ci const uint8_t *payload) { 4101cb0ef41Sopenharmony_ci int32_t dep_stream_id; 4111cb0ef41Sopenharmony_ci uint8_t exclusive; 4121cb0ef41Sopenharmony_ci int32_t weight; 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 4151cb0ef41Sopenharmony_ci exclusive = (payload[0] & 0x80) > 0; 4161cb0ef41Sopenharmony_ci weight = payload[4] + 1; 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive); 4191cb0ef41Sopenharmony_ci} 4201cb0ef41Sopenharmony_ci 4211cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame, 4221cb0ef41Sopenharmony_ci const uint8_t *payload) { 4231cb0ef41Sopenharmony_ci if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { 4241cb0ef41Sopenharmony_ci nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload); 4251cb0ef41Sopenharmony_ci } else { 4261cb0ef41Sopenharmony_ci nghttp2_priority_spec_default_init(&frame->pri_spec); 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci frame->nva = NULL; 4301cb0ef41Sopenharmony_ci frame->nvlen = 0; 4311cb0ef41Sopenharmony_ci} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_civoid nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) { 4341cb0ef41Sopenharmony_ci nghttp2_buf *buf; 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= NGHTTP2_PRIORITY_SPECLEN); 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec); 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci buf->last += NGHTTP2_PRIORITY_SPECLEN; 4491cb0ef41Sopenharmony_ci} 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame, 4521cb0ef41Sopenharmony_ci const uint8_t *payload) { 4531cb0ef41Sopenharmony_ci nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload); 4541cb0ef41Sopenharmony_ci} 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_civoid nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs, 4571cb0ef41Sopenharmony_ci nghttp2_rst_stream *frame) { 4581cb0ef41Sopenharmony_ci nghttp2_buf *buf; 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 4); 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->last, frame->error_code); 4711cb0ef41Sopenharmony_ci buf->last += 4; 4721cb0ef41Sopenharmony_ci} 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame, 4751cb0ef41Sopenharmony_ci const uint8_t *payload) { 4761cb0ef41Sopenharmony_ci frame->error_code = nghttp2_get_uint32(payload); 4771cb0ef41Sopenharmony_ci} 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ciint nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) { 4801cb0ef41Sopenharmony_ci nghttp2_buf *buf; 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci if (nghttp2_buf_avail(buf) < frame->hd.length) { 4871cb0ef41Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci buf->last += 4951cb0ef41Sopenharmony_ci nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv); 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci return 0; 4981cb0ef41Sopenharmony_ci} 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_cisize_t nghttp2_frame_pack_settings_payload(uint8_t *buf, 5011cb0ef41Sopenharmony_ci const nghttp2_settings_entry *iv, 5021cb0ef41Sopenharmony_ci size_t niv) { 5031cb0ef41Sopenharmony_ci size_t i; 5041cb0ef41Sopenharmony_ci for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) { 5051cb0ef41Sopenharmony_ci nghttp2_put_uint16be(buf, (uint16_t)iv[i].settings_id); 5061cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf + 2, iv[i].value); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv; 5091cb0ef41Sopenharmony_ci} 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, 5121cb0ef41Sopenharmony_ci nghttp2_settings_entry *iv, 5131cb0ef41Sopenharmony_ci size_t niv) { 5141cb0ef41Sopenharmony_ci frame->iv = iv; 5151cb0ef41Sopenharmony_ci frame->niv = niv; 5161cb0ef41Sopenharmony_ci} 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv, 5191cb0ef41Sopenharmony_ci const uint8_t *payload) { 5201cb0ef41Sopenharmony_ci iv->settings_id = nghttp2_get_uint16(&payload[0]); 5211cb0ef41Sopenharmony_ci iv->value = nghttp2_get_uint32(&payload[2]); 5221cb0ef41Sopenharmony_ci} 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ciint nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr, 5251cb0ef41Sopenharmony_ci size_t *niv_ptr, 5261cb0ef41Sopenharmony_ci const uint8_t *payload, 5271cb0ef41Sopenharmony_ci size_t payloadlen, 5281cb0ef41Sopenharmony_ci nghttp2_mem *mem) { 5291cb0ef41Sopenharmony_ci size_t i; 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci *niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH; 5321cb0ef41Sopenharmony_ci 5331cb0ef41Sopenharmony_ci if (*niv_ptr == 0) { 5341cb0ef41Sopenharmony_ci *iv_ptr = NULL; 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci return 0; 5371cb0ef41Sopenharmony_ci } 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci *iv_ptr = 5401cb0ef41Sopenharmony_ci nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry)); 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci if (*iv_ptr == NULL) { 5431cb0ef41Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci for (i = 0; i < *niv_ptr; ++i) { 5471cb0ef41Sopenharmony_ci size_t off = i * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH; 5481cb0ef41Sopenharmony_ci nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]); 5491cb0ef41Sopenharmony_ci } 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci return 0; 5521cb0ef41Sopenharmony_ci} 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ciint nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs, 5551cb0ef41Sopenharmony_ci nghttp2_push_promise *frame, 5561cb0ef41Sopenharmony_ci nghttp2_hd_deflater *deflater) { 5571cb0ef41Sopenharmony_ci size_t nv_offset = 4; 5581cb0ef41Sopenharmony_ci int rv; 5591cb0ef41Sopenharmony_ci nghttp2_buf *buf; 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci buf = &bufs->cur->buf; 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci buf->pos += nv_offset; 5661cb0ef41Sopenharmony_ci buf->last = buf->pos; 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci /* This call will adjust buf->last to the correct position */ 5691cb0ef41Sopenharmony_ci rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen); 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_ci if (rv == NGHTTP2_ERR_BUFFER_ERROR) { 5721cb0ef41Sopenharmony_ci rv = NGHTTP2_ERR_HEADER_COMP; 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci buf->pos -= nv_offset; 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci if (rv != 0) { 5781cb0ef41Sopenharmony_ci return rv; 5791cb0ef41Sopenharmony_ci } 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->pos, (uint32_t)frame->promised_stream_id); 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_ci frame->padlen = 0; 5841cb0ef41Sopenharmony_ci frame->hd.length = nghttp2_bufs_len(bufs); 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci return frame_pack_headers_shared(bufs, &frame->hd); 5871cb0ef41Sopenharmony_ci} 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame, 5901cb0ef41Sopenharmony_ci const uint8_t *payload) { 5911cb0ef41Sopenharmony_ci frame->promised_stream_id = 5921cb0ef41Sopenharmony_ci nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 5931cb0ef41Sopenharmony_ci frame->nva = NULL; 5941cb0ef41Sopenharmony_ci frame->nvlen = 0; 5951cb0ef41Sopenharmony_ci} 5961cb0ef41Sopenharmony_ci 5971cb0ef41Sopenharmony_civoid nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) { 5981cb0ef41Sopenharmony_ci nghttp2_buf *buf; 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 6031cb0ef41Sopenharmony_ci 6041cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 8); 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ci buf->last = 6111cb0ef41Sopenharmony_ci nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data)); 6121cb0ef41Sopenharmony_ci} 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame, 6151cb0ef41Sopenharmony_ci const uint8_t *payload) { 6161cb0ef41Sopenharmony_ci memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data)); 6171cb0ef41Sopenharmony_ci} 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_ciint nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) { 6201cb0ef41Sopenharmony_ci int rv; 6211cb0ef41Sopenharmony_ci nghttp2_buf *buf; 6221cb0ef41Sopenharmony_ci 6231cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 6301cb0ef41Sopenharmony_ci 6311cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->last, (uint32_t)frame->last_stream_id); 6321cb0ef41Sopenharmony_ci buf->last += 4; 6331cb0ef41Sopenharmony_ci 6341cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->last, frame->error_code); 6351cb0ef41Sopenharmony_ci buf->last += 4; 6361cb0ef41Sopenharmony_ci 6371cb0ef41Sopenharmony_ci rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len); 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci if (rv == NGHTTP2_ERR_BUFFER_ERROR) { 6401cb0ef41Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 6411cb0ef41Sopenharmony_ci } 6421cb0ef41Sopenharmony_ci 6431cb0ef41Sopenharmony_ci if (rv != 0) { 6441cb0ef41Sopenharmony_ci return rv; 6451cb0ef41Sopenharmony_ci } 6461cb0ef41Sopenharmony_ci 6471cb0ef41Sopenharmony_ci return 0; 6481cb0ef41Sopenharmony_ci} 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame, 6511cb0ef41Sopenharmony_ci const uint8_t *payload, 6521cb0ef41Sopenharmony_ci uint8_t *var_gift_payload, 6531cb0ef41Sopenharmony_ci size_t var_gift_payloadlen) { 6541cb0ef41Sopenharmony_ci frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 6551cb0ef41Sopenharmony_ci frame->error_code = nghttp2_get_uint32(payload + 4); 6561cb0ef41Sopenharmony_ci 6571cb0ef41Sopenharmony_ci frame->opaque_data = var_gift_payload; 6581cb0ef41Sopenharmony_ci frame->opaque_data_len = var_gift_payloadlen; 6591cb0ef41Sopenharmony_ci} 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ciint nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, 6621cb0ef41Sopenharmony_ci const uint8_t *payload, 6631cb0ef41Sopenharmony_ci size_t payloadlen, nghttp2_mem *mem) { 6641cb0ef41Sopenharmony_ci uint8_t *var_gift_payload; 6651cb0ef41Sopenharmony_ci size_t var_gift_payloadlen; 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci if (payloadlen > 8) { 6681cb0ef41Sopenharmony_ci var_gift_payloadlen = payloadlen - 8; 6691cb0ef41Sopenharmony_ci } else { 6701cb0ef41Sopenharmony_ci var_gift_payloadlen = 0; 6711cb0ef41Sopenharmony_ci } 6721cb0ef41Sopenharmony_ci 6731cb0ef41Sopenharmony_ci if (!var_gift_payloadlen) { 6741cb0ef41Sopenharmony_ci var_gift_payload = NULL; 6751cb0ef41Sopenharmony_ci } else { 6761cb0ef41Sopenharmony_ci var_gift_payload = nghttp2_mem_malloc(mem, var_gift_payloadlen); 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci if (var_gift_payload == NULL) { 6791cb0ef41Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 6801cb0ef41Sopenharmony_ci } 6811cb0ef41Sopenharmony_ci 6821cb0ef41Sopenharmony_ci memcpy(var_gift_payload, payload + 8, var_gift_payloadlen); 6831cb0ef41Sopenharmony_ci } 6841cb0ef41Sopenharmony_ci 6851cb0ef41Sopenharmony_ci nghttp2_frame_unpack_goaway_payload(frame, payload, var_gift_payload, 6861cb0ef41Sopenharmony_ci var_gift_payloadlen); 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_ci return 0; 6891cb0ef41Sopenharmony_ci} 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_civoid nghttp2_frame_pack_window_update(nghttp2_bufs *bufs, 6921cb0ef41Sopenharmony_ci nghttp2_window_update *frame) { 6931cb0ef41Sopenharmony_ci nghttp2_buf *buf; 6941cb0ef41Sopenharmony_ci 6951cb0ef41Sopenharmony_ci assert(bufs->head == bufs->cur); 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 6981cb0ef41Sopenharmony_ci 6991cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 4); 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment); 7061cb0ef41Sopenharmony_ci buf->last += 4; 7071cb0ef41Sopenharmony_ci} 7081cb0ef41Sopenharmony_ci 7091cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame, 7101cb0ef41Sopenharmony_ci const uint8_t *payload) { 7111cb0ef41Sopenharmony_ci frame->window_size_increment = 7121cb0ef41Sopenharmony_ci nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK; 7131cb0ef41Sopenharmony_ci} 7141cb0ef41Sopenharmony_ci 7151cb0ef41Sopenharmony_civoid nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) { 7161cb0ef41Sopenharmony_ci int rv; 7171cb0ef41Sopenharmony_ci nghttp2_buf *buf; 7181cb0ef41Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ci /* This is required with --disable-assert. */ 7211cb0ef41Sopenharmony_ci (void)rv; 7221cb0ef41Sopenharmony_ci 7231cb0ef41Sopenharmony_ci altsvc = frame->payload; 7241cb0ef41Sopenharmony_ci 7251cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 7281cb0ef41Sopenharmony_ci 2 + altsvc->origin_len + altsvc->field_value_len); 7291cb0ef41Sopenharmony_ci 7301cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 7311cb0ef41Sopenharmony_ci 7321cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 7331cb0ef41Sopenharmony_ci 7341cb0ef41Sopenharmony_ci nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len); 7351cb0ef41Sopenharmony_ci buf->last += 2; 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len); 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci assert(rv == 0); 7401cb0ef41Sopenharmony_ci 7411cb0ef41Sopenharmony_ci rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len); 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci assert(rv == 0); 7441cb0ef41Sopenharmony_ci} 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, 7471cb0ef41Sopenharmony_ci size_t origin_len, uint8_t *payload, 7481cb0ef41Sopenharmony_ci size_t payloadlen) { 7491cb0ef41Sopenharmony_ci nghttp2_ext_altsvc *altsvc; 7501cb0ef41Sopenharmony_ci uint8_t *p; 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci altsvc = frame->payload; 7531cb0ef41Sopenharmony_ci p = payload; 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_ci altsvc->origin = p; 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ci p += origin_len; 7581cb0ef41Sopenharmony_ci 7591cb0ef41Sopenharmony_ci altsvc->origin_len = origin_len; 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci altsvc->field_value = p; 7621cb0ef41Sopenharmony_ci altsvc->field_value_len = (size_t)(payload + payloadlen - p); 7631cb0ef41Sopenharmony_ci} 7641cb0ef41Sopenharmony_ci 7651cb0ef41Sopenharmony_ciint nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame, 7661cb0ef41Sopenharmony_ci const uint8_t *payload, 7671cb0ef41Sopenharmony_ci size_t payloadlen, nghttp2_mem *mem) { 7681cb0ef41Sopenharmony_ci uint8_t *buf; 7691cb0ef41Sopenharmony_ci size_t origin_len; 7701cb0ef41Sopenharmony_ci 7711cb0ef41Sopenharmony_ci if (payloadlen < 2) { 7721cb0ef41Sopenharmony_ci return NGHTTP2_FRAME_SIZE_ERROR; 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ci origin_len = nghttp2_get_uint16(payload); 7761cb0ef41Sopenharmony_ci 7771cb0ef41Sopenharmony_ci buf = nghttp2_mem_malloc(mem, payloadlen - 2); 7781cb0ef41Sopenharmony_ci if (!buf) { 7791cb0ef41Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_ci nghttp2_cpymem(buf, payload + 2, payloadlen - 2); 7831cb0ef41Sopenharmony_ci 7841cb0ef41Sopenharmony_ci nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2); 7851cb0ef41Sopenharmony_ci 7861cb0ef41Sopenharmony_ci return 0; 7871cb0ef41Sopenharmony_ci} 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ciint nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *frame) { 7901cb0ef41Sopenharmony_ci nghttp2_buf *buf; 7911cb0ef41Sopenharmony_ci nghttp2_ext_origin *origin; 7921cb0ef41Sopenharmony_ci nghttp2_origin_entry *orig; 7931cb0ef41Sopenharmony_ci size_t i; 7941cb0ef41Sopenharmony_ci 7951cb0ef41Sopenharmony_ci origin = frame->payload; 7961cb0ef41Sopenharmony_ci 7971cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci if (nghttp2_buf_avail(buf) < frame->hd.length) { 8001cb0ef41Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 8011cb0ef41Sopenharmony_ci } 8021cb0ef41Sopenharmony_ci 8031cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci for (i = 0; i < origin->nov; ++i) { 8081cb0ef41Sopenharmony_ci orig = &origin->ov[i]; 8091cb0ef41Sopenharmony_ci nghttp2_put_uint16be(buf->last, (uint16_t)orig->origin_len); 8101cb0ef41Sopenharmony_ci buf->last += 2; 8111cb0ef41Sopenharmony_ci buf->last = nghttp2_cpymem(buf->last, orig->origin, orig->origin_len); 8121cb0ef41Sopenharmony_ci } 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci assert(nghttp2_buf_len(buf) == NGHTTP2_FRAME_HDLEN + frame->hd.length); 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ci return 0; 8171cb0ef41Sopenharmony_ci} 8181cb0ef41Sopenharmony_ci 8191cb0ef41Sopenharmony_ciint nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame, 8201cb0ef41Sopenharmony_ci const uint8_t *payload, 8211cb0ef41Sopenharmony_ci size_t payloadlen, nghttp2_mem *mem) { 8221cb0ef41Sopenharmony_ci nghttp2_ext_origin *origin; 8231cb0ef41Sopenharmony_ci const uint8_t *p, *end; 8241cb0ef41Sopenharmony_ci uint8_t *dst; 8251cb0ef41Sopenharmony_ci size_t originlen; 8261cb0ef41Sopenharmony_ci nghttp2_origin_entry *ov; 8271cb0ef41Sopenharmony_ci size_t nov = 0; 8281cb0ef41Sopenharmony_ci size_t len = 0; 8291cb0ef41Sopenharmony_ci 8301cb0ef41Sopenharmony_ci origin = frame->payload; 8311cb0ef41Sopenharmony_ci p = end = payload; 8321cb0ef41Sopenharmony_ci if (payloadlen) { 8331cb0ef41Sopenharmony_ci end += payloadlen; 8341cb0ef41Sopenharmony_ci } 8351cb0ef41Sopenharmony_ci 8361cb0ef41Sopenharmony_ci for (; p != end;) { 8371cb0ef41Sopenharmony_ci if (end - p < 2) { 8381cb0ef41Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 8391cb0ef41Sopenharmony_ci } 8401cb0ef41Sopenharmony_ci originlen = nghttp2_get_uint16(p); 8411cb0ef41Sopenharmony_ci p += 2; 8421cb0ef41Sopenharmony_ci if (originlen == 0) { 8431cb0ef41Sopenharmony_ci continue; 8441cb0ef41Sopenharmony_ci } 8451cb0ef41Sopenharmony_ci if (originlen > (size_t)(end - p)) { 8461cb0ef41Sopenharmony_ci return NGHTTP2_ERR_FRAME_SIZE_ERROR; 8471cb0ef41Sopenharmony_ci } 8481cb0ef41Sopenharmony_ci p += originlen; 8491cb0ef41Sopenharmony_ci /* 1 for terminal NULL */ 8501cb0ef41Sopenharmony_ci len += originlen + 1; 8511cb0ef41Sopenharmony_ci ++nov; 8521cb0ef41Sopenharmony_ci } 8531cb0ef41Sopenharmony_ci 8541cb0ef41Sopenharmony_ci if (nov == 0) { 8551cb0ef41Sopenharmony_ci origin->ov = NULL; 8561cb0ef41Sopenharmony_ci origin->nov = 0; 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci return 0; 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci 8611cb0ef41Sopenharmony_ci len += nov * sizeof(nghttp2_origin_entry); 8621cb0ef41Sopenharmony_ci 8631cb0ef41Sopenharmony_ci ov = nghttp2_mem_malloc(mem, len); 8641cb0ef41Sopenharmony_ci if (ov == NULL) { 8651cb0ef41Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 8661cb0ef41Sopenharmony_ci } 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_ci origin->ov = ov; 8691cb0ef41Sopenharmony_ci origin->nov = nov; 8701cb0ef41Sopenharmony_ci 8711cb0ef41Sopenharmony_ci dst = (uint8_t *)ov + nov * sizeof(nghttp2_origin_entry); 8721cb0ef41Sopenharmony_ci p = payload; 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_ci for (; p != end;) { 8751cb0ef41Sopenharmony_ci originlen = nghttp2_get_uint16(p); 8761cb0ef41Sopenharmony_ci p += 2; 8771cb0ef41Sopenharmony_ci if (originlen == 0) { 8781cb0ef41Sopenharmony_ci continue; 8791cb0ef41Sopenharmony_ci } 8801cb0ef41Sopenharmony_ci ov->origin = dst; 8811cb0ef41Sopenharmony_ci ov->origin_len = originlen; 8821cb0ef41Sopenharmony_ci dst = nghttp2_cpymem(dst, p, originlen); 8831cb0ef41Sopenharmony_ci *dst++ = '\0'; 8841cb0ef41Sopenharmony_ci p += originlen; 8851cb0ef41Sopenharmony_ci ++ov; 8861cb0ef41Sopenharmony_ci } 8871cb0ef41Sopenharmony_ci 8881cb0ef41Sopenharmony_ci return 0; 8891cb0ef41Sopenharmony_ci} 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_civoid nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs, 8921cb0ef41Sopenharmony_ci nghttp2_extension *frame) { 8931cb0ef41Sopenharmony_ci int rv; 8941cb0ef41Sopenharmony_ci nghttp2_buf *buf; 8951cb0ef41Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 8961cb0ef41Sopenharmony_ci 8971cb0ef41Sopenharmony_ci /* This is required with --disable-assert. */ 8981cb0ef41Sopenharmony_ci (void)rv; 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci priority_update = frame->payload; 9011cb0ef41Sopenharmony_ci 9021cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 9031cb0ef41Sopenharmony_ci 9041cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= 4 + priority_update->field_value_len); 9051cb0ef41Sopenharmony_ci 9061cb0ef41Sopenharmony_ci buf->pos -= NGHTTP2_FRAME_HDLEN; 9071cb0ef41Sopenharmony_ci 9081cb0ef41Sopenharmony_ci nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); 9091cb0ef41Sopenharmony_ci 9101cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->last, (uint32_t)priority_update->stream_id); 9111cb0ef41Sopenharmony_ci buf->last += 4; 9121cb0ef41Sopenharmony_ci 9131cb0ef41Sopenharmony_ci rv = nghttp2_bufs_add(bufs, priority_update->field_value, 9141cb0ef41Sopenharmony_ci priority_update->field_value_len); 9151cb0ef41Sopenharmony_ci 9161cb0ef41Sopenharmony_ci assert(rv == 0); 9171cb0ef41Sopenharmony_ci} 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_civoid nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame, 9201cb0ef41Sopenharmony_ci uint8_t *payload, 9211cb0ef41Sopenharmony_ci size_t payloadlen) { 9221cb0ef41Sopenharmony_ci nghttp2_ext_priority_update *priority_update; 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ci assert(payloadlen >= 4); 9251cb0ef41Sopenharmony_ci 9261cb0ef41Sopenharmony_ci priority_update = frame->payload; 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci priority_update->stream_id = 9291cb0ef41Sopenharmony_ci nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ci if (payloadlen > 4) { 9321cb0ef41Sopenharmony_ci priority_update->field_value = payload + 4; 9331cb0ef41Sopenharmony_ci priority_update->field_value_len = payloadlen - 4; 9341cb0ef41Sopenharmony_ci } else { 9351cb0ef41Sopenharmony_ci priority_update->field_value = NULL; 9361cb0ef41Sopenharmony_ci priority_update->field_value_len = 0; 9371cb0ef41Sopenharmony_ci } 9381cb0ef41Sopenharmony_ci} 9391cb0ef41Sopenharmony_ci 9401cb0ef41Sopenharmony_cinghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv, 9411cb0ef41Sopenharmony_ci size_t niv, nghttp2_mem *mem) { 9421cb0ef41Sopenharmony_ci nghttp2_settings_entry *iv_copy; 9431cb0ef41Sopenharmony_ci size_t len = niv * sizeof(nghttp2_settings_entry); 9441cb0ef41Sopenharmony_ci 9451cb0ef41Sopenharmony_ci if (len == 0) { 9461cb0ef41Sopenharmony_ci return NULL; 9471cb0ef41Sopenharmony_ci } 9481cb0ef41Sopenharmony_ci 9491cb0ef41Sopenharmony_ci iv_copy = nghttp2_mem_malloc(mem, len); 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ci if (iv_copy == NULL) { 9521cb0ef41Sopenharmony_ci return NULL; 9531cb0ef41Sopenharmony_ci } 9541cb0ef41Sopenharmony_ci 9551cb0ef41Sopenharmony_ci memcpy(iv_copy, iv, len); 9561cb0ef41Sopenharmony_ci 9571cb0ef41Sopenharmony_ci return iv_copy; 9581cb0ef41Sopenharmony_ci} 9591cb0ef41Sopenharmony_ci 9601cb0ef41Sopenharmony_ciint nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b) { 9611cb0ef41Sopenharmony_ci if (a->namelen != b->namelen || a->valuelen != b->valuelen) { 9621cb0ef41Sopenharmony_ci return 0; 9631cb0ef41Sopenharmony_ci } 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_ci if (a->name == NULL || b->name == NULL) { 9661cb0ef41Sopenharmony_ci assert(a->namelen == 0); 9671cb0ef41Sopenharmony_ci assert(b->namelen == 0); 9681cb0ef41Sopenharmony_ci } else if (memcmp(a->name, b->name, a->namelen) != 0) { 9691cb0ef41Sopenharmony_ci return 0; 9701cb0ef41Sopenharmony_ci } 9711cb0ef41Sopenharmony_ci 9721cb0ef41Sopenharmony_ci if (a->value == NULL || b->value == NULL) { 9731cb0ef41Sopenharmony_ci assert(a->valuelen == 0); 9741cb0ef41Sopenharmony_ci assert(b->valuelen == 0); 9751cb0ef41Sopenharmony_ci } else if (memcmp(a->value, b->value, a->valuelen) != 0) { 9761cb0ef41Sopenharmony_ci return 0; 9771cb0ef41Sopenharmony_ci } 9781cb0ef41Sopenharmony_ci 9791cb0ef41Sopenharmony_ci return 1; 9801cb0ef41Sopenharmony_ci} 9811cb0ef41Sopenharmony_ci 9821cb0ef41Sopenharmony_civoid nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem) { 9831cb0ef41Sopenharmony_ci nghttp2_mem_free(mem, nva); 9841cb0ef41Sopenharmony_ci} 9851cb0ef41Sopenharmony_ci 9861cb0ef41Sopenharmony_cistatic int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b, 9871cb0ef41Sopenharmony_ci size_t blen) { 9881cb0ef41Sopenharmony_ci int rv; 9891cb0ef41Sopenharmony_ci 9901cb0ef41Sopenharmony_ci if (alen == blen) { 9911cb0ef41Sopenharmony_ci return memcmp(a, b, alen); 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci 9941cb0ef41Sopenharmony_ci if (alen < blen) { 9951cb0ef41Sopenharmony_ci rv = memcmp(a, b, alen); 9961cb0ef41Sopenharmony_ci 9971cb0ef41Sopenharmony_ci if (rv == 0) { 9981cb0ef41Sopenharmony_ci return -1; 9991cb0ef41Sopenharmony_ci } 10001cb0ef41Sopenharmony_ci 10011cb0ef41Sopenharmony_ci return rv; 10021cb0ef41Sopenharmony_ci } 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_ci rv = memcmp(a, b, blen); 10051cb0ef41Sopenharmony_ci 10061cb0ef41Sopenharmony_ci if (rv == 0) { 10071cb0ef41Sopenharmony_ci return 1; 10081cb0ef41Sopenharmony_ci } 10091cb0ef41Sopenharmony_ci 10101cb0ef41Sopenharmony_ci return rv; 10111cb0ef41Sopenharmony_ci} 10121cb0ef41Sopenharmony_ci 10131cb0ef41Sopenharmony_ciint nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) { 10141cb0ef41Sopenharmony_ci return bytes_compar(lhs->name, lhs->namelen, rhs->name, rhs->namelen); 10151cb0ef41Sopenharmony_ci} 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_cistatic int nv_compar(const void *lhs, const void *rhs) { 10181cb0ef41Sopenharmony_ci const nghttp2_nv *a = (const nghttp2_nv *)lhs; 10191cb0ef41Sopenharmony_ci const nghttp2_nv *b = (const nghttp2_nv *)rhs; 10201cb0ef41Sopenharmony_ci int rv; 10211cb0ef41Sopenharmony_ci 10221cb0ef41Sopenharmony_ci rv = bytes_compar(a->name, a->namelen, b->name, b->namelen); 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_ci if (rv == 0) { 10251cb0ef41Sopenharmony_ci return bytes_compar(a->value, a->valuelen, b->value, b->valuelen); 10261cb0ef41Sopenharmony_ci } 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_ci return rv; 10291cb0ef41Sopenharmony_ci} 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_civoid nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) { 10321cb0ef41Sopenharmony_ci qsort(nva, nvlen, sizeof(nghttp2_nv), nv_compar); 10331cb0ef41Sopenharmony_ci} 10341cb0ef41Sopenharmony_ci 10351cb0ef41Sopenharmony_ciint nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva, 10361cb0ef41Sopenharmony_ci size_t nvlen, nghttp2_mem *mem) { 10371cb0ef41Sopenharmony_ci size_t i; 10381cb0ef41Sopenharmony_ci uint8_t *data = NULL; 10391cb0ef41Sopenharmony_ci size_t buflen = 0; 10401cb0ef41Sopenharmony_ci nghttp2_nv *p; 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_ci if (nvlen == 0) { 10431cb0ef41Sopenharmony_ci *nva_ptr = NULL; 10441cb0ef41Sopenharmony_ci 10451cb0ef41Sopenharmony_ci return 0; 10461cb0ef41Sopenharmony_ci } 10471cb0ef41Sopenharmony_ci 10481cb0ef41Sopenharmony_ci for (i = 0; i < nvlen; ++i) { 10491cb0ef41Sopenharmony_ci /* + 1 for null-termination */ 10501cb0ef41Sopenharmony_ci if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) { 10511cb0ef41Sopenharmony_ci buflen += nva[i].namelen + 1; 10521cb0ef41Sopenharmony_ci } 10531cb0ef41Sopenharmony_ci if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) { 10541cb0ef41Sopenharmony_ci buflen += nva[i].valuelen + 1; 10551cb0ef41Sopenharmony_ci } 10561cb0ef41Sopenharmony_ci } 10571cb0ef41Sopenharmony_ci 10581cb0ef41Sopenharmony_ci buflen += sizeof(nghttp2_nv) * nvlen; 10591cb0ef41Sopenharmony_ci 10601cb0ef41Sopenharmony_ci *nva_ptr = nghttp2_mem_malloc(mem, buflen); 10611cb0ef41Sopenharmony_ci 10621cb0ef41Sopenharmony_ci if (*nva_ptr == NULL) { 10631cb0ef41Sopenharmony_ci return NGHTTP2_ERR_NOMEM; 10641cb0ef41Sopenharmony_ci } 10651cb0ef41Sopenharmony_ci 10661cb0ef41Sopenharmony_ci p = *nva_ptr; 10671cb0ef41Sopenharmony_ci data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen; 10681cb0ef41Sopenharmony_ci 10691cb0ef41Sopenharmony_ci for (i = 0; i < nvlen; ++i) { 10701cb0ef41Sopenharmony_ci p->flags = nva[i].flags; 10711cb0ef41Sopenharmony_ci 10721cb0ef41Sopenharmony_ci if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) { 10731cb0ef41Sopenharmony_ci p->name = nva[i].name; 10741cb0ef41Sopenharmony_ci p->namelen = nva[i].namelen; 10751cb0ef41Sopenharmony_ci } else { 10761cb0ef41Sopenharmony_ci if (nva[i].namelen) { 10771cb0ef41Sopenharmony_ci memcpy(data, nva[i].name, nva[i].namelen); 10781cb0ef41Sopenharmony_ci } 10791cb0ef41Sopenharmony_ci p->name = data; 10801cb0ef41Sopenharmony_ci p->namelen = nva[i].namelen; 10811cb0ef41Sopenharmony_ci data[p->namelen] = '\0'; 10821cb0ef41Sopenharmony_ci nghttp2_downcase(p->name, p->namelen); 10831cb0ef41Sopenharmony_ci data += nva[i].namelen + 1; 10841cb0ef41Sopenharmony_ci } 10851cb0ef41Sopenharmony_ci 10861cb0ef41Sopenharmony_ci if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) { 10871cb0ef41Sopenharmony_ci p->value = nva[i].value; 10881cb0ef41Sopenharmony_ci p->valuelen = nva[i].valuelen; 10891cb0ef41Sopenharmony_ci } else { 10901cb0ef41Sopenharmony_ci if (nva[i].valuelen) { 10911cb0ef41Sopenharmony_ci memcpy(data, nva[i].value, nva[i].valuelen); 10921cb0ef41Sopenharmony_ci } 10931cb0ef41Sopenharmony_ci p->value = data; 10941cb0ef41Sopenharmony_ci p->valuelen = nva[i].valuelen; 10951cb0ef41Sopenharmony_ci data[p->valuelen] = '\0'; 10961cb0ef41Sopenharmony_ci data += nva[i].valuelen + 1; 10971cb0ef41Sopenharmony_ci } 10981cb0ef41Sopenharmony_ci 10991cb0ef41Sopenharmony_ci ++p; 11001cb0ef41Sopenharmony_ci } 11011cb0ef41Sopenharmony_ci return 0; 11021cb0ef41Sopenharmony_ci} 11031cb0ef41Sopenharmony_ci 11041cb0ef41Sopenharmony_ciint nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) { 11051cb0ef41Sopenharmony_ci size_t i; 11061cb0ef41Sopenharmony_ci for (i = 0; i < niv; ++i) { 11071cb0ef41Sopenharmony_ci switch (iv[i].settings_id) { 11081cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: 11091cb0ef41Sopenharmony_ci break; 11101cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: 11111cb0ef41Sopenharmony_ci break; 11121cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_ENABLE_PUSH: 11131cb0ef41Sopenharmony_ci if (iv[i].value != 0 && iv[i].value != 1) { 11141cb0ef41Sopenharmony_ci return 0; 11151cb0ef41Sopenharmony_ci } 11161cb0ef41Sopenharmony_ci break; 11171cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: 11181cb0ef41Sopenharmony_ci if (iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) { 11191cb0ef41Sopenharmony_ci return 0; 11201cb0ef41Sopenharmony_ci } 11211cb0ef41Sopenharmony_ci break; 11221cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: 11231cb0ef41Sopenharmony_ci if (iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN || 11241cb0ef41Sopenharmony_ci iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) { 11251cb0ef41Sopenharmony_ci return 0; 11261cb0ef41Sopenharmony_ci } 11271cb0ef41Sopenharmony_ci break; 11281cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: 11291cb0ef41Sopenharmony_ci break; 11301cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: 11311cb0ef41Sopenharmony_ci if (iv[i].value != 0 && iv[i].value != 1) { 11321cb0ef41Sopenharmony_ci return 0; 11331cb0ef41Sopenharmony_ci } 11341cb0ef41Sopenharmony_ci break; 11351cb0ef41Sopenharmony_ci case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES: 11361cb0ef41Sopenharmony_ci if (iv[i].value != 0 && iv[i].value != 1) { 11371cb0ef41Sopenharmony_ci return 0; 11381cb0ef41Sopenharmony_ci } 11391cb0ef41Sopenharmony_ci break; 11401cb0ef41Sopenharmony_ci } 11411cb0ef41Sopenharmony_ci } 11421cb0ef41Sopenharmony_ci return 1; 11431cb0ef41Sopenharmony_ci} 11441cb0ef41Sopenharmony_ci 11451cb0ef41Sopenharmony_cistatic void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) { 11461cb0ef41Sopenharmony_ci size_t trail_padlen; 11471cb0ef41Sopenharmony_ci size_t newlen; 11481cb0ef41Sopenharmony_ci 11491cb0ef41Sopenharmony_ci DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen); 11501cb0ef41Sopenharmony_ci 11511cb0ef41Sopenharmony_ci memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN); 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_ci --buf->pos; 11541cb0ef41Sopenharmony_ci 11551cb0ef41Sopenharmony_ci buf->pos[4] |= NGHTTP2_FLAG_PADDED; 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ci newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen; 11581cb0ef41Sopenharmony_ci nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3])); 11591cb0ef41Sopenharmony_ci 11601cb0ef41Sopenharmony_ci if (framehd_only) { 11611cb0ef41Sopenharmony_ci return; 11621cb0ef41Sopenharmony_ci } 11631cb0ef41Sopenharmony_ci 11641cb0ef41Sopenharmony_ci trail_padlen = padlen - 1; 11651cb0ef41Sopenharmony_ci buf->pos[NGHTTP2_FRAME_HDLEN] = (uint8_t)trail_padlen; 11661cb0ef41Sopenharmony_ci 11671cb0ef41Sopenharmony_ci /* zero out padding */ 11681cb0ef41Sopenharmony_ci memset(buf->last, 0, trail_padlen); 11691cb0ef41Sopenharmony_ci /* extend buffers trail_padlen bytes, since we ate previous padlen - 11701cb0ef41Sopenharmony_ci trail_padlen byte(s) */ 11711cb0ef41Sopenharmony_ci buf->last += trail_padlen; 11721cb0ef41Sopenharmony_ci} 11731cb0ef41Sopenharmony_ci 11741cb0ef41Sopenharmony_civoid nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, 11751cb0ef41Sopenharmony_ci size_t padlen, int framehd_only) { 11761cb0ef41Sopenharmony_ci nghttp2_buf *buf; 11771cb0ef41Sopenharmony_ci 11781cb0ef41Sopenharmony_ci if (padlen == 0) { 11791cb0ef41Sopenharmony_ci DEBUGF("send: padlen = 0, nothing to do\n"); 11801cb0ef41Sopenharmony_ci 11811cb0ef41Sopenharmony_ci return; 11821cb0ef41Sopenharmony_ci } 11831cb0ef41Sopenharmony_ci 11841cb0ef41Sopenharmony_ci /* 11851cb0ef41Sopenharmony_ci * We have arranged bufs like this: 11861cb0ef41Sopenharmony_ci * 11871cb0ef41Sopenharmony_ci * 0 1 2 3 11881cb0ef41Sopenharmony_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 11891cb0ef41Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11901cb0ef41Sopenharmony_ci * | |Frame header | Frame payload... : 11911cb0ef41Sopenharmony_ci * +-+-----------------+-------------------------------------------+ 11921cb0ef41Sopenharmony_ci * | |Frame header | Frame payload... : 11931cb0ef41Sopenharmony_ci * +-+-----------------+-------------------------------------------+ 11941cb0ef41Sopenharmony_ci * | |Frame header | Frame payload... : 11951cb0ef41Sopenharmony_ci * +-+-----------------+-------------------------------------------+ 11961cb0ef41Sopenharmony_ci * 11971cb0ef41Sopenharmony_ci * We arranged padding so that it is included in the first frame 11981cb0ef41Sopenharmony_ci * completely. For padded frame, we are going to adjust buf->pos of 11991cb0ef41Sopenharmony_ci * frame which includes padding and serialize (memmove) frame header 12001cb0ef41Sopenharmony_ci * in the correct position. Also extends buf->last to include 12011cb0ef41Sopenharmony_ci * padding. 12021cb0ef41Sopenharmony_ci */ 12031cb0ef41Sopenharmony_ci 12041cb0ef41Sopenharmony_ci buf = &bufs->head->buf; 12051cb0ef41Sopenharmony_ci 12061cb0ef41Sopenharmony_ci assert(nghttp2_buf_avail(buf) >= padlen - 1); 12071cb0ef41Sopenharmony_ci 12081cb0ef41Sopenharmony_ci frame_set_pad(buf, padlen, framehd_only); 12091cb0ef41Sopenharmony_ci 12101cb0ef41Sopenharmony_ci hd->length += padlen; 12111cb0ef41Sopenharmony_ci hd->flags |= NGHTTP2_FLAG_PADDED; 12121cb0ef41Sopenharmony_ci 12131cb0ef41Sopenharmony_ci DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen); 12141cb0ef41Sopenharmony_ci} 1215