11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * nghttp2 - HTTP/2 C Library 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Copyright (c) 2015 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_http.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci#include <string.h> 281cb0ef41Sopenharmony_ci#include <assert.h> 291cb0ef41Sopenharmony_ci#include <stdio.h> 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#include "nghttp2_hd.h" 321cb0ef41Sopenharmony_ci#include "nghttp2_helper.h" 331cb0ef41Sopenharmony_ci#include "nghttp2_extpri.h" 341cb0ef41Sopenharmony_ci#include "sfparse.h" 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_cistatic uint8_t downcase(uint8_t c) { 371cb0ef41Sopenharmony_ci return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c; 381cb0ef41Sopenharmony_ci} 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cistatic int memieq(const void *a, const void *b, size_t n) { 411cb0ef41Sopenharmony_ci size_t i; 421cb0ef41Sopenharmony_ci const uint8_t *aa = a, *bb = b; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci for (i = 0; i < n; ++i) { 451cb0ef41Sopenharmony_ci if (downcase(aa[i]) != downcase(bb[i])) { 461cb0ef41Sopenharmony_ci return 0; 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci } 491cb0ef41Sopenharmony_ci return 1; 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci#define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N))) 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cistatic int64_t parse_uint(const uint8_t *s, size_t len) { 551cb0ef41Sopenharmony_ci int64_t n = 0; 561cb0ef41Sopenharmony_ci size_t i; 571cb0ef41Sopenharmony_ci if (len == 0) { 581cb0ef41Sopenharmony_ci return -1; 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci for (i = 0; i < len; ++i) { 611cb0ef41Sopenharmony_ci if ('0' <= s[i] && s[i] <= '9') { 621cb0ef41Sopenharmony_ci if (n > INT64_MAX / 10) { 631cb0ef41Sopenharmony_ci return -1; 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci n *= 10; 661cb0ef41Sopenharmony_ci if (n > INT64_MAX - (s[i] - '0')) { 671cb0ef41Sopenharmony_ci return -1; 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci n += s[i] - '0'; 701cb0ef41Sopenharmony_ci continue; 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci return -1; 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci return n; 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_cistatic int check_pseudo_header(nghttp2_stream *stream, const nghttp2_hd_nv *nv, 781cb0ef41Sopenharmony_ci uint32_t flag) { 791cb0ef41Sopenharmony_ci if ((stream->http_flags & flag) || nv->value->len == 0) { 801cb0ef41Sopenharmony_ci return 0; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci stream->http_flags = stream->http_flags | flag; 831cb0ef41Sopenharmony_ci return 1; 841cb0ef41Sopenharmony_ci} 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cistatic int expect_response_body(nghttp2_stream *stream) { 871cb0ef41Sopenharmony_ci return (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_HEAD) == 0 && 881cb0ef41Sopenharmony_ci stream->status_code / 100 != 1 && stream->status_code != 304 && 891cb0ef41Sopenharmony_ci stream->status_code != 204; 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci/* For "http" or "https" URIs, OPTIONS request may have "*" in :path 931cb0ef41Sopenharmony_ci header field to represent system-wide OPTIONS request. Otherwise, 941cb0ef41Sopenharmony_ci :path header field value must start with "/". This function must 951cb0ef41Sopenharmony_ci be called after ":method" header field was received. This function 961cb0ef41Sopenharmony_ci returns nonzero if path is valid.*/ 971cb0ef41Sopenharmony_cistatic int check_path(nghttp2_stream *stream) { 981cb0ef41Sopenharmony_ci return (stream->http_flags & NGHTTP2_HTTP_FLAG_SCHEME_HTTP) == 0 || 991cb0ef41Sopenharmony_ci ((stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_REGULAR) || 1001cb0ef41Sopenharmony_ci ((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_OPTIONS) && 1011cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_ASTERISK))); 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_cistatic int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv, 1051cb0ef41Sopenharmony_ci int trailer, int connect_protocol) { 1061cb0ef41Sopenharmony_ci nghttp2_extpri extpri; 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci if (nv->name->base[0] == ':') { 1091cb0ef41Sopenharmony_ci if (trailer || 1101cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { 1111cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci switch (nv->token) { 1161cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__AUTHORITY: 1171cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) { 1181cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci break; 1211cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__METHOD: 1221cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) { 1231cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci switch (nv->value->len) { 1261cb0ef41Sopenharmony_ci case 4: 1271cb0ef41Sopenharmony_ci if (lstreq("HEAD", nv->value->base, nv->value->len)) { 1281cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; 1291cb0ef41Sopenharmony_ci } 1301cb0ef41Sopenharmony_ci break; 1311cb0ef41Sopenharmony_ci case 7: 1321cb0ef41Sopenharmony_ci switch (nv->value->base[6]) { 1331cb0ef41Sopenharmony_ci case 'T': 1341cb0ef41Sopenharmony_ci if (lstreq("CONNECT", nv->value->base, nv->value->len)) { 1351cb0ef41Sopenharmony_ci if (stream->stream_id % 2 == 0) { 1361cb0ef41Sopenharmony_ci /* we won't allow CONNECT for push */ 1371cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci break; 1421cb0ef41Sopenharmony_ci case 'S': 1431cb0ef41Sopenharmony_ci if (lstreq("OPTIONS", nv->value->base, nv->value->len)) { 1441cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci break; 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci break; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci break; 1511cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__PATH: 1521cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) { 1531cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci if (nv->value->base[0] == '/') { 1561cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_REGULAR; 1571cb0ef41Sopenharmony_ci } else if (nv->value->len == 1 && nv->value->base[0] == '*') { 1581cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_ASTERISK; 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci break; 1611cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__SCHEME: 1621cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) { 1631cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) || 1661cb0ef41Sopenharmony_ci (nv->value->len == 5 && memieq("https", nv->value->base, 5))) { 1671cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP; 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci break; 1701cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__PROTOCOL: 1711cb0ef41Sopenharmony_ci if (!connect_protocol) { 1721cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PROTOCOL)) { 1761cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci break; 1791cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_HOST: 1801cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) { 1811cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci break; 1841cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_CONTENT_LENGTH: { 1851cb0ef41Sopenharmony_ci if (stream->content_length != -1) { 1861cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1871cb0ef41Sopenharmony_ci } 1881cb0ef41Sopenharmony_ci stream->content_length = parse_uint(nv->value->base, nv->value->len); 1891cb0ef41Sopenharmony_ci if (stream->content_length == -1) { 1901cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci break; 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci /* disallowed header fields */ 1951cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_CONNECTION: 1961cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_KEEP_ALIVE: 1971cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_PROXY_CONNECTION: 1981cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_TRANSFER_ENCODING: 1991cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_UPGRADE: 2001cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2011cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_TE: 2021cb0ef41Sopenharmony_ci if (!lstrieq("trailers", nv->value->base, nv->value->len)) { 2031cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci break; 2061cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_PRIORITY: 2071cb0ef41Sopenharmony_ci if (!trailer && 2081cb0ef41Sopenharmony_ci /* Do not parse the header field in PUSH_PROMISE. */ 2091cb0ef41Sopenharmony_ci (stream->stream_id & 1) && 2101cb0ef41Sopenharmony_ci (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) && 2111cb0ef41Sopenharmony_ci !(stream->http_flags & NGHTTP2_HTTP_FLAG_BAD_PRIORITY)) { 2121cb0ef41Sopenharmony_ci nghttp2_extpri_from_uint8(&extpri, stream->http_extpri); 2131cb0ef41Sopenharmony_ci if (nghttp2_http_parse_priority(&extpri, nv->value->base, 2141cb0ef41Sopenharmony_ci nv->value->len) == 0) { 2151cb0ef41Sopenharmony_ci stream->http_extpri = nghttp2_extpri_to_uint8(&extpri); 2161cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PRIORITY; 2171cb0ef41Sopenharmony_ci } else { 2181cb0ef41Sopenharmony_ci stream->http_flags &= (uint32_t)~NGHTTP2_HTTP_FLAG_PRIORITY; 2191cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_BAD_PRIORITY; 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci break; 2231cb0ef41Sopenharmony_ci default: 2241cb0ef41Sopenharmony_ci if (nv->name->base[0] == ':') { 2251cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci if (nv->name->base[0] != ':') { 2301cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci return 0; 2341cb0ef41Sopenharmony_ci} 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_cistatic int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv, 2371cb0ef41Sopenharmony_ci int trailer) { 2381cb0ef41Sopenharmony_ci if (nv->name->base[0] == ':') { 2391cb0ef41Sopenharmony_ci if (trailer || 2401cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { 2411cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci switch (nv->token) { 2461cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__STATUS: { 2471cb0ef41Sopenharmony_ci if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) { 2481cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci if (nv->value->len != 3) { 2511cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len); 2541cb0ef41Sopenharmony_ci if (stream->status_code == -1 || stream->status_code == 101) { 2551cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci break; 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_CONTENT_LENGTH: { 2601cb0ef41Sopenharmony_ci if (stream->status_code == 204) { 2611cb0ef41Sopenharmony_ci /* content-length header field in 204 response is prohibited by 2621cb0ef41Sopenharmony_ci RFC 7230. But some widely used servers send content-length: 2631cb0ef41Sopenharmony_ci 0. Until they get fixed, we ignore it. */ 2641cb0ef41Sopenharmony_ci if (stream->content_length != -1) { 2651cb0ef41Sopenharmony_ci /* Found multiple content-length field */ 2661cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci if (!lstrieq("0", nv->value->base, nv->value->len)) { 2691cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci stream->content_length = 0; 2721cb0ef41Sopenharmony_ci return NGHTTP2_ERR_REMOVE_HTTP_HEADER; 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci if (stream->status_code / 100 == 1) { 2751cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci /* https://tools.ietf.org/html/rfc7230#section-3.3.3 */ 2781cb0ef41Sopenharmony_ci if (stream->status_code / 100 == 2 && 2791cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT)) { 2801cb0ef41Sopenharmony_ci return NGHTTP2_ERR_REMOVE_HTTP_HEADER; 2811cb0ef41Sopenharmony_ci } 2821cb0ef41Sopenharmony_ci if (stream->content_length != -1) { 2831cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci stream->content_length = parse_uint(nv->value->base, nv->value->len); 2861cb0ef41Sopenharmony_ci if (stream->content_length == -1) { 2871cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci break; 2901cb0ef41Sopenharmony_ci } 2911cb0ef41Sopenharmony_ci /* disallowed header fields */ 2921cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_CONNECTION: 2931cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_KEEP_ALIVE: 2941cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_PROXY_CONNECTION: 2951cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_TRANSFER_ENCODING: 2961cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_UPGRADE: 2971cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 2981cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_TE: 2991cb0ef41Sopenharmony_ci if (!lstrieq("trailers", nv->value->base, nv->value->len)) { 3001cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 3011cb0ef41Sopenharmony_ci } 3021cb0ef41Sopenharmony_ci break; 3031cb0ef41Sopenharmony_ci default: 3041cb0ef41Sopenharmony_ci if (nv->name->base[0] == ':') { 3051cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 3061cb0ef41Sopenharmony_ci } 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci if (nv->name->base[0] != ':') { 3101cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci return 0; 3141cb0ef41Sopenharmony_ci} 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_cistatic int check_scheme(const uint8_t *value, size_t len) { 3171cb0ef41Sopenharmony_ci const uint8_t *last; 3181cb0ef41Sopenharmony_ci if (len == 0) { 3191cb0ef41Sopenharmony_ci return 0; 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci if (!(('A' <= *value && *value <= 'Z') || ('a' <= *value && *value <= 'z'))) { 3231cb0ef41Sopenharmony_ci return 0; 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci last = value + len; 3271cb0ef41Sopenharmony_ci ++value; 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci for (; value != last; ++value) { 3301cb0ef41Sopenharmony_ci if (!(('A' <= *value && *value <= 'Z') || 3311cb0ef41Sopenharmony_ci ('a' <= *value && *value <= 'z') || 3321cb0ef41Sopenharmony_ci ('0' <= *value && *value <= '9') || *value == '+' || *value == '-' || 3331cb0ef41Sopenharmony_ci *value == '.')) { 3341cb0ef41Sopenharmony_ci return 0; 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci } 3371cb0ef41Sopenharmony_ci return 1; 3381cb0ef41Sopenharmony_ci} 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_cistatic int lws(const uint8_t *s, size_t n) { 3411cb0ef41Sopenharmony_ci size_t i; 3421cb0ef41Sopenharmony_ci for (i = 0; i < n; ++i) { 3431cb0ef41Sopenharmony_ci if (s[i] != ' ' && s[i] != '\t') { 3441cb0ef41Sopenharmony_ci return 0; 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci return 1; 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ciint nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, 3511cb0ef41Sopenharmony_ci nghttp2_frame *frame, nghttp2_hd_nv *nv, 3521cb0ef41Sopenharmony_ci int trailer) { 3531cb0ef41Sopenharmony_ci int rv; 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci /* We are strict for pseudo header field. One bad character should 3561cb0ef41Sopenharmony_ci lead to fail. OTOH, we should be a bit forgiving for regular 3571cb0ef41Sopenharmony_ci headers, since existing public internet has so much illegal 3581cb0ef41Sopenharmony_ci headers floating around and if we kill the stream because of 3591cb0ef41Sopenharmony_ci this, we may disrupt many web sites and/or libraries. So we 3601cb0ef41Sopenharmony_ci become conservative here, and just ignore those illegal regular 3611cb0ef41Sopenharmony_ci headers. */ 3621cb0ef41Sopenharmony_ci if (!nghttp2_check_header_name(nv->name->base, nv->name->len)) { 3631cb0ef41Sopenharmony_ci size_t i; 3641cb0ef41Sopenharmony_ci if (nv->name->len > 0 && nv->name->base[0] == ':') { 3651cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 3661cb0ef41Sopenharmony_ci } 3671cb0ef41Sopenharmony_ci /* header field name must be lower-cased without exception */ 3681cb0ef41Sopenharmony_ci for (i = 0; i < nv->name->len; ++i) { 3691cb0ef41Sopenharmony_ci uint8_t c = nv->name->base[i]; 3701cb0ef41Sopenharmony_ci if ('A' <= c && c <= 'Z') { 3711cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci } 3741cb0ef41Sopenharmony_ci /* When ignoring regular headers, we set this flag so that we 3751cb0ef41Sopenharmony_ci still enforce header field ordering rule for pseudo header 3761cb0ef41Sopenharmony_ci fields. */ 3771cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; 3781cb0ef41Sopenharmony_ci return NGHTTP2_ERR_IGN_HTTP_HEADER; 3791cb0ef41Sopenharmony_ci } 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci switch (nv->token) { 3821cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__METHOD: 3831cb0ef41Sopenharmony_ci rv = nghttp2_check_method(nv->value->base, nv->value->len); 3841cb0ef41Sopenharmony_ci break; 3851cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__PATH: 3861cb0ef41Sopenharmony_ci rv = nghttp2_check_path(nv->value->base, nv->value->len); 3871cb0ef41Sopenharmony_ci break; 3881cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__AUTHORITY: 3891cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN_HOST: 3901cb0ef41Sopenharmony_ci if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) { 3911cb0ef41Sopenharmony_ci rv = nghttp2_check_authority(nv->value->base, nv->value->len); 3921cb0ef41Sopenharmony_ci } else if ( 3931cb0ef41Sopenharmony_ci stream->flags & 3941cb0ef41Sopenharmony_ci NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) { 3951cb0ef41Sopenharmony_ci rv = nghttp2_check_header_value(nv->value->base, nv->value->len); 3961cb0ef41Sopenharmony_ci } else { 3971cb0ef41Sopenharmony_ci rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len); 3981cb0ef41Sopenharmony_ci } 3991cb0ef41Sopenharmony_ci break; 4001cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__SCHEME: 4011cb0ef41Sopenharmony_ci rv = check_scheme(nv->value->base, nv->value->len); 4021cb0ef41Sopenharmony_ci break; 4031cb0ef41Sopenharmony_ci case NGHTTP2_TOKEN__PROTOCOL: 4041cb0ef41Sopenharmony_ci /* Check the value consists of just white spaces, which was done 4051cb0ef41Sopenharmony_ci in check_pseudo_header before 4061cb0ef41Sopenharmony_ci nghttp2_check_header_value_rfc9113 has been introduced. */ 4071cb0ef41Sopenharmony_ci if ((stream->flags & 4081cb0ef41Sopenharmony_ci NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) && 4091cb0ef41Sopenharmony_ci lws(nv->value->base, nv->value->len)) { 4101cb0ef41Sopenharmony_ci rv = 0; 4111cb0ef41Sopenharmony_ci break; 4121cb0ef41Sopenharmony_ci } 4131cb0ef41Sopenharmony_ci /* fall through */ 4141cb0ef41Sopenharmony_ci default: 4151cb0ef41Sopenharmony_ci if (stream->flags & 4161cb0ef41Sopenharmony_ci NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) { 4171cb0ef41Sopenharmony_ci rv = nghttp2_check_header_value(nv->value->base, nv->value->len); 4181cb0ef41Sopenharmony_ci } else { 4191cb0ef41Sopenharmony_ci rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len); 4201cb0ef41Sopenharmony_ci } 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci if (rv == 0) { 4241cb0ef41Sopenharmony_ci assert(nv->name->len > 0); 4251cb0ef41Sopenharmony_ci if (nv->name->base[0] == ':') { 4261cb0ef41Sopenharmony_ci return NGHTTP2_ERR_HTTP_HEADER; 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci /* When ignoring regular headers, we set this flag so that we 4291cb0ef41Sopenharmony_ci still enforce header field ordering rule for pseudo header 4301cb0ef41Sopenharmony_ci fields. */ 4311cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; 4321cb0ef41Sopenharmony_ci return NGHTTP2_ERR_IGN_HTTP_HEADER; 4331cb0ef41Sopenharmony_ci } 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) { 4361cb0ef41Sopenharmony_ci return http_request_on_header(stream, nv, trailer, 4371cb0ef41Sopenharmony_ci session->server && 4381cb0ef41Sopenharmony_ci session->pending_enable_connect_protocol); 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci return http_response_on_header(stream, nv, trailer); 4421cb0ef41Sopenharmony_ci} 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ciint nghttp2_http_on_request_headers(nghttp2_stream *stream, 4451cb0ef41Sopenharmony_ci nghttp2_frame *frame) { 4461cb0ef41Sopenharmony_ci if (!(stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) && 4471cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT)) { 4481cb0ef41Sopenharmony_ci if ((stream->http_flags & 4491cb0ef41Sopenharmony_ci (NGHTTP2_HTTP_FLAG__SCHEME | NGHTTP2_HTTP_FLAG__PATH)) || 4501cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) { 4511cb0ef41Sopenharmony_ci return -1; 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci stream->content_length = -1; 4541cb0ef41Sopenharmony_ci } else { 4551cb0ef41Sopenharmony_ci if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) != 4561cb0ef41Sopenharmony_ci NGHTTP2_HTTP_FLAG_REQ_HEADERS || 4571cb0ef41Sopenharmony_ci (stream->http_flags & 4581cb0ef41Sopenharmony_ci (NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) { 4591cb0ef41Sopenharmony_ci return -1; 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci if ((stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) && 4621cb0ef41Sopenharmony_ci ((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) == 0 || 4631cb0ef41Sopenharmony_ci (stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0)) { 4641cb0ef41Sopenharmony_ci return -1; 4651cb0ef41Sopenharmony_ci } 4661cb0ef41Sopenharmony_ci if (!check_path(stream)) { 4671cb0ef41Sopenharmony_ci return -1; 4681cb0ef41Sopenharmony_ci } 4691cb0ef41Sopenharmony_ci } 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { 4721cb0ef41Sopenharmony_ci /* we are going to reuse data fields for upcoming response. Clear 4731cb0ef41Sopenharmony_ci them now, except for method flags. */ 4741cb0ef41Sopenharmony_ci stream->http_flags &= NGHTTP2_HTTP_FLAG_METH_ALL; 4751cb0ef41Sopenharmony_ci stream->content_length = -1; 4761cb0ef41Sopenharmony_ci } 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci return 0; 4791cb0ef41Sopenharmony_ci} 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ciint nghttp2_http_on_response_headers(nghttp2_stream *stream) { 4821cb0ef41Sopenharmony_ci if ((stream->http_flags & NGHTTP2_HTTP_FLAG__STATUS) == 0) { 4831cb0ef41Sopenharmony_ci return -1; 4841cb0ef41Sopenharmony_ci } 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci if (stream->status_code / 100 == 1) { 4871cb0ef41Sopenharmony_ci /* non-final response */ 4881cb0ef41Sopenharmony_ci stream->http_flags = (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_ALL) | 4891cb0ef41Sopenharmony_ci NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE; 4901cb0ef41Sopenharmony_ci stream->content_length = -1; 4911cb0ef41Sopenharmony_ci stream->status_code = -1; 4921cb0ef41Sopenharmony_ci return 0; 4931cb0ef41Sopenharmony_ci } 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci stream->http_flags = 4961cb0ef41Sopenharmony_ci stream->http_flags & (uint32_t)~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE; 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci if (!expect_response_body(stream)) { 4991cb0ef41Sopenharmony_ci stream->content_length = 0; 5001cb0ef41Sopenharmony_ci } else if (stream->http_flags & (NGHTTP2_HTTP_FLAG_METH_CONNECT | 5011cb0ef41Sopenharmony_ci NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND)) { 5021cb0ef41Sopenharmony_ci stream->content_length = -1; 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci return 0; 5061cb0ef41Sopenharmony_ci} 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ciint nghttp2_http_on_trailer_headers(nghttp2_stream *stream, 5091cb0ef41Sopenharmony_ci nghttp2_frame *frame) { 5101cb0ef41Sopenharmony_ci (void)stream; 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { 5131cb0ef41Sopenharmony_ci return -1; 5141cb0ef41Sopenharmony_ci } 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci return 0; 5171cb0ef41Sopenharmony_ci} 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ciint nghttp2_http_on_remote_end_stream(nghttp2_stream *stream) { 5201cb0ef41Sopenharmony_ci if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) { 5211cb0ef41Sopenharmony_ci return -1; 5221cb0ef41Sopenharmony_ci } 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci if (stream->content_length != -1 && 5251cb0ef41Sopenharmony_ci stream->content_length != stream->recv_content_length) { 5261cb0ef41Sopenharmony_ci return -1; 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci return 0; 5301cb0ef41Sopenharmony_ci} 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ciint nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n) { 5331cb0ef41Sopenharmony_ci stream->recv_content_length += (int64_t)n; 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci if ((stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) || 5361cb0ef41Sopenharmony_ci (stream->content_length != -1 && 5371cb0ef41Sopenharmony_ci stream->recv_content_length > stream->content_length)) { 5381cb0ef41Sopenharmony_ci return -1; 5391cb0ef41Sopenharmony_ci } 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci return 0; 5421cb0ef41Sopenharmony_ci} 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_civoid nghttp2_http_record_request_method(nghttp2_stream *stream, 5451cb0ef41Sopenharmony_ci nghttp2_frame *frame) { 5461cb0ef41Sopenharmony_ci const nghttp2_nv *nva; 5471cb0ef41Sopenharmony_ci size_t nvlen; 5481cb0ef41Sopenharmony_ci size_t i; 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci switch (frame->hd.type) { 5511cb0ef41Sopenharmony_ci case NGHTTP2_HEADERS: 5521cb0ef41Sopenharmony_ci nva = frame->headers.nva; 5531cb0ef41Sopenharmony_ci nvlen = frame->headers.nvlen; 5541cb0ef41Sopenharmony_ci break; 5551cb0ef41Sopenharmony_ci case NGHTTP2_PUSH_PROMISE: 5561cb0ef41Sopenharmony_ci nva = frame->push_promise.nva; 5571cb0ef41Sopenharmony_ci nvlen = frame->push_promise.nvlen; 5581cb0ef41Sopenharmony_ci break; 5591cb0ef41Sopenharmony_ci default: 5601cb0ef41Sopenharmony_ci return; 5611cb0ef41Sopenharmony_ci } 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci /* TODO we should do this strictly. */ 5641cb0ef41Sopenharmony_ci for (i = 0; i < nvlen; ++i) { 5651cb0ef41Sopenharmony_ci const nghttp2_nv *nv = &nva[i]; 5661cb0ef41Sopenharmony_ci if (!(nv->namelen == 7 && nv->name[6] == 'd' && 5671cb0ef41Sopenharmony_ci memcmp(":metho", nv->name, nv->namelen - 1) == 0)) { 5681cb0ef41Sopenharmony_ci continue; 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci if (lstreq("CONNECT", nv->value, nv->valuelen)) { 5711cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; 5721cb0ef41Sopenharmony_ci return; 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci if (lstreq("HEAD", nv->value, nv->valuelen)) { 5751cb0ef41Sopenharmony_ci stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; 5761cb0ef41Sopenharmony_ci return; 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci return; 5791cb0ef41Sopenharmony_ci } 5801cb0ef41Sopenharmony_ci} 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ciint nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value, 5831cb0ef41Sopenharmony_ci size_t valuelen) { 5841cb0ef41Sopenharmony_ci nghttp2_extpri pri = *dest; 5851cb0ef41Sopenharmony_ci sf_parser sfp; 5861cb0ef41Sopenharmony_ci sf_vec key; 5871cb0ef41Sopenharmony_ci sf_value val; 5881cb0ef41Sopenharmony_ci int rv; 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci sf_parser_init(&sfp, value, valuelen); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci for (;;) { 5931cb0ef41Sopenharmony_ci rv = sf_parser_dict(&sfp, &key, &val); 5941cb0ef41Sopenharmony_ci if (rv != 0) { 5951cb0ef41Sopenharmony_ci if (rv == SF_ERR_EOF) { 5961cb0ef41Sopenharmony_ci break; 5971cb0ef41Sopenharmony_ci } 5981cb0ef41Sopenharmony_ci 5991cb0ef41Sopenharmony_ci return NGHTTP2_ERR_INVALID_ARGUMENT; 6001cb0ef41Sopenharmony_ci } 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci if (key.len != 1) { 6031cb0ef41Sopenharmony_ci continue; 6041cb0ef41Sopenharmony_ci } 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci switch (key.base[0]) { 6071cb0ef41Sopenharmony_ci case 'i': 6081cb0ef41Sopenharmony_ci if (val.type != SF_TYPE_BOOLEAN) { 6091cb0ef41Sopenharmony_ci return NGHTTP2_ERR_INVALID_ARGUMENT; 6101cb0ef41Sopenharmony_ci } 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci pri.inc = val.boolean; 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci break; 6151cb0ef41Sopenharmony_ci case 'u': 6161cb0ef41Sopenharmony_ci if (val.type != SF_TYPE_INTEGER || 6171cb0ef41Sopenharmony_ci val.integer < NGHTTP2_EXTPRI_URGENCY_HIGH || 6181cb0ef41Sopenharmony_ci NGHTTP2_EXTPRI_URGENCY_LOW < val.integer) { 6191cb0ef41Sopenharmony_ci return NGHTTP2_ERR_INVALID_ARGUMENT; 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci pri.urgency = (uint32_t)val.integer; 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci break; 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci } 6271cb0ef41Sopenharmony_ci 6281cb0ef41Sopenharmony_ci *dest = pri; 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci return 0; 6311cb0ef41Sopenharmony_ci} 632