12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2012 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "http2.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#include "llhttp.h" 282c593315Sopenharmony_ci 292c593315Sopenharmony_ci#include "util.h" 302c593315Sopenharmony_ci 312c593315Sopenharmony_cinamespace nghttp2 { 322c593315Sopenharmony_ci 332c593315Sopenharmony_cinamespace http2 { 342c593315Sopenharmony_ci 352c593315Sopenharmony_ciStringRef get_reason_phrase(unsigned int status_code) { 362c593315Sopenharmony_ci switch (status_code) { 372c593315Sopenharmony_ci case 100: 382c593315Sopenharmony_ci return StringRef::from_lit("Continue"); 392c593315Sopenharmony_ci case 101: 402c593315Sopenharmony_ci return StringRef::from_lit("Switching Protocols"); 412c593315Sopenharmony_ci case 103: 422c593315Sopenharmony_ci return StringRef::from_lit("Early Hints"); 432c593315Sopenharmony_ci case 200: 442c593315Sopenharmony_ci return StringRef::from_lit("OK"); 452c593315Sopenharmony_ci case 201: 462c593315Sopenharmony_ci return StringRef::from_lit("Created"); 472c593315Sopenharmony_ci case 202: 482c593315Sopenharmony_ci return StringRef::from_lit("Accepted"); 492c593315Sopenharmony_ci case 203: 502c593315Sopenharmony_ci return StringRef::from_lit("Non-Authoritative Information"); 512c593315Sopenharmony_ci case 204: 522c593315Sopenharmony_ci return StringRef::from_lit("No Content"); 532c593315Sopenharmony_ci case 205: 542c593315Sopenharmony_ci return StringRef::from_lit("Reset Content"); 552c593315Sopenharmony_ci case 206: 562c593315Sopenharmony_ci return StringRef::from_lit("Partial Content"); 572c593315Sopenharmony_ci case 300: 582c593315Sopenharmony_ci return StringRef::from_lit("Multiple Choices"); 592c593315Sopenharmony_ci case 301: 602c593315Sopenharmony_ci return StringRef::from_lit("Moved Permanently"); 612c593315Sopenharmony_ci case 302: 622c593315Sopenharmony_ci return StringRef::from_lit("Found"); 632c593315Sopenharmony_ci case 303: 642c593315Sopenharmony_ci return StringRef::from_lit("See Other"); 652c593315Sopenharmony_ci case 304: 662c593315Sopenharmony_ci return StringRef::from_lit("Not Modified"); 672c593315Sopenharmony_ci case 305: 682c593315Sopenharmony_ci return StringRef::from_lit("Use Proxy"); 692c593315Sopenharmony_ci // case 306: return StringRef::from_lit("(Unused)"); 702c593315Sopenharmony_ci case 307: 712c593315Sopenharmony_ci return StringRef::from_lit("Temporary Redirect"); 722c593315Sopenharmony_ci case 308: 732c593315Sopenharmony_ci return StringRef::from_lit("Permanent Redirect"); 742c593315Sopenharmony_ci case 400: 752c593315Sopenharmony_ci return StringRef::from_lit("Bad Request"); 762c593315Sopenharmony_ci case 401: 772c593315Sopenharmony_ci return StringRef::from_lit("Unauthorized"); 782c593315Sopenharmony_ci case 402: 792c593315Sopenharmony_ci return StringRef::from_lit("Payment Required"); 802c593315Sopenharmony_ci case 403: 812c593315Sopenharmony_ci return StringRef::from_lit("Forbidden"); 822c593315Sopenharmony_ci case 404: 832c593315Sopenharmony_ci return StringRef::from_lit("Not Found"); 842c593315Sopenharmony_ci case 405: 852c593315Sopenharmony_ci return StringRef::from_lit("Method Not Allowed"); 862c593315Sopenharmony_ci case 406: 872c593315Sopenharmony_ci return StringRef::from_lit("Not Acceptable"); 882c593315Sopenharmony_ci case 407: 892c593315Sopenharmony_ci return StringRef::from_lit("Proxy Authentication Required"); 902c593315Sopenharmony_ci case 408: 912c593315Sopenharmony_ci return StringRef::from_lit("Request Timeout"); 922c593315Sopenharmony_ci case 409: 932c593315Sopenharmony_ci return StringRef::from_lit("Conflict"); 942c593315Sopenharmony_ci case 410: 952c593315Sopenharmony_ci return StringRef::from_lit("Gone"); 962c593315Sopenharmony_ci case 411: 972c593315Sopenharmony_ci return StringRef::from_lit("Length Required"); 982c593315Sopenharmony_ci case 412: 992c593315Sopenharmony_ci return StringRef::from_lit("Precondition Failed"); 1002c593315Sopenharmony_ci case 413: 1012c593315Sopenharmony_ci return StringRef::from_lit("Payload Too Large"); 1022c593315Sopenharmony_ci case 414: 1032c593315Sopenharmony_ci return StringRef::from_lit("URI Too Long"); 1042c593315Sopenharmony_ci case 415: 1052c593315Sopenharmony_ci return StringRef::from_lit("Unsupported Media Type"); 1062c593315Sopenharmony_ci case 416: 1072c593315Sopenharmony_ci return StringRef::from_lit("Requested Range Not Satisfiable"); 1082c593315Sopenharmony_ci case 417: 1092c593315Sopenharmony_ci return StringRef::from_lit("Expectation Failed"); 1102c593315Sopenharmony_ci case 421: 1112c593315Sopenharmony_ci return StringRef::from_lit("Misdirected Request"); 1122c593315Sopenharmony_ci case 425: 1132c593315Sopenharmony_ci // https://tools.ietf.org/html/rfc8470 1142c593315Sopenharmony_ci return StringRef::from_lit("Too Early"); 1152c593315Sopenharmony_ci case 426: 1162c593315Sopenharmony_ci return StringRef::from_lit("Upgrade Required"); 1172c593315Sopenharmony_ci case 428: 1182c593315Sopenharmony_ci return StringRef::from_lit("Precondition Required"); 1192c593315Sopenharmony_ci case 429: 1202c593315Sopenharmony_ci return StringRef::from_lit("Too Many Requests"); 1212c593315Sopenharmony_ci case 431: 1222c593315Sopenharmony_ci return StringRef::from_lit("Request Header Fields Too Large"); 1232c593315Sopenharmony_ci case 451: 1242c593315Sopenharmony_ci return StringRef::from_lit("Unavailable For Legal Reasons"); 1252c593315Sopenharmony_ci case 500: 1262c593315Sopenharmony_ci return StringRef::from_lit("Internal Server Error"); 1272c593315Sopenharmony_ci case 501: 1282c593315Sopenharmony_ci return StringRef::from_lit("Not Implemented"); 1292c593315Sopenharmony_ci case 502: 1302c593315Sopenharmony_ci return StringRef::from_lit("Bad Gateway"); 1312c593315Sopenharmony_ci case 503: 1322c593315Sopenharmony_ci return StringRef::from_lit("Service Unavailable"); 1332c593315Sopenharmony_ci case 504: 1342c593315Sopenharmony_ci return StringRef::from_lit("Gateway Timeout"); 1352c593315Sopenharmony_ci case 505: 1362c593315Sopenharmony_ci return StringRef::from_lit("HTTP Version Not Supported"); 1372c593315Sopenharmony_ci case 511: 1382c593315Sopenharmony_ci return StringRef::from_lit("Network Authentication Required"); 1392c593315Sopenharmony_ci default: 1402c593315Sopenharmony_ci return StringRef{}; 1412c593315Sopenharmony_ci } 1422c593315Sopenharmony_ci} 1432c593315Sopenharmony_ci 1442c593315Sopenharmony_ciStringRef stringify_status(BlockAllocator &balloc, unsigned int status_code) { 1452c593315Sopenharmony_ci switch (status_code) { 1462c593315Sopenharmony_ci case 100: 1472c593315Sopenharmony_ci return StringRef::from_lit("100"); 1482c593315Sopenharmony_ci case 101: 1492c593315Sopenharmony_ci return StringRef::from_lit("101"); 1502c593315Sopenharmony_ci case 103: 1512c593315Sopenharmony_ci return StringRef::from_lit("103"); 1522c593315Sopenharmony_ci case 200: 1532c593315Sopenharmony_ci return StringRef::from_lit("200"); 1542c593315Sopenharmony_ci case 201: 1552c593315Sopenharmony_ci return StringRef::from_lit("201"); 1562c593315Sopenharmony_ci case 202: 1572c593315Sopenharmony_ci return StringRef::from_lit("202"); 1582c593315Sopenharmony_ci case 203: 1592c593315Sopenharmony_ci return StringRef::from_lit("203"); 1602c593315Sopenharmony_ci case 204: 1612c593315Sopenharmony_ci return StringRef::from_lit("204"); 1622c593315Sopenharmony_ci case 205: 1632c593315Sopenharmony_ci return StringRef::from_lit("205"); 1642c593315Sopenharmony_ci case 206: 1652c593315Sopenharmony_ci return StringRef::from_lit("206"); 1662c593315Sopenharmony_ci case 300: 1672c593315Sopenharmony_ci return StringRef::from_lit("300"); 1682c593315Sopenharmony_ci case 301: 1692c593315Sopenharmony_ci return StringRef::from_lit("301"); 1702c593315Sopenharmony_ci case 302: 1712c593315Sopenharmony_ci return StringRef::from_lit("302"); 1722c593315Sopenharmony_ci case 303: 1732c593315Sopenharmony_ci return StringRef::from_lit("303"); 1742c593315Sopenharmony_ci case 304: 1752c593315Sopenharmony_ci return StringRef::from_lit("304"); 1762c593315Sopenharmony_ci case 305: 1772c593315Sopenharmony_ci return StringRef::from_lit("305"); 1782c593315Sopenharmony_ci // case 306: return StringRef::from_lit("306"); 1792c593315Sopenharmony_ci case 307: 1802c593315Sopenharmony_ci return StringRef::from_lit("307"); 1812c593315Sopenharmony_ci case 308: 1822c593315Sopenharmony_ci return StringRef::from_lit("308"); 1832c593315Sopenharmony_ci case 400: 1842c593315Sopenharmony_ci return StringRef::from_lit("400"); 1852c593315Sopenharmony_ci case 401: 1862c593315Sopenharmony_ci return StringRef::from_lit("401"); 1872c593315Sopenharmony_ci case 402: 1882c593315Sopenharmony_ci return StringRef::from_lit("402"); 1892c593315Sopenharmony_ci case 403: 1902c593315Sopenharmony_ci return StringRef::from_lit("403"); 1912c593315Sopenharmony_ci case 404: 1922c593315Sopenharmony_ci return StringRef::from_lit("404"); 1932c593315Sopenharmony_ci case 405: 1942c593315Sopenharmony_ci return StringRef::from_lit("405"); 1952c593315Sopenharmony_ci case 406: 1962c593315Sopenharmony_ci return StringRef::from_lit("406"); 1972c593315Sopenharmony_ci case 407: 1982c593315Sopenharmony_ci return StringRef::from_lit("407"); 1992c593315Sopenharmony_ci case 408: 2002c593315Sopenharmony_ci return StringRef::from_lit("408"); 2012c593315Sopenharmony_ci case 409: 2022c593315Sopenharmony_ci return StringRef::from_lit("409"); 2032c593315Sopenharmony_ci case 410: 2042c593315Sopenharmony_ci return StringRef::from_lit("410"); 2052c593315Sopenharmony_ci case 411: 2062c593315Sopenharmony_ci return StringRef::from_lit("411"); 2072c593315Sopenharmony_ci case 412: 2082c593315Sopenharmony_ci return StringRef::from_lit("412"); 2092c593315Sopenharmony_ci case 413: 2102c593315Sopenharmony_ci return StringRef::from_lit("413"); 2112c593315Sopenharmony_ci case 414: 2122c593315Sopenharmony_ci return StringRef::from_lit("414"); 2132c593315Sopenharmony_ci case 415: 2142c593315Sopenharmony_ci return StringRef::from_lit("415"); 2152c593315Sopenharmony_ci case 416: 2162c593315Sopenharmony_ci return StringRef::from_lit("416"); 2172c593315Sopenharmony_ci case 417: 2182c593315Sopenharmony_ci return StringRef::from_lit("417"); 2192c593315Sopenharmony_ci case 421: 2202c593315Sopenharmony_ci return StringRef::from_lit("421"); 2212c593315Sopenharmony_ci case 426: 2222c593315Sopenharmony_ci return StringRef::from_lit("426"); 2232c593315Sopenharmony_ci case 428: 2242c593315Sopenharmony_ci return StringRef::from_lit("428"); 2252c593315Sopenharmony_ci case 429: 2262c593315Sopenharmony_ci return StringRef::from_lit("429"); 2272c593315Sopenharmony_ci case 431: 2282c593315Sopenharmony_ci return StringRef::from_lit("431"); 2292c593315Sopenharmony_ci case 451: 2302c593315Sopenharmony_ci return StringRef::from_lit("451"); 2312c593315Sopenharmony_ci case 500: 2322c593315Sopenharmony_ci return StringRef::from_lit("500"); 2332c593315Sopenharmony_ci case 501: 2342c593315Sopenharmony_ci return StringRef::from_lit("501"); 2352c593315Sopenharmony_ci case 502: 2362c593315Sopenharmony_ci return StringRef::from_lit("502"); 2372c593315Sopenharmony_ci case 503: 2382c593315Sopenharmony_ci return StringRef::from_lit("503"); 2392c593315Sopenharmony_ci case 504: 2402c593315Sopenharmony_ci return StringRef::from_lit("504"); 2412c593315Sopenharmony_ci case 505: 2422c593315Sopenharmony_ci return StringRef::from_lit("505"); 2432c593315Sopenharmony_ci case 511: 2442c593315Sopenharmony_ci return StringRef::from_lit("511"); 2452c593315Sopenharmony_ci default: 2462c593315Sopenharmony_ci return util::make_string_ref_uint(balloc, status_code); 2472c593315Sopenharmony_ci } 2482c593315Sopenharmony_ci} 2492c593315Sopenharmony_ci 2502c593315Sopenharmony_civoid capitalize(DefaultMemchunks *buf, const StringRef &s) { 2512c593315Sopenharmony_ci buf->append(util::upcase(s[0])); 2522c593315Sopenharmony_ci for (size_t i = 1; i < s.size(); ++i) { 2532c593315Sopenharmony_ci if (s[i - 1] == '-') { 2542c593315Sopenharmony_ci buf->append(util::upcase(s[i])); 2552c593315Sopenharmony_ci } else { 2562c593315Sopenharmony_ci buf->append(s[i]); 2572c593315Sopenharmony_ci } 2582c593315Sopenharmony_ci } 2592c593315Sopenharmony_ci} 2602c593315Sopenharmony_ci 2612c593315Sopenharmony_cibool lws(const char *value) { 2622c593315Sopenharmony_ci for (; *value; ++value) { 2632c593315Sopenharmony_ci switch (*value) { 2642c593315Sopenharmony_ci case '\t': 2652c593315Sopenharmony_ci case ' ': 2662c593315Sopenharmony_ci continue; 2672c593315Sopenharmony_ci default: 2682c593315Sopenharmony_ci return false; 2692c593315Sopenharmony_ci } 2702c593315Sopenharmony_ci } 2712c593315Sopenharmony_ci return true; 2722c593315Sopenharmony_ci} 2732c593315Sopenharmony_ci 2742c593315Sopenharmony_civoid copy_url_component(std::string &dest, const http_parser_url *u, int field, 2752c593315Sopenharmony_ci const char *url) { 2762c593315Sopenharmony_ci if (u->field_set & (1 << field)) { 2772c593315Sopenharmony_ci dest.assign(url + u->field_data[field].off, u->field_data[field].len); 2782c593315Sopenharmony_ci } 2792c593315Sopenharmony_ci} 2802c593315Sopenharmony_ci 2812c593315Sopenharmony_ciHeaders::value_type to_header(const uint8_t *name, size_t namelen, 2822c593315Sopenharmony_ci const uint8_t *value, size_t valuelen, 2832c593315Sopenharmony_ci bool no_index, int32_t token) { 2842c593315Sopenharmony_ci return Header(std::string(reinterpret_cast<const char *>(name), namelen), 2852c593315Sopenharmony_ci std::string(reinterpret_cast<const char *>(value), valuelen), 2862c593315Sopenharmony_ci no_index, token); 2872c593315Sopenharmony_ci} 2882c593315Sopenharmony_ci 2892c593315Sopenharmony_civoid add_header(Headers &nva, const uint8_t *name, size_t namelen, 2902c593315Sopenharmony_ci const uint8_t *value, size_t valuelen, bool no_index, 2912c593315Sopenharmony_ci int32_t token) { 2922c593315Sopenharmony_ci if (valuelen > 0) { 2932c593315Sopenharmony_ci size_t i, j; 2942c593315Sopenharmony_ci for (i = 0; i < valuelen && (value[i] == ' ' || value[i] == '\t'); ++i) 2952c593315Sopenharmony_ci ; 2962c593315Sopenharmony_ci for (j = valuelen - 1; j > i && (value[j] == ' ' || value[j] == '\t'); --j) 2972c593315Sopenharmony_ci ; 2982c593315Sopenharmony_ci value += i; 2992c593315Sopenharmony_ci valuelen -= i + (valuelen - j - 1); 3002c593315Sopenharmony_ci } 3012c593315Sopenharmony_ci nva.push_back(to_header(name, namelen, value, valuelen, no_index, token)); 3022c593315Sopenharmony_ci} 3032c593315Sopenharmony_ci 3042c593315Sopenharmony_ciconst Headers::value_type *get_header(const Headers &nva, const char *name) { 3052c593315Sopenharmony_ci const Headers::value_type *res = nullptr; 3062c593315Sopenharmony_ci for (auto &nv : nva) { 3072c593315Sopenharmony_ci if (nv.name == name) { 3082c593315Sopenharmony_ci res = &nv; 3092c593315Sopenharmony_ci } 3102c593315Sopenharmony_ci } 3112c593315Sopenharmony_ci return res; 3122c593315Sopenharmony_ci} 3132c593315Sopenharmony_ci 3142c593315Sopenharmony_cibool non_empty_value(const HeaderRefs::value_type *nv) { 3152c593315Sopenharmony_ci return nv && !nv->value.empty(); 3162c593315Sopenharmony_ci} 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_cinamespace { 3192c593315Sopenharmony_cinghttp2_nv make_nv_internal(const std::string &name, const std::string &value, 3202c593315Sopenharmony_ci bool no_index, uint8_t nv_flags) { 3212c593315Sopenharmony_ci uint8_t flags; 3222c593315Sopenharmony_ci 3232c593315Sopenharmony_ci flags = 3242c593315Sopenharmony_ci nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE); 3252c593315Sopenharmony_ci 3262c593315Sopenharmony_ci return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), 3272c593315Sopenharmony_ci value.size(), flags}; 3282c593315Sopenharmony_ci} 3292c593315Sopenharmony_ci} // namespace 3302c593315Sopenharmony_ci 3312c593315Sopenharmony_cinamespace { 3322c593315Sopenharmony_cinghttp2_nv make_nv_internal(const StringRef &name, const StringRef &value, 3332c593315Sopenharmony_ci bool no_index, uint8_t nv_flags) { 3342c593315Sopenharmony_ci uint8_t flags; 3352c593315Sopenharmony_ci 3362c593315Sopenharmony_ci flags = 3372c593315Sopenharmony_ci nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE); 3382c593315Sopenharmony_ci 3392c593315Sopenharmony_ci return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), 3402c593315Sopenharmony_ci value.size(), flags}; 3412c593315Sopenharmony_ci} 3422c593315Sopenharmony_ci} // namespace 3432c593315Sopenharmony_ci 3442c593315Sopenharmony_cinghttp2_nv make_nv(const std::string &name, const std::string &value, 3452c593315Sopenharmony_ci bool no_index) { 3462c593315Sopenharmony_ci return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE); 3472c593315Sopenharmony_ci} 3482c593315Sopenharmony_ci 3492c593315Sopenharmony_cinghttp2_nv make_nv(const StringRef &name, const StringRef &value, 3502c593315Sopenharmony_ci bool no_index) { 3512c593315Sopenharmony_ci return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE); 3522c593315Sopenharmony_ci} 3532c593315Sopenharmony_ci 3542c593315Sopenharmony_cinghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value, 3552c593315Sopenharmony_ci bool no_index) { 3562c593315Sopenharmony_ci return make_nv_internal(name, value, no_index, 3572c593315Sopenharmony_ci NGHTTP2_NV_FLAG_NO_COPY_NAME | 3582c593315Sopenharmony_ci NGHTTP2_NV_FLAG_NO_COPY_VALUE); 3592c593315Sopenharmony_ci} 3602c593315Sopenharmony_ci 3612c593315Sopenharmony_cinghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value, 3622c593315Sopenharmony_ci bool no_index) { 3632c593315Sopenharmony_ci return make_nv_internal(name, value, no_index, 3642c593315Sopenharmony_ci NGHTTP2_NV_FLAG_NO_COPY_NAME | 3652c593315Sopenharmony_ci NGHTTP2_NV_FLAG_NO_COPY_VALUE); 3662c593315Sopenharmony_ci} 3672c593315Sopenharmony_ci 3682c593315Sopenharmony_cinamespace { 3692c593315Sopenharmony_civoid copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva, 3702c593315Sopenharmony_ci const HeaderRefs &headers, uint8_t nv_flags, 3712c593315Sopenharmony_ci uint32_t flags) { 3722c593315Sopenharmony_ci auto it_forwarded = std::end(headers); 3732c593315Sopenharmony_ci auto it_xff = std::end(headers); 3742c593315Sopenharmony_ci auto it_xfp = std::end(headers); 3752c593315Sopenharmony_ci auto it_via = std::end(headers); 3762c593315Sopenharmony_ci 3772c593315Sopenharmony_ci for (auto it = std::begin(headers); it != std::end(headers); ++it) { 3782c593315Sopenharmony_ci auto kv = &(*it); 3792c593315Sopenharmony_ci if (kv->name.empty() || kv->name[0] == ':') { 3802c593315Sopenharmony_ci continue; 3812c593315Sopenharmony_ci } 3822c593315Sopenharmony_ci switch (kv->token) { 3832c593315Sopenharmony_ci case HD_COOKIE: 3842c593315Sopenharmony_ci case HD_CONNECTION: 3852c593315Sopenharmony_ci case HD_HOST: 3862c593315Sopenharmony_ci case HD_HTTP2_SETTINGS: 3872c593315Sopenharmony_ci case HD_KEEP_ALIVE: 3882c593315Sopenharmony_ci case HD_PROXY_CONNECTION: 3892c593315Sopenharmony_ci case HD_SERVER: 3902c593315Sopenharmony_ci case HD_TE: 3912c593315Sopenharmony_ci case HD_TRANSFER_ENCODING: 3922c593315Sopenharmony_ci case HD_UPGRADE: 3932c593315Sopenharmony_ci continue; 3942c593315Sopenharmony_ci case HD_EARLY_DATA: 3952c593315Sopenharmony_ci if (flags & HDOP_STRIP_EARLY_DATA) { 3962c593315Sopenharmony_ci continue; 3972c593315Sopenharmony_ci } 3982c593315Sopenharmony_ci break; 3992c593315Sopenharmony_ci case HD_SEC_WEBSOCKET_ACCEPT: 4002c593315Sopenharmony_ci if (flags & HDOP_STRIP_SEC_WEBSOCKET_ACCEPT) { 4012c593315Sopenharmony_ci continue; 4022c593315Sopenharmony_ci } 4032c593315Sopenharmony_ci break; 4042c593315Sopenharmony_ci case HD_SEC_WEBSOCKET_KEY: 4052c593315Sopenharmony_ci if (flags & HDOP_STRIP_SEC_WEBSOCKET_KEY) { 4062c593315Sopenharmony_ci continue; 4072c593315Sopenharmony_ci } 4082c593315Sopenharmony_ci break; 4092c593315Sopenharmony_ci case HD_FORWARDED: 4102c593315Sopenharmony_ci if (flags & HDOP_STRIP_FORWARDED) { 4112c593315Sopenharmony_ci continue; 4122c593315Sopenharmony_ci } 4132c593315Sopenharmony_ci 4142c593315Sopenharmony_ci if (it_forwarded == std::end(headers)) { 4152c593315Sopenharmony_ci it_forwarded = it; 4162c593315Sopenharmony_ci continue; 4172c593315Sopenharmony_ci } 4182c593315Sopenharmony_ci 4192c593315Sopenharmony_ci kv = &(*it_forwarded); 4202c593315Sopenharmony_ci it_forwarded = it; 4212c593315Sopenharmony_ci break; 4222c593315Sopenharmony_ci case HD_X_FORWARDED_FOR: 4232c593315Sopenharmony_ci if (flags & HDOP_STRIP_X_FORWARDED_FOR) { 4242c593315Sopenharmony_ci continue; 4252c593315Sopenharmony_ci } 4262c593315Sopenharmony_ci 4272c593315Sopenharmony_ci if (it_xff == std::end(headers)) { 4282c593315Sopenharmony_ci it_xff = it; 4292c593315Sopenharmony_ci continue; 4302c593315Sopenharmony_ci } 4312c593315Sopenharmony_ci 4322c593315Sopenharmony_ci kv = &(*it_xff); 4332c593315Sopenharmony_ci it_xff = it; 4342c593315Sopenharmony_ci break; 4352c593315Sopenharmony_ci case HD_X_FORWARDED_PROTO: 4362c593315Sopenharmony_ci if (flags & HDOP_STRIP_X_FORWARDED_PROTO) { 4372c593315Sopenharmony_ci continue; 4382c593315Sopenharmony_ci } 4392c593315Sopenharmony_ci 4402c593315Sopenharmony_ci if (it_xfp == std::end(headers)) { 4412c593315Sopenharmony_ci it_xfp = it; 4422c593315Sopenharmony_ci continue; 4432c593315Sopenharmony_ci } 4442c593315Sopenharmony_ci 4452c593315Sopenharmony_ci kv = &(*it_xfp); 4462c593315Sopenharmony_ci it_xfp = it; 4472c593315Sopenharmony_ci break; 4482c593315Sopenharmony_ci case HD_VIA: 4492c593315Sopenharmony_ci if (flags & HDOP_STRIP_VIA) { 4502c593315Sopenharmony_ci continue; 4512c593315Sopenharmony_ci } 4522c593315Sopenharmony_ci 4532c593315Sopenharmony_ci if (it_via == std::end(headers)) { 4542c593315Sopenharmony_ci it_via = it; 4552c593315Sopenharmony_ci continue; 4562c593315Sopenharmony_ci } 4572c593315Sopenharmony_ci 4582c593315Sopenharmony_ci kv = &(*it_via); 4592c593315Sopenharmony_ci it_via = it; 4602c593315Sopenharmony_ci break; 4612c593315Sopenharmony_ci } 4622c593315Sopenharmony_ci nva.push_back( 4632c593315Sopenharmony_ci make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags)); 4642c593315Sopenharmony_ci } 4652c593315Sopenharmony_ci} 4662c593315Sopenharmony_ci} // namespace 4672c593315Sopenharmony_ci 4682c593315Sopenharmony_civoid copy_headers_to_nva(std::vector<nghttp2_nv> &nva, 4692c593315Sopenharmony_ci const HeaderRefs &headers, uint32_t flags) { 4702c593315Sopenharmony_ci copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NONE, flags); 4712c593315Sopenharmony_ci} 4722c593315Sopenharmony_ci 4732c593315Sopenharmony_civoid copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva, 4742c593315Sopenharmony_ci const HeaderRefs &headers, uint32_t flags) { 4752c593315Sopenharmony_ci copy_headers_to_nva_internal( 4762c593315Sopenharmony_ci nva, headers, 4772c593315Sopenharmony_ci NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE, flags); 4782c593315Sopenharmony_ci} 4792c593315Sopenharmony_ci 4802c593315Sopenharmony_civoid build_http1_headers_from_headers(DefaultMemchunks *buf, 4812c593315Sopenharmony_ci const HeaderRefs &headers, 4822c593315Sopenharmony_ci uint32_t flags) { 4832c593315Sopenharmony_ci auto it_forwarded = std::end(headers); 4842c593315Sopenharmony_ci auto it_xff = std::end(headers); 4852c593315Sopenharmony_ci auto it_xfp = std::end(headers); 4862c593315Sopenharmony_ci auto it_via = std::end(headers); 4872c593315Sopenharmony_ci 4882c593315Sopenharmony_ci for (auto it = std::begin(headers); it != std::end(headers); ++it) { 4892c593315Sopenharmony_ci auto kv = &(*it); 4902c593315Sopenharmony_ci if (kv->name.empty() || kv->name[0] == ':') { 4912c593315Sopenharmony_ci continue; 4922c593315Sopenharmony_ci } 4932c593315Sopenharmony_ci switch (kv->token) { 4942c593315Sopenharmony_ci case HD_CONNECTION: 4952c593315Sopenharmony_ci case HD_COOKIE: 4962c593315Sopenharmony_ci case HD_HOST: 4972c593315Sopenharmony_ci case HD_HTTP2_SETTINGS: 4982c593315Sopenharmony_ci case HD_KEEP_ALIVE: 4992c593315Sopenharmony_ci case HD_PROXY_CONNECTION: 5002c593315Sopenharmony_ci case HD_SERVER: 5012c593315Sopenharmony_ci case HD_UPGRADE: 5022c593315Sopenharmony_ci continue; 5032c593315Sopenharmony_ci case HD_EARLY_DATA: 5042c593315Sopenharmony_ci if (flags & HDOP_STRIP_EARLY_DATA) { 5052c593315Sopenharmony_ci continue; 5062c593315Sopenharmony_ci } 5072c593315Sopenharmony_ci break; 5082c593315Sopenharmony_ci case HD_TRANSFER_ENCODING: 5092c593315Sopenharmony_ci if (flags & HDOP_STRIP_TRANSFER_ENCODING) { 5102c593315Sopenharmony_ci continue; 5112c593315Sopenharmony_ci } 5122c593315Sopenharmony_ci break; 5132c593315Sopenharmony_ci case HD_FORWARDED: 5142c593315Sopenharmony_ci if (flags & HDOP_STRIP_FORWARDED) { 5152c593315Sopenharmony_ci continue; 5162c593315Sopenharmony_ci } 5172c593315Sopenharmony_ci 5182c593315Sopenharmony_ci if (it_forwarded == std::end(headers)) { 5192c593315Sopenharmony_ci it_forwarded = it; 5202c593315Sopenharmony_ci continue; 5212c593315Sopenharmony_ci } 5222c593315Sopenharmony_ci 5232c593315Sopenharmony_ci kv = &(*it_forwarded); 5242c593315Sopenharmony_ci it_forwarded = it; 5252c593315Sopenharmony_ci break; 5262c593315Sopenharmony_ci case HD_X_FORWARDED_FOR: 5272c593315Sopenharmony_ci if (flags & HDOP_STRIP_X_FORWARDED_FOR) { 5282c593315Sopenharmony_ci continue; 5292c593315Sopenharmony_ci } 5302c593315Sopenharmony_ci 5312c593315Sopenharmony_ci if (it_xff == std::end(headers)) { 5322c593315Sopenharmony_ci it_xff = it; 5332c593315Sopenharmony_ci continue; 5342c593315Sopenharmony_ci } 5352c593315Sopenharmony_ci 5362c593315Sopenharmony_ci kv = &(*it_xff); 5372c593315Sopenharmony_ci it_xff = it; 5382c593315Sopenharmony_ci break; 5392c593315Sopenharmony_ci case HD_X_FORWARDED_PROTO: 5402c593315Sopenharmony_ci if (flags & HDOP_STRIP_X_FORWARDED_PROTO) { 5412c593315Sopenharmony_ci continue; 5422c593315Sopenharmony_ci } 5432c593315Sopenharmony_ci 5442c593315Sopenharmony_ci if (it_xfp == std::end(headers)) { 5452c593315Sopenharmony_ci it_xfp = it; 5462c593315Sopenharmony_ci continue; 5472c593315Sopenharmony_ci } 5482c593315Sopenharmony_ci 5492c593315Sopenharmony_ci kv = &(*it_xfp); 5502c593315Sopenharmony_ci it_xfp = it; 5512c593315Sopenharmony_ci break; 5522c593315Sopenharmony_ci case HD_VIA: 5532c593315Sopenharmony_ci if (flags & HDOP_STRIP_VIA) { 5542c593315Sopenharmony_ci continue; 5552c593315Sopenharmony_ci } 5562c593315Sopenharmony_ci 5572c593315Sopenharmony_ci if (it_via == std::end(headers)) { 5582c593315Sopenharmony_ci it_via = it; 5592c593315Sopenharmony_ci continue; 5602c593315Sopenharmony_ci } 5612c593315Sopenharmony_ci 5622c593315Sopenharmony_ci kv = &(*it_via); 5632c593315Sopenharmony_ci it_via = it; 5642c593315Sopenharmony_ci break; 5652c593315Sopenharmony_ci } 5662c593315Sopenharmony_ci capitalize(buf, kv->name); 5672c593315Sopenharmony_ci buf->append(": "); 5682c593315Sopenharmony_ci buf->append(kv->value); 5692c593315Sopenharmony_ci buf->append("\r\n"); 5702c593315Sopenharmony_ci } 5712c593315Sopenharmony_ci} 5722c593315Sopenharmony_ci 5732c593315Sopenharmony_ciint32_t determine_window_update_transmission(nghttp2_session *session, 5742c593315Sopenharmony_ci int32_t stream_id) { 5752c593315Sopenharmony_ci int32_t recv_length, window_size; 5762c593315Sopenharmony_ci if (stream_id == 0) { 5772c593315Sopenharmony_ci recv_length = nghttp2_session_get_effective_recv_data_length(session); 5782c593315Sopenharmony_ci window_size = nghttp2_session_get_effective_local_window_size(session); 5792c593315Sopenharmony_ci } else { 5802c593315Sopenharmony_ci recv_length = nghttp2_session_get_stream_effective_recv_data_length( 5812c593315Sopenharmony_ci session, stream_id); 5822c593315Sopenharmony_ci window_size = nghttp2_session_get_stream_effective_local_window_size( 5832c593315Sopenharmony_ci session, stream_id); 5842c593315Sopenharmony_ci } 5852c593315Sopenharmony_ci if (recv_length != -1 && window_size != -1) { 5862c593315Sopenharmony_ci if (recv_length >= window_size / 2) { 5872c593315Sopenharmony_ci return recv_length; 5882c593315Sopenharmony_ci } 5892c593315Sopenharmony_ci } 5902c593315Sopenharmony_ci return -1; 5912c593315Sopenharmony_ci} 5922c593315Sopenharmony_ci 5932c593315Sopenharmony_civoid dump_nv(FILE *out, const char **nv) { 5942c593315Sopenharmony_ci for (size_t i = 0; nv[i]; i += 2) { 5952c593315Sopenharmony_ci fprintf(out, "%s: %s\n", nv[i], nv[i + 1]); 5962c593315Sopenharmony_ci } 5972c593315Sopenharmony_ci fputc('\n', out); 5982c593315Sopenharmony_ci fflush(out); 5992c593315Sopenharmony_ci} 6002c593315Sopenharmony_ci 6012c593315Sopenharmony_civoid dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen) { 6022c593315Sopenharmony_ci auto end = nva + nvlen; 6032c593315Sopenharmony_ci for (; nva != end; ++nva) { 6042c593315Sopenharmony_ci fprintf(out, "%s: %s\n", nva->name, nva->value); 6052c593315Sopenharmony_ci } 6062c593315Sopenharmony_ci fputc('\n', out); 6072c593315Sopenharmony_ci fflush(out); 6082c593315Sopenharmony_ci} 6092c593315Sopenharmony_ci 6102c593315Sopenharmony_civoid dump_nv(FILE *out, const Headers &nva) { 6112c593315Sopenharmony_ci for (auto &nv : nva) { 6122c593315Sopenharmony_ci fprintf(out, "%s: %s\n", nv.name.c_str(), nv.value.c_str()); 6132c593315Sopenharmony_ci } 6142c593315Sopenharmony_ci fputc('\n', out); 6152c593315Sopenharmony_ci fflush(out); 6162c593315Sopenharmony_ci} 6172c593315Sopenharmony_ci 6182c593315Sopenharmony_civoid dump_nv(FILE *out, const HeaderRefs &nva) { 6192c593315Sopenharmony_ci for (auto &nv : nva) { 6202c593315Sopenharmony_ci fprintf(out, "%s: %s\n", nv.name.c_str(), nv.value.c_str()); 6212c593315Sopenharmony_ci } 6222c593315Sopenharmony_ci fputc('\n', out); 6232c593315Sopenharmony_ci fflush(out); 6242c593315Sopenharmony_ci} 6252c593315Sopenharmony_ci 6262c593315Sopenharmony_civoid erase_header(HeaderRef *hd) { 6272c593315Sopenharmony_ci hd->name = StringRef{}; 6282c593315Sopenharmony_ci hd->token = -1; 6292c593315Sopenharmony_ci} 6302c593315Sopenharmony_ci 6312c593315Sopenharmony_ciStringRef rewrite_location_uri(BlockAllocator &balloc, const StringRef &uri, 6322c593315Sopenharmony_ci const http_parser_url &u, 6332c593315Sopenharmony_ci const StringRef &match_host, 6342c593315Sopenharmony_ci const StringRef &request_authority, 6352c593315Sopenharmony_ci const StringRef &upstream_scheme) { 6362c593315Sopenharmony_ci // We just rewrite scheme and authority. 6372c593315Sopenharmony_ci if ((u.field_set & (1 << UF_HOST)) == 0) { 6382c593315Sopenharmony_ci return StringRef{}; 6392c593315Sopenharmony_ci } 6402c593315Sopenharmony_ci auto field = &u.field_data[UF_HOST]; 6412c593315Sopenharmony_ci if (!util::starts_with(std::begin(match_host), std::end(match_host), 6422c593315Sopenharmony_ci &uri[field->off], &uri[field->off] + field->len) || 6432c593315Sopenharmony_ci (match_host.size() != field->len && match_host[field->len] != ':')) { 6442c593315Sopenharmony_ci return StringRef{}; 6452c593315Sopenharmony_ci } 6462c593315Sopenharmony_ci 6472c593315Sopenharmony_ci auto len = 0; 6482c593315Sopenharmony_ci if (!request_authority.empty()) { 6492c593315Sopenharmony_ci len += upstream_scheme.size() + str_size("://") + request_authority.size(); 6502c593315Sopenharmony_ci } 6512c593315Sopenharmony_ci 6522c593315Sopenharmony_ci if (u.field_set & (1 << UF_PATH)) { 6532c593315Sopenharmony_ci field = &u.field_data[UF_PATH]; 6542c593315Sopenharmony_ci len += field->len; 6552c593315Sopenharmony_ci } 6562c593315Sopenharmony_ci 6572c593315Sopenharmony_ci if (u.field_set & (1 << UF_QUERY)) { 6582c593315Sopenharmony_ci field = &u.field_data[UF_QUERY]; 6592c593315Sopenharmony_ci len += 1 + field->len; 6602c593315Sopenharmony_ci } 6612c593315Sopenharmony_ci 6622c593315Sopenharmony_ci if (u.field_set & (1 << UF_FRAGMENT)) { 6632c593315Sopenharmony_ci field = &u.field_data[UF_FRAGMENT]; 6642c593315Sopenharmony_ci len += 1 + field->len; 6652c593315Sopenharmony_ci } 6662c593315Sopenharmony_ci 6672c593315Sopenharmony_ci auto iov = make_byte_ref(balloc, len + 1); 6682c593315Sopenharmony_ci auto p = iov.base; 6692c593315Sopenharmony_ci 6702c593315Sopenharmony_ci if (!request_authority.empty()) { 6712c593315Sopenharmony_ci p = std::copy(std::begin(upstream_scheme), std::end(upstream_scheme), p); 6722c593315Sopenharmony_ci p = util::copy_lit(p, "://"); 6732c593315Sopenharmony_ci p = std::copy(std::begin(request_authority), std::end(request_authority), 6742c593315Sopenharmony_ci p); 6752c593315Sopenharmony_ci } 6762c593315Sopenharmony_ci if (u.field_set & (1 << UF_PATH)) { 6772c593315Sopenharmony_ci field = &u.field_data[UF_PATH]; 6782c593315Sopenharmony_ci p = std::copy_n(&uri[field->off], field->len, p); 6792c593315Sopenharmony_ci } 6802c593315Sopenharmony_ci if (u.field_set & (1 << UF_QUERY)) { 6812c593315Sopenharmony_ci field = &u.field_data[UF_QUERY]; 6822c593315Sopenharmony_ci *p++ = '?'; 6832c593315Sopenharmony_ci p = std::copy_n(&uri[field->off], field->len, p); 6842c593315Sopenharmony_ci } 6852c593315Sopenharmony_ci if (u.field_set & (1 << UF_FRAGMENT)) { 6862c593315Sopenharmony_ci field = &u.field_data[UF_FRAGMENT]; 6872c593315Sopenharmony_ci *p++ = '#'; 6882c593315Sopenharmony_ci p = std::copy_n(&uri[field->off], field->len, p); 6892c593315Sopenharmony_ci } 6902c593315Sopenharmony_ci 6912c593315Sopenharmony_ci *p = '\0'; 6922c593315Sopenharmony_ci 6932c593315Sopenharmony_ci return StringRef{iov.base, p}; 6942c593315Sopenharmony_ci} 6952c593315Sopenharmony_ci 6962c593315Sopenharmony_ciint parse_http_status_code(const StringRef &src) { 6972c593315Sopenharmony_ci if (src.size() != 3) { 6982c593315Sopenharmony_ci return -1; 6992c593315Sopenharmony_ci } 7002c593315Sopenharmony_ci 7012c593315Sopenharmony_ci int status = 0; 7022c593315Sopenharmony_ci for (auto c : src) { 7032c593315Sopenharmony_ci if (!isdigit(c)) { 7042c593315Sopenharmony_ci return -1; 7052c593315Sopenharmony_ci } 7062c593315Sopenharmony_ci status *= 10; 7072c593315Sopenharmony_ci status += c - '0'; 7082c593315Sopenharmony_ci } 7092c593315Sopenharmony_ci 7102c593315Sopenharmony_ci if (status < 100) { 7112c593315Sopenharmony_ci return -1; 7122c593315Sopenharmony_ci } 7132c593315Sopenharmony_ci 7142c593315Sopenharmony_ci return status; 7152c593315Sopenharmony_ci} 7162c593315Sopenharmony_ci 7172c593315Sopenharmony_ciint lookup_token(const StringRef &name) { 7182c593315Sopenharmony_ci return lookup_token(name.byte(), name.size()); 7192c593315Sopenharmony_ci} 7202c593315Sopenharmony_ci 7212c593315Sopenharmony_ci// This function was generated by genheaderfunc.py. Inspired by h2o 7222c593315Sopenharmony_ci// header lookup. https://github.com/h2o/h2o 7232c593315Sopenharmony_ciint lookup_token(const uint8_t *name, size_t namelen) { 7242c593315Sopenharmony_ci switch (namelen) { 7252c593315Sopenharmony_ci case 2: 7262c593315Sopenharmony_ci switch (name[1]) { 7272c593315Sopenharmony_ci case 'e': 7282c593315Sopenharmony_ci if (util::streq_l("t", name, 1)) { 7292c593315Sopenharmony_ci return HD_TE; 7302c593315Sopenharmony_ci } 7312c593315Sopenharmony_ci break; 7322c593315Sopenharmony_ci } 7332c593315Sopenharmony_ci break; 7342c593315Sopenharmony_ci case 3: 7352c593315Sopenharmony_ci switch (name[2]) { 7362c593315Sopenharmony_ci case 'a': 7372c593315Sopenharmony_ci if (util::streq_l("vi", name, 2)) { 7382c593315Sopenharmony_ci return HD_VIA; 7392c593315Sopenharmony_ci } 7402c593315Sopenharmony_ci break; 7412c593315Sopenharmony_ci } 7422c593315Sopenharmony_ci break; 7432c593315Sopenharmony_ci case 4: 7442c593315Sopenharmony_ci switch (name[3]) { 7452c593315Sopenharmony_ci case 'e': 7462c593315Sopenharmony_ci if (util::streq_l("dat", name, 3)) { 7472c593315Sopenharmony_ci return HD_DATE; 7482c593315Sopenharmony_ci } 7492c593315Sopenharmony_ci break; 7502c593315Sopenharmony_ci case 'k': 7512c593315Sopenharmony_ci if (util::streq_l("lin", name, 3)) { 7522c593315Sopenharmony_ci return HD_LINK; 7532c593315Sopenharmony_ci } 7542c593315Sopenharmony_ci break; 7552c593315Sopenharmony_ci case 't': 7562c593315Sopenharmony_ci if (util::streq_l("hos", name, 3)) { 7572c593315Sopenharmony_ci return HD_HOST; 7582c593315Sopenharmony_ci } 7592c593315Sopenharmony_ci break; 7602c593315Sopenharmony_ci } 7612c593315Sopenharmony_ci break; 7622c593315Sopenharmony_ci case 5: 7632c593315Sopenharmony_ci switch (name[4]) { 7642c593315Sopenharmony_ci case 'h': 7652c593315Sopenharmony_ci if (util::streq_l(":pat", name, 4)) { 7662c593315Sopenharmony_ci return HD__PATH; 7672c593315Sopenharmony_ci } 7682c593315Sopenharmony_ci break; 7692c593315Sopenharmony_ci case 't': 7702c593315Sopenharmony_ci if (util::streq_l(":hos", name, 4)) { 7712c593315Sopenharmony_ci return HD__HOST; 7722c593315Sopenharmony_ci } 7732c593315Sopenharmony_ci break; 7742c593315Sopenharmony_ci } 7752c593315Sopenharmony_ci break; 7762c593315Sopenharmony_ci case 6: 7772c593315Sopenharmony_ci switch (name[5]) { 7782c593315Sopenharmony_ci case 'e': 7792c593315Sopenharmony_ci if (util::streq_l("cooki", name, 5)) { 7802c593315Sopenharmony_ci return HD_COOKIE; 7812c593315Sopenharmony_ci } 7822c593315Sopenharmony_ci break; 7832c593315Sopenharmony_ci case 'r': 7842c593315Sopenharmony_ci if (util::streq_l("serve", name, 5)) { 7852c593315Sopenharmony_ci return HD_SERVER; 7862c593315Sopenharmony_ci } 7872c593315Sopenharmony_ci break; 7882c593315Sopenharmony_ci case 't': 7892c593315Sopenharmony_ci if (util::streq_l("expec", name, 5)) { 7902c593315Sopenharmony_ci return HD_EXPECT; 7912c593315Sopenharmony_ci } 7922c593315Sopenharmony_ci break; 7932c593315Sopenharmony_ci } 7942c593315Sopenharmony_ci break; 7952c593315Sopenharmony_ci case 7: 7962c593315Sopenharmony_ci switch (name[6]) { 7972c593315Sopenharmony_ci case 'c': 7982c593315Sopenharmony_ci if (util::streq_l("alt-sv", name, 6)) { 7992c593315Sopenharmony_ci return HD_ALT_SVC; 8002c593315Sopenharmony_ci } 8012c593315Sopenharmony_ci break; 8022c593315Sopenharmony_ci case 'd': 8032c593315Sopenharmony_ci if (util::streq_l(":metho", name, 6)) { 8042c593315Sopenharmony_ci return HD__METHOD; 8052c593315Sopenharmony_ci } 8062c593315Sopenharmony_ci break; 8072c593315Sopenharmony_ci case 'e': 8082c593315Sopenharmony_ci if (util::streq_l(":schem", name, 6)) { 8092c593315Sopenharmony_ci return HD__SCHEME; 8102c593315Sopenharmony_ci } 8112c593315Sopenharmony_ci if (util::streq_l("upgrad", name, 6)) { 8122c593315Sopenharmony_ci return HD_UPGRADE; 8132c593315Sopenharmony_ci } 8142c593315Sopenharmony_ci break; 8152c593315Sopenharmony_ci case 'r': 8162c593315Sopenharmony_ci if (util::streq_l("traile", name, 6)) { 8172c593315Sopenharmony_ci return HD_TRAILER; 8182c593315Sopenharmony_ci } 8192c593315Sopenharmony_ci break; 8202c593315Sopenharmony_ci case 's': 8212c593315Sopenharmony_ci if (util::streq_l(":statu", name, 6)) { 8222c593315Sopenharmony_ci return HD__STATUS; 8232c593315Sopenharmony_ci } 8242c593315Sopenharmony_ci break; 8252c593315Sopenharmony_ci } 8262c593315Sopenharmony_ci break; 8272c593315Sopenharmony_ci case 8: 8282c593315Sopenharmony_ci switch (name[7]) { 8292c593315Sopenharmony_ci case 'n': 8302c593315Sopenharmony_ci if (util::streq_l("locatio", name, 7)) { 8312c593315Sopenharmony_ci return HD_LOCATION; 8322c593315Sopenharmony_ci } 8332c593315Sopenharmony_ci break; 8342c593315Sopenharmony_ci } 8352c593315Sopenharmony_ci break; 8362c593315Sopenharmony_ci case 9: 8372c593315Sopenharmony_ci switch (name[8]) { 8382c593315Sopenharmony_ci case 'd': 8392c593315Sopenharmony_ci if (util::streq_l("forwarde", name, 8)) { 8402c593315Sopenharmony_ci return HD_FORWARDED; 8412c593315Sopenharmony_ci } 8422c593315Sopenharmony_ci break; 8432c593315Sopenharmony_ci case 'l': 8442c593315Sopenharmony_ci if (util::streq_l(":protoco", name, 8)) { 8452c593315Sopenharmony_ci return HD__PROTOCOL; 8462c593315Sopenharmony_ci } 8472c593315Sopenharmony_ci break; 8482c593315Sopenharmony_ci } 8492c593315Sopenharmony_ci break; 8502c593315Sopenharmony_ci case 10: 8512c593315Sopenharmony_ci switch (name[9]) { 8522c593315Sopenharmony_ci case 'a': 8532c593315Sopenharmony_ci if (util::streq_l("early-dat", name, 9)) { 8542c593315Sopenharmony_ci return HD_EARLY_DATA; 8552c593315Sopenharmony_ci } 8562c593315Sopenharmony_ci break; 8572c593315Sopenharmony_ci case 'e': 8582c593315Sopenharmony_ci if (util::streq_l("keep-aliv", name, 9)) { 8592c593315Sopenharmony_ci return HD_KEEP_ALIVE; 8602c593315Sopenharmony_ci } 8612c593315Sopenharmony_ci break; 8622c593315Sopenharmony_ci case 'n': 8632c593315Sopenharmony_ci if (util::streq_l("connectio", name, 9)) { 8642c593315Sopenharmony_ci return HD_CONNECTION; 8652c593315Sopenharmony_ci } 8662c593315Sopenharmony_ci break; 8672c593315Sopenharmony_ci case 't': 8682c593315Sopenharmony_ci if (util::streq_l("user-agen", name, 9)) { 8692c593315Sopenharmony_ci return HD_USER_AGENT; 8702c593315Sopenharmony_ci } 8712c593315Sopenharmony_ci break; 8722c593315Sopenharmony_ci case 'y': 8732c593315Sopenharmony_ci if (util::streq_l(":authorit", name, 9)) { 8742c593315Sopenharmony_ci return HD__AUTHORITY; 8752c593315Sopenharmony_ci } 8762c593315Sopenharmony_ci break; 8772c593315Sopenharmony_ci } 8782c593315Sopenharmony_ci break; 8792c593315Sopenharmony_ci case 12: 8802c593315Sopenharmony_ci switch (name[11]) { 8812c593315Sopenharmony_ci case 'e': 8822c593315Sopenharmony_ci if (util::streq_l("content-typ", name, 11)) { 8832c593315Sopenharmony_ci return HD_CONTENT_TYPE; 8842c593315Sopenharmony_ci } 8852c593315Sopenharmony_ci break; 8862c593315Sopenharmony_ci } 8872c593315Sopenharmony_ci break; 8882c593315Sopenharmony_ci case 13: 8892c593315Sopenharmony_ci switch (name[12]) { 8902c593315Sopenharmony_ci case 'l': 8912c593315Sopenharmony_ci if (util::streq_l("cache-contro", name, 12)) { 8922c593315Sopenharmony_ci return HD_CACHE_CONTROL; 8932c593315Sopenharmony_ci } 8942c593315Sopenharmony_ci break; 8952c593315Sopenharmony_ci } 8962c593315Sopenharmony_ci break; 8972c593315Sopenharmony_ci case 14: 8982c593315Sopenharmony_ci switch (name[13]) { 8992c593315Sopenharmony_ci case 'h': 9002c593315Sopenharmony_ci if (util::streq_l("content-lengt", name, 13)) { 9012c593315Sopenharmony_ci return HD_CONTENT_LENGTH; 9022c593315Sopenharmony_ci } 9032c593315Sopenharmony_ci break; 9042c593315Sopenharmony_ci case 's': 9052c593315Sopenharmony_ci if (util::streq_l("http2-setting", name, 13)) { 9062c593315Sopenharmony_ci return HD_HTTP2_SETTINGS; 9072c593315Sopenharmony_ci } 9082c593315Sopenharmony_ci break; 9092c593315Sopenharmony_ci } 9102c593315Sopenharmony_ci break; 9112c593315Sopenharmony_ci case 15: 9122c593315Sopenharmony_ci switch (name[14]) { 9132c593315Sopenharmony_ci case 'e': 9142c593315Sopenharmony_ci if (util::streq_l("accept-languag", name, 14)) { 9152c593315Sopenharmony_ci return HD_ACCEPT_LANGUAGE; 9162c593315Sopenharmony_ci } 9172c593315Sopenharmony_ci break; 9182c593315Sopenharmony_ci case 'g': 9192c593315Sopenharmony_ci if (util::streq_l("accept-encodin", name, 14)) { 9202c593315Sopenharmony_ci return HD_ACCEPT_ENCODING; 9212c593315Sopenharmony_ci } 9222c593315Sopenharmony_ci break; 9232c593315Sopenharmony_ci case 'r': 9242c593315Sopenharmony_ci if (util::streq_l("x-forwarded-fo", name, 14)) { 9252c593315Sopenharmony_ci return HD_X_FORWARDED_FOR; 9262c593315Sopenharmony_ci } 9272c593315Sopenharmony_ci break; 9282c593315Sopenharmony_ci } 9292c593315Sopenharmony_ci break; 9302c593315Sopenharmony_ci case 16: 9312c593315Sopenharmony_ci switch (name[15]) { 9322c593315Sopenharmony_ci case 'n': 9332c593315Sopenharmony_ci if (util::streq_l("proxy-connectio", name, 15)) { 9342c593315Sopenharmony_ci return HD_PROXY_CONNECTION; 9352c593315Sopenharmony_ci } 9362c593315Sopenharmony_ci break; 9372c593315Sopenharmony_ci } 9382c593315Sopenharmony_ci break; 9392c593315Sopenharmony_ci case 17: 9402c593315Sopenharmony_ci switch (name[16]) { 9412c593315Sopenharmony_ci case 'e': 9422c593315Sopenharmony_ci if (util::streq_l("if-modified-sinc", name, 16)) { 9432c593315Sopenharmony_ci return HD_IF_MODIFIED_SINCE; 9442c593315Sopenharmony_ci } 9452c593315Sopenharmony_ci break; 9462c593315Sopenharmony_ci case 'g': 9472c593315Sopenharmony_ci if (util::streq_l("transfer-encodin", name, 16)) { 9482c593315Sopenharmony_ci return HD_TRANSFER_ENCODING; 9492c593315Sopenharmony_ci } 9502c593315Sopenharmony_ci break; 9512c593315Sopenharmony_ci case 'o': 9522c593315Sopenharmony_ci if (util::streq_l("x-forwarded-prot", name, 16)) { 9532c593315Sopenharmony_ci return HD_X_FORWARDED_PROTO; 9542c593315Sopenharmony_ci } 9552c593315Sopenharmony_ci break; 9562c593315Sopenharmony_ci case 'y': 9572c593315Sopenharmony_ci if (util::streq_l("sec-websocket-ke", name, 16)) { 9582c593315Sopenharmony_ci return HD_SEC_WEBSOCKET_KEY; 9592c593315Sopenharmony_ci } 9602c593315Sopenharmony_ci break; 9612c593315Sopenharmony_ci } 9622c593315Sopenharmony_ci break; 9632c593315Sopenharmony_ci case 20: 9642c593315Sopenharmony_ci switch (name[19]) { 9652c593315Sopenharmony_ci case 't': 9662c593315Sopenharmony_ci if (util::streq_l("sec-websocket-accep", name, 19)) { 9672c593315Sopenharmony_ci return HD_SEC_WEBSOCKET_ACCEPT; 9682c593315Sopenharmony_ci } 9692c593315Sopenharmony_ci break; 9702c593315Sopenharmony_ci } 9712c593315Sopenharmony_ci break; 9722c593315Sopenharmony_ci } 9732c593315Sopenharmony_ci return -1; 9742c593315Sopenharmony_ci} 9752c593315Sopenharmony_ci 9762c593315Sopenharmony_civoid init_hdidx(HeaderIndex &hdidx) { 9772c593315Sopenharmony_ci std::fill(std::begin(hdidx), std::end(hdidx), -1); 9782c593315Sopenharmony_ci} 9792c593315Sopenharmony_ci 9802c593315Sopenharmony_civoid index_header(HeaderIndex &hdidx, int32_t token, size_t idx) { 9812c593315Sopenharmony_ci if (token == -1) { 9822c593315Sopenharmony_ci return; 9832c593315Sopenharmony_ci } 9842c593315Sopenharmony_ci assert(token < HD_MAXIDX); 9852c593315Sopenharmony_ci hdidx[token] = idx; 9862c593315Sopenharmony_ci} 9872c593315Sopenharmony_ci 9882c593315Sopenharmony_ciconst Headers::value_type *get_header(const HeaderIndex &hdidx, int32_t token, 9892c593315Sopenharmony_ci const Headers &nva) { 9902c593315Sopenharmony_ci auto i = hdidx[token]; 9912c593315Sopenharmony_ci if (i == -1) { 9922c593315Sopenharmony_ci return nullptr; 9932c593315Sopenharmony_ci } 9942c593315Sopenharmony_ci return &nva[i]; 9952c593315Sopenharmony_ci} 9962c593315Sopenharmony_ci 9972c593315Sopenharmony_ciHeaders::value_type *get_header(const HeaderIndex &hdidx, int32_t token, 9982c593315Sopenharmony_ci Headers &nva) { 9992c593315Sopenharmony_ci auto i = hdidx[token]; 10002c593315Sopenharmony_ci if (i == -1) { 10012c593315Sopenharmony_ci return nullptr; 10022c593315Sopenharmony_ci } 10032c593315Sopenharmony_ci return &nva[i]; 10042c593315Sopenharmony_ci} 10052c593315Sopenharmony_ci 10062c593315Sopenharmony_cinamespace { 10072c593315Sopenharmony_citemplate <typename InputIt> InputIt skip_lws(InputIt first, InputIt last) { 10082c593315Sopenharmony_ci for (; first != last; ++first) { 10092c593315Sopenharmony_ci switch (*first) { 10102c593315Sopenharmony_ci case ' ': 10112c593315Sopenharmony_ci case '\t': 10122c593315Sopenharmony_ci continue; 10132c593315Sopenharmony_ci default: 10142c593315Sopenharmony_ci return first; 10152c593315Sopenharmony_ci } 10162c593315Sopenharmony_ci } 10172c593315Sopenharmony_ci return first; 10182c593315Sopenharmony_ci} 10192c593315Sopenharmony_ci} // namespace 10202c593315Sopenharmony_ci 10212c593315Sopenharmony_cinamespace { 10222c593315Sopenharmony_citemplate <typename InputIt> 10232c593315Sopenharmony_ciInputIt skip_to_next_field(InputIt first, InputIt last) { 10242c593315Sopenharmony_ci for (; first != last; ++first) { 10252c593315Sopenharmony_ci switch (*first) { 10262c593315Sopenharmony_ci case ' ': 10272c593315Sopenharmony_ci case '\t': 10282c593315Sopenharmony_ci case ',': 10292c593315Sopenharmony_ci continue; 10302c593315Sopenharmony_ci default: 10312c593315Sopenharmony_ci return first; 10322c593315Sopenharmony_ci } 10332c593315Sopenharmony_ci } 10342c593315Sopenharmony_ci return first; 10352c593315Sopenharmony_ci} 10362c593315Sopenharmony_ci} // namespace 10372c593315Sopenharmony_ci 10382c593315Sopenharmony_cinamespace { 10392c593315Sopenharmony_ci// Skip to the right dquote ('"'), handling backslash escapes. 10402c593315Sopenharmony_ci// Returns |last| if input is not terminated with '"'. 10412c593315Sopenharmony_citemplate <typename InputIt> 10422c593315Sopenharmony_ciInputIt skip_to_right_dquote(InputIt first, InputIt last) { 10432c593315Sopenharmony_ci for (; first != last;) { 10442c593315Sopenharmony_ci switch (*first) { 10452c593315Sopenharmony_ci case '"': 10462c593315Sopenharmony_ci return first; 10472c593315Sopenharmony_ci // quoted-pair 10482c593315Sopenharmony_ci case '\\': 10492c593315Sopenharmony_ci ++first; 10502c593315Sopenharmony_ci if (first == last) { 10512c593315Sopenharmony_ci return first; 10522c593315Sopenharmony_ci } 10532c593315Sopenharmony_ci 10542c593315Sopenharmony_ci switch (*first) { 10552c593315Sopenharmony_ci case '\t': 10562c593315Sopenharmony_ci case ' ': 10572c593315Sopenharmony_ci break; 10582c593315Sopenharmony_ci default: 10592c593315Sopenharmony_ci if ((0x21 <= *first && *first <= 0x7e) /* VCHAR */ || 10602c593315Sopenharmony_ci (0x80 <= *first && *first <= 0xff) /* obs-text */) { 10612c593315Sopenharmony_ci break; 10622c593315Sopenharmony_ci } 10632c593315Sopenharmony_ci 10642c593315Sopenharmony_ci return last; 10652c593315Sopenharmony_ci } 10662c593315Sopenharmony_ci 10672c593315Sopenharmony_ci break; 10682c593315Sopenharmony_ci // qdtext 10692c593315Sopenharmony_ci case '\t': 10702c593315Sopenharmony_ci case ' ': 10712c593315Sopenharmony_ci case '!': 10722c593315Sopenharmony_ci break; 10732c593315Sopenharmony_ci default: 10742c593315Sopenharmony_ci if ((0x23 <= *first && *first <= 0x5b) || 10752c593315Sopenharmony_ci (0x5d <= *first && *first <= 0x7e)) { 10762c593315Sopenharmony_ci break; 10772c593315Sopenharmony_ci } 10782c593315Sopenharmony_ci 10792c593315Sopenharmony_ci return last; 10802c593315Sopenharmony_ci } 10812c593315Sopenharmony_ci ++first; 10822c593315Sopenharmony_ci } 10832c593315Sopenharmony_ci return first; 10842c593315Sopenharmony_ci} 10852c593315Sopenharmony_ci} // namespace 10862c593315Sopenharmony_ci 10872c593315Sopenharmony_cinamespace { 10882c593315Sopenharmony_ci// Returns true if link-param does not match pattern |pat| of length 10892c593315Sopenharmony_ci// |patlen| or it has empty value (""). |pat| should be parmname 10902c593315Sopenharmony_ci// followed by "=". 10912c593315Sopenharmony_cibool check_link_param_empty(const char *first, const char *last, 10922c593315Sopenharmony_ci const char *pat, size_t patlen) { 10932c593315Sopenharmony_ci if (first + patlen <= last) { 10942c593315Sopenharmony_ci if (std::equal(pat, pat + patlen, first, util::CaseCmp())) { 10952c593315Sopenharmony_ci // we only accept URI if pat is followd by "" (e.g., 10962c593315Sopenharmony_ci // loadpolicy="") here. 10972c593315Sopenharmony_ci if (first + patlen + 2 <= last) { 10982c593315Sopenharmony_ci if (*(first + patlen) != '"' || *(first + patlen + 1) != '"') { 10992c593315Sopenharmony_ci return false; 11002c593315Sopenharmony_ci } 11012c593315Sopenharmony_ci } else { 11022c593315Sopenharmony_ci // here we got invalid production (anchor=") or anchor=? 11032c593315Sopenharmony_ci return false; 11042c593315Sopenharmony_ci } 11052c593315Sopenharmony_ci } 11062c593315Sopenharmony_ci } 11072c593315Sopenharmony_ci return true; 11082c593315Sopenharmony_ci} 11092c593315Sopenharmony_ci} // namespace 11102c593315Sopenharmony_ci 11112c593315Sopenharmony_cinamespace { 11122c593315Sopenharmony_ci// Returns true if link-param consists of only parmname, and it 11132c593315Sopenharmony_ci// matches string [pat, pat + patlen). 11142c593315Sopenharmony_cibool check_link_param_without_value(const char *first, const char *last, 11152c593315Sopenharmony_ci const char *pat, size_t patlen) { 11162c593315Sopenharmony_ci if (first + patlen > last) { 11172c593315Sopenharmony_ci return false; 11182c593315Sopenharmony_ci } 11192c593315Sopenharmony_ci 11202c593315Sopenharmony_ci if (first + patlen == last) { 11212c593315Sopenharmony_ci return std::equal(pat, pat + patlen, first, util::CaseCmp()); 11222c593315Sopenharmony_ci } 11232c593315Sopenharmony_ci 11242c593315Sopenharmony_ci switch (*(first + patlen)) { 11252c593315Sopenharmony_ci case ';': 11262c593315Sopenharmony_ci case ',': 11272c593315Sopenharmony_ci return std::equal(pat, pat + patlen, first, util::CaseCmp()); 11282c593315Sopenharmony_ci } 11292c593315Sopenharmony_ci 11302c593315Sopenharmony_ci return false; 11312c593315Sopenharmony_ci} 11322c593315Sopenharmony_ci} // namespace 11332c593315Sopenharmony_ci 11342c593315Sopenharmony_cinamespace { 11352c593315Sopenharmony_cistd::pair<LinkHeader, const char *> 11362c593315Sopenharmony_ciparse_next_link_header_once(const char *first, const char *last) { 11372c593315Sopenharmony_ci first = skip_to_next_field(first, last); 11382c593315Sopenharmony_ci if (first == last || *first != '<') { 11392c593315Sopenharmony_ci return {{StringRef{}}, last}; 11402c593315Sopenharmony_ci } 11412c593315Sopenharmony_ci auto url_first = ++first; 11422c593315Sopenharmony_ci first = std::find(first, last, '>'); 11432c593315Sopenharmony_ci if (first == last) { 11442c593315Sopenharmony_ci return {{StringRef{}}, first}; 11452c593315Sopenharmony_ci } 11462c593315Sopenharmony_ci auto url_last = first++; 11472c593315Sopenharmony_ci if (first == last) { 11482c593315Sopenharmony_ci return {{StringRef{}}, first}; 11492c593315Sopenharmony_ci } 11502c593315Sopenharmony_ci // we expect ';' or ',' here 11512c593315Sopenharmony_ci switch (*first) { 11522c593315Sopenharmony_ci case ',': 11532c593315Sopenharmony_ci return {{StringRef{}}, ++first}; 11542c593315Sopenharmony_ci case ';': 11552c593315Sopenharmony_ci ++first; 11562c593315Sopenharmony_ci break; 11572c593315Sopenharmony_ci default: 11582c593315Sopenharmony_ci return {{StringRef{}}, last}; 11592c593315Sopenharmony_ci } 11602c593315Sopenharmony_ci 11612c593315Sopenharmony_ci auto ok = false; 11622c593315Sopenharmony_ci auto ign = false; 11632c593315Sopenharmony_ci for (;;) { 11642c593315Sopenharmony_ci first = skip_lws(first, last); 11652c593315Sopenharmony_ci if (first == last) { 11662c593315Sopenharmony_ci return {{StringRef{}}, first}; 11672c593315Sopenharmony_ci } 11682c593315Sopenharmony_ci // we expect link-param 11692c593315Sopenharmony_ci 11702c593315Sopenharmony_ci if (!ign) { 11712c593315Sopenharmony_ci if (!ok) { 11722c593315Sopenharmony_ci // rel can take several relations using quoted form. 11732c593315Sopenharmony_ci static constexpr char PLP[] = "rel=\""; 11742c593315Sopenharmony_ci static constexpr size_t PLPLEN = str_size(PLP); 11752c593315Sopenharmony_ci 11762c593315Sopenharmony_ci static constexpr char PLT[] = "preload"; 11772c593315Sopenharmony_ci static constexpr size_t PLTLEN = str_size(PLT); 11782c593315Sopenharmony_ci if (first + PLPLEN < last && *(first + PLPLEN - 1) == '"' && 11792c593315Sopenharmony_ci std::equal(PLP, PLP + PLPLEN, first, util::CaseCmp())) { 11802c593315Sopenharmony_ci // we have to search preload in whitespace separated list: 11812c593315Sopenharmony_ci // rel="preload something http://example.org/foo" 11822c593315Sopenharmony_ci first += PLPLEN; 11832c593315Sopenharmony_ci auto start = first; 11842c593315Sopenharmony_ci for (; first != last;) { 11852c593315Sopenharmony_ci if (*first != ' ' && *first != '"') { 11862c593315Sopenharmony_ci ++first; 11872c593315Sopenharmony_ci continue; 11882c593315Sopenharmony_ci } 11892c593315Sopenharmony_ci 11902c593315Sopenharmony_ci if (start == first) { 11912c593315Sopenharmony_ci return {{StringRef{}}, last}; 11922c593315Sopenharmony_ci } 11932c593315Sopenharmony_ci 11942c593315Sopenharmony_ci if (!ok && start + PLTLEN == first && 11952c593315Sopenharmony_ci std::equal(PLT, PLT + PLTLEN, start, util::CaseCmp())) { 11962c593315Sopenharmony_ci ok = true; 11972c593315Sopenharmony_ci } 11982c593315Sopenharmony_ci 11992c593315Sopenharmony_ci if (*first == '"') { 12002c593315Sopenharmony_ci break; 12012c593315Sopenharmony_ci } 12022c593315Sopenharmony_ci first = skip_lws(first, last); 12032c593315Sopenharmony_ci start = first; 12042c593315Sopenharmony_ci } 12052c593315Sopenharmony_ci if (first == last) { 12062c593315Sopenharmony_ci return {{StringRef{}}, last}; 12072c593315Sopenharmony_ci } 12082c593315Sopenharmony_ci assert(*first == '"'); 12092c593315Sopenharmony_ci ++first; 12102c593315Sopenharmony_ci if (first == last || *first == ',') { 12112c593315Sopenharmony_ci goto almost_done; 12122c593315Sopenharmony_ci } 12132c593315Sopenharmony_ci if (*first == ';') { 12142c593315Sopenharmony_ci ++first; 12152c593315Sopenharmony_ci // parse next link-param 12162c593315Sopenharmony_ci continue; 12172c593315Sopenharmony_ci } 12182c593315Sopenharmony_ci return {{StringRef{}}, last}; 12192c593315Sopenharmony_ci } 12202c593315Sopenharmony_ci } 12212c593315Sopenharmony_ci // we are only interested in rel=preload parameter. Others are 12222c593315Sopenharmony_ci // simply skipped. 12232c593315Sopenharmony_ci static constexpr char PL[] = "rel=preload"; 12242c593315Sopenharmony_ci static constexpr size_t PLLEN = str_size(PL); 12252c593315Sopenharmony_ci if (first + PLLEN == last) { 12262c593315Sopenharmony_ci if (std::equal(PL, PL + PLLEN, first, util::CaseCmp())) { 12272c593315Sopenharmony_ci // ok = true; 12282c593315Sopenharmony_ci // this is the end of sequence 12292c593315Sopenharmony_ci return {{{url_first, url_last}}, last}; 12302c593315Sopenharmony_ci } 12312c593315Sopenharmony_ci } else if (first + PLLEN + 1 <= last) { 12322c593315Sopenharmony_ci switch (*(first + PLLEN)) { 12332c593315Sopenharmony_ci case ',': 12342c593315Sopenharmony_ci if (!std::equal(PL, PL + PLLEN, first, util::CaseCmp())) { 12352c593315Sopenharmony_ci break; 12362c593315Sopenharmony_ci } 12372c593315Sopenharmony_ci // ok = true; 12382c593315Sopenharmony_ci // skip including ',' 12392c593315Sopenharmony_ci first += PLLEN + 1; 12402c593315Sopenharmony_ci return {{{url_first, url_last}}, first}; 12412c593315Sopenharmony_ci case ';': 12422c593315Sopenharmony_ci if (!std::equal(PL, PL + PLLEN, first, util::CaseCmp())) { 12432c593315Sopenharmony_ci break; 12442c593315Sopenharmony_ci } 12452c593315Sopenharmony_ci ok = true; 12462c593315Sopenharmony_ci // skip including ';' 12472c593315Sopenharmony_ci first += PLLEN + 1; 12482c593315Sopenharmony_ci // continue parse next link-param 12492c593315Sopenharmony_ci continue; 12502c593315Sopenharmony_ci } 12512c593315Sopenharmony_ci } 12522c593315Sopenharmony_ci // we have to reject URI if we have nonempty anchor parameter. 12532c593315Sopenharmony_ci static constexpr char ANCHOR[] = "anchor="; 12542c593315Sopenharmony_ci static constexpr size_t ANCHORLEN = str_size(ANCHOR); 12552c593315Sopenharmony_ci if (!ign && !check_link_param_empty(first, last, ANCHOR, ANCHORLEN)) { 12562c593315Sopenharmony_ci ign = true; 12572c593315Sopenharmony_ci } 12582c593315Sopenharmony_ci 12592c593315Sopenharmony_ci // reject URI if we have non-empty loadpolicy. This could be 12602c593315Sopenharmony_ci // tightened up to just pick up "next" or "insert". 12612c593315Sopenharmony_ci static constexpr char LOADPOLICY[] = "loadpolicy="; 12622c593315Sopenharmony_ci static constexpr size_t LOADPOLICYLEN = str_size(LOADPOLICY); 12632c593315Sopenharmony_ci if (!ign && 12642c593315Sopenharmony_ci !check_link_param_empty(first, last, LOADPOLICY, LOADPOLICYLEN)) { 12652c593315Sopenharmony_ci ign = true; 12662c593315Sopenharmony_ci } 12672c593315Sopenharmony_ci 12682c593315Sopenharmony_ci // reject URI if we have nopush attribute. 12692c593315Sopenharmony_ci static constexpr char NOPUSH[] = "nopush"; 12702c593315Sopenharmony_ci static constexpr size_t NOPUSHLEN = str_size(NOPUSH); 12712c593315Sopenharmony_ci if (!ign && 12722c593315Sopenharmony_ci check_link_param_without_value(first, last, NOPUSH, NOPUSHLEN)) { 12732c593315Sopenharmony_ci ign = true; 12742c593315Sopenharmony_ci } 12752c593315Sopenharmony_ci } 12762c593315Sopenharmony_ci 12772c593315Sopenharmony_ci auto param_first = first; 12782c593315Sopenharmony_ci for (; first != last;) { 12792c593315Sopenharmony_ci if (util::in_attr_char(*first)) { 12802c593315Sopenharmony_ci ++first; 12812c593315Sopenharmony_ci continue; 12822c593315Sopenharmony_ci } 12832c593315Sopenharmony_ci // '*' is only allowed at the end of parameter name and must be 12842c593315Sopenharmony_ci // followed by '=' 12852c593315Sopenharmony_ci if (last - first >= 2 && first != param_first) { 12862c593315Sopenharmony_ci if (*first == '*' && *(first + 1) == '=') { 12872c593315Sopenharmony_ci ++first; 12882c593315Sopenharmony_ci break; 12892c593315Sopenharmony_ci } 12902c593315Sopenharmony_ci } 12912c593315Sopenharmony_ci if (*first == '=' || *first == ';' || *first == ',') { 12922c593315Sopenharmony_ci break; 12932c593315Sopenharmony_ci } 12942c593315Sopenharmony_ci return {{StringRef{}}, last}; 12952c593315Sopenharmony_ci } 12962c593315Sopenharmony_ci if (param_first == first) { 12972c593315Sopenharmony_ci // empty parmname 12982c593315Sopenharmony_ci return {{StringRef{}}, last}; 12992c593315Sopenharmony_ci } 13002c593315Sopenharmony_ci // link-param without value is acceptable (see link-extension) if 13012c593315Sopenharmony_ci // it is not followed by '=' 13022c593315Sopenharmony_ci if (first == last || *first == ',') { 13032c593315Sopenharmony_ci goto almost_done; 13042c593315Sopenharmony_ci } 13052c593315Sopenharmony_ci if (*first == ';') { 13062c593315Sopenharmony_ci ++first; 13072c593315Sopenharmony_ci // parse next link-param 13082c593315Sopenharmony_ci continue; 13092c593315Sopenharmony_ci } 13102c593315Sopenharmony_ci // now parsing link-param value 13112c593315Sopenharmony_ci assert(*first == '='); 13122c593315Sopenharmony_ci ++first; 13132c593315Sopenharmony_ci if (first == last) { 13142c593315Sopenharmony_ci // empty value is not acceptable 13152c593315Sopenharmony_ci return {{StringRef{}}, first}; 13162c593315Sopenharmony_ci } 13172c593315Sopenharmony_ci if (*first == '"') { 13182c593315Sopenharmony_ci // quoted-string 13192c593315Sopenharmony_ci first = skip_to_right_dquote(first + 1, last); 13202c593315Sopenharmony_ci if (first == last) { 13212c593315Sopenharmony_ci return {{StringRef{}}, first}; 13222c593315Sopenharmony_ci } 13232c593315Sopenharmony_ci ++first; 13242c593315Sopenharmony_ci if (first == last || *first == ',') { 13252c593315Sopenharmony_ci goto almost_done; 13262c593315Sopenharmony_ci } 13272c593315Sopenharmony_ci if (*first == ';') { 13282c593315Sopenharmony_ci ++first; 13292c593315Sopenharmony_ci // parse next link-param 13302c593315Sopenharmony_ci continue; 13312c593315Sopenharmony_ci } 13322c593315Sopenharmony_ci return {{StringRef{}}, last}; 13332c593315Sopenharmony_ci } 13342c593315Sopenharmony_ci // not quoted-string, skip to next ',' or ';' 13352c593315Sopenharmony_ci if (*first == ',' || *first == ';') { 13362c593315Sopenharmony_ci // empty value 13372c593315Sopenharmony_ci return {{StringRef{}}, last}; 13382c593315Sopenharmony_ci } 13392c593315Sopenharmony_ci for (; first != last; ++first) { 13402c593315Sopenharmony_ci if (*first == ',' || *first == ';') { 13412c593315Sopenharmony_ci break; 13422c593315Sopenharmony_ci } 13432c593315Sopenharmony_ci } 13442c593315Sopenharmony_ci if (first == last || *first == ',') { 13452c593315Sopenharmony_ci goto almost_done; 13462c593315Sopenharmony_ci } 13472c593315Sopenharmony_ci assert(*first == ';'); 13482c593315Sopenharmony_ci ++first; 13492c593315Sopenharmony_ci // parse next link-param 13502c593315Sopenharmony_ci } 13512c593315Sopenharmony_ci 13522c593315Sopenharmony_cialmost_done: 13532c593315Sopenharmony_ci assert(first == last || *first == ','); 13542c593315Sopenharmony_ci 13552c593315Sopenharmony_ci if (first != last) { 13562c593315Sopenharmony_ci ++first; 13572c593315Sopenharmony_ci } 13582c593315Sopenharmony_ci if (ok && !ign) { 13592c593315Sopenharmony_ci return {{{url_first, url_last}}, first}; 13602c593315Sopenharmony_ci } 13612c593315Sopenharmony_ci return {{StringRef{}}, first}; 13622c593315Sopenharmony_ci} 13632c593315Sopenharmony_ci} // namespace 13642c593315Sopenharmony_ci 13652c593315Sopenharmony_cistd::vector<LinkHeader> parse_link_header(const StringRef &src) { 13662c593315Sopenharmony_ci std::vector<LinkHeader> res; 13672c593315Sopenharmony_ci for (auto first = std::begin(src); first != std::end(src);) { 13682c593315Sopenharmony_ci auto rv = parse_next_link_header_once(first, std::end(src)); 13692c593315Sopenharmony_ci first = rv.second; 13702c593315Sopenharmony_ci auto &link = rv.first; 13712c593315Sopenharmony_ci if (!link.uri.empty()) { 13722c593315Sopenharmony_ci res.push_back(link); 13732c593315Sopenharmony_ci } 13742c593315Sopenharmony_ci } 13752c593315Sopenharmony_ci return res; 13762c593315Sopenharmony_ci} 13772c593315Sopenharmony_ci 13782c593315Sopenharmony_cistd::string path_join(const StringRef &base_path, const StringRef &base_query, 13792c593315Sopenharmony_ci const StringRef &rel_path, const StringRef &rel_query) { 13802c593315Sopenharmony_ci BlockAllocator balloc(1024, 1024); 13812c593315Sopenharmony_ci 13822c593315Sopenharmony_ci return path_join(balloc, base_path, base_query, rel_path, rel_query).str(); 13832c593315Sopenharmony_ci} 13842c593315Sopenharmony_ci 13852c593315Sopenharmony_cibool expect_response_body(int status_code) { 13862c593315Sopenharmony_ci return status_code == 101 || 13872c593315Sopenharmony_ci (status_code / 100 != 1 && status_code != 304 && status_code != 204); 13882c593315Sopenharmony_ci} 13892c593315Sopenharmony_ci 13902c593315Sopenharmony_cibool expect_response_body(const std::string &method, int status_code) { 13912c593315Sopenharmony_ci return method != "HEAD" && expect_response_body(status_code); 13922c593315Sopenharmony_ci} 13932c593315Sopenharmony_ci 13942c593315Sopenharmony_cibool expect_response_body(int method_token, int status_code) { 13952c593315Sopenharmony_ci return method_token != HTTP_HEAD && expect_response_body(status_code); 13962c593315Sopenharmony_ci} 13972c593315Sopenharmony_ci 13982c593315Sopenharmony_ciint lookup_method_token(const StringRef &name) { 13992c593315Sopenharmony_ci return lookup_method_token(name.byte(), name.size()); 14002c593315Sopenharmony_ci} 14012c593315Sopenharmony_ci 14022c593315Sopenharmony_ci// This function was generated by genmethodfunc.py. 14032c593315Sopenharmony_ciint lookup_method_token(const uint8_t *name, size_t namelen) { 14042c593315Sopenharmony_ci switch (namelen) { 14052c593315Sopenharmony_ci case 3: 14062c593315Sopenharmony_ci switch (name[2]) { 14072c593315Sopenharmony_ci case 'L': 14082c593315Sopenharmony_ci if (util::streq_l("AC", name, 2)) { 14092c593315Sopenharmony_ci return HTTP_ACL; 14102c593315Sopenharmony_ci } 14112c593315Sopenharmony_ci break; 14122c593315Sopenharmony_ci case 'T': 14132c593315Sopenharmony_ci if (util::streq_l("GE", name, 2)) { 14142c593315Sopenharmony_ci return HTTP_GET; 14152c593315Sopenharmony_ci } 14162c593315Sopenharmony_ci if (util::streq_l("PU", name, 2)) { 14172c593315Sopenharmony_ci return HTTP_PUT; 14182c593315Sopenharmony_ci } 14192c593315Sopenharmony_ci break; 14202c593315Sopenharmony_ci } 14212c593315Sopenharmony_ci break; 14222c593315Sopenharmony_ci case 4: 14232c593315Sopenharmony_ci switch (name[3]) { 14242c593315Sopenharmony_ci case 'D': 14252c593315Sopenharmony_ci if (util::streq_l("BIN", name, 3)) { 14262c593315Sopenharmony_ci return HTTP_BIND; 14272c593315Sopenharmony_ci } 14282c593315Sopenharmony_ci if (util::streq_l("HEA", name, 3)) { 14292c593315Sopenharmony_ci return HTTP_HEAD; 14302c593315Sopenharmony_ci } 14312c593315Sopenharmony_ci break; 14322c593315Sopenharmony_ci case 'E': 14332c593315Sopenharmony_ci if (util::streq_l("MOV", name, 3)) { 14342c593315Sopenharmony_ci return HTTP_MOVE; 14352c593315Sopenharmony_ci } 14362c593315Sopenharmony_ci break; 14372c593315Sopenharmony_ci case 'K': 14382c593315Sopenharmony_ci if (util::streq_l("LIN", name, 3)) { 14392c593315Sopenharmony_ci return HTTP_LINK; 14402c593315Sopenharmony_ci } 14412c593315Sopenharmony_ci if (util::streq_l("LOC", name, 3)) { 14422c593315Sopenharmony_ci return HTTP_LOCK; 14432c593315Sopenharmony_ci } 14442c593315Sopenharmony_ci break; 14452c593315Sopenharmony_ci case 'T': 14462c593315Sopenharmony_ci if (util::streq_l("POS", name, 3)) { 14472c593315Sopenharmony_ci return HTTP_POST; 14482c593315Sopenharmony_ci } 14492c593315Sopenharmony_ci break; 14502c593315Sopenharmony_ci case 'Y': 14512c593315Sopenharmony_ci if (util::streq_l("COP", name, 3)) { 14522c593315Sopenharmony_ci return HTTP_COPY; 14532c593315Sopenharmony_ci } 14542c593315Sopenharmony_ci break; 14552c593315Sopenharmony_ci } 14562c593315Sopenharmony_ci break; 14572c593315Sopenharmony_ci case 5: 14582c593315Sopenharmony_ci switch (name[4]) { 14592c593315Sopenharmony_ci case 'E': 14602c593315Sopenharmony_ci if (util::streq_l("MERG", name, 4)) { 14612c593315Sopenharmony_ci return HTTP_MERGE; 14622c593315Sopenharmony_ci } 14632c593315Sopenharmony_ci if (util::streq_l("PURG", name, 4)) { 14642c593315Sopenharmony_ci return HTTP_PURGE; 14652c593315Sopenharmony_ci } 14662c593315Sopenharmony_ci if (util::streq_l("TRAC", name, 4)) { 14672c593315Sopenharmony_ci return HTTP_TRACE; 14682c593315Sopenharmony_ci } 14692c593315Sopenharmony_ci break; 14702c593315Sopenharmony_ci case 'H': 14712c593315Sopenharmony_ci if (util::streq_l("PATC", name, 4)) { 14722c593315Sopenharmony_ci return HTTP_PATCH; 14732c593315Sopenharmony_ci } 14742c593315Sopenharmony_ci break; 14752c593315Sopenharmony_ci case 'L': 14762c593315Sopenharmony_ci if (util::streq_l("MKCO", name, 4)) { 14772c593315Sopenharmony_ci return HTTP_MKCOL; 14782c593315Sopenharmony_ci } 14792c593315Sopenharmony_ci break; 14802c593315Sopenharmony_ci } 14812c593315Sopenharmony_ci break; 14822c593315Sopenharmony_ci case 6: 14832c593315Sopenharmony_ci switch (name[5]) { 14842c593315Sopenharmony_ci case 'D': 14852c593315Sopenharmony_ci if (util::streq_l("REBIN", name, 5)) { 14862c593315Sopenharmony_ci return HTTP_REBIND; 14872c593315Sopenharmony_ci } 14882c593315Sopenharmony_ci if (util::streq_l("UNBIN", name, 5)) { 14892c593315Sopenharmony_ci return HTTP_UNBIND; 14902c593315Sopenharmony_ci } 14912c593315Sopenharmony_ci break; 14922c593315Sopenharmony_ci case 'E': 14932c593315Sopenharmony_ci if (util::streq_l("DELET", name, 5)) { 14942c593315Sopenharmony_ci return HTTP_DELETE; 14952c593315Sopenharmony_ci } 14962c593315Sopenharmony_ci if (util::streq_l("SOURC", name, 5)) { 14972c593315Sopenharmony_ci return HTTP_SOURCE; 14982c593315Sopenharmony_ci } 14992c593315Sopenharmony_ci break; 15002c593315Sopenharmony_ci case 'H': 15012c593315Sopenharmony_ci if (util::streq_l("SEARC", name, 5)) { 15022c593315Sopenharmony_ci return HTTP_SEARCH; 15032c593315Sopenharmony_ci } 15042c593315Sopenharmony_ci break; 15052c593315Sopenharmony_ci case 'K': 15062c593315Sopenharmony_ci if (util::streq_l("UNLIN", name, 5)) { 15072c593315Sopenharmony_ci return HTTP_UNLINK; 15082c593315Sopenharmony_ci } 15092c593315Sopenharmony_ci if (util::streq_l("UNLOC", name, 5)) { 15102c593315Sopenharmony_ci return HTTP_UNLOCK; 15112c593315Sopenharmony_ci } 15122c593315Sopenharmony_ci break; 15132c593315Sopenharmony_ci case 'T': 15142c593315Sopenharmony_ci if (util::streq_l("REPOR", name, 5)) { 15152c593315Sopenharmony_ci return HTTP_REPORT; 15162c593315Sopenharmony_ci } 15172c593315Sopenharmony_ci break; 15182c593315Sopenharmony_ci case 'Y': 15192c593315Sopenharmony_ci if (util::streq_l("NOTIF", name, 5)) { 15202c593315Sopenharmony_ci return HTTP_NOTIFY; 15212c593315Sopenharmony_ci } 15222c593315Sopenharmony_ci break; 15232c593315Sopenharmony_ci } 15242c593315Sopenharmony_ci break; 15252c593315Sopenharmony_ci case 7: 15262c593315Sopenharmony_ci switch (name[6]) { 15272c593315Sopenharmony_ci case 'H': 15282c593315Sopenharmony_ci if (util::streq_l("MSEARC", name, 6)) { 15292c593315Sopenharmony_ci return HTTP_MSEARCH; 15302c593315Sopenharmony_ci } 15312c593315Sopenharmony_ci break; 15322c593315Sopenharmony_ci case 'S': 15332c593315Sopenharmony_ci if (util::streq_l("OPTION", name, 6)) { 15342c593315Sopenharmony_ci return HTTP_OPTIONS; 15352c593315Sopenharmony_ci } 15362c593315Sopenharmony_ci break; 15372c593315Sopenharmony_ci case 'T': 15382c593315Sopenharmony_ci if (util::streq_l("CONNEC", name, 6)) { 15392c593315Sopenharmony_ci return HTTP_CONNECT; 15402c593315Sopenharmony_ci } 15412c593315Sopenharmony_ci break; 15422c593315Sopenharmony_ci } 15432c593315Sopenharmony_ci break; 15442c593315Sopenharmony_ci case 8: 15452c593315Sopenharmony_ci switch (name[7]) { 15462c593315Sopenharmony_ci case 'D': 15472c593315Sopenharmony_ci if (util::streq_l("PROPFIN", name, 7)) { 15482c593315Sopenharmony_ci return HTTP_PROPFIND; 15492c593315Sopenharmony_ci } 15502c593315Sopenharmony_ci break; 15512c593315Sopenharmony_ci case 'T': 15522c593315Sopenharmony_ci if (util::streq_l("CHECKOU", name, 7)) { 15532c593315Sopenharmony_ci return HTTP_CHECKOUT; 15542c593315Sopenharmony_ci } 15552c593315Sopenharmony_ci break; 15562c593315Sopenharmony_ci } 15572c593315Sopenharmony_ci break; 15582c593315Sopenharmony_ci case 9: 15592c593315Sopenharmony_ci switch (name[8]) { 15602c593315Sopenharmony_ci case 'E': 15612c593315Sopenharmony_ci if (util::streq_l("SUBSCRIB", name, 8)) { 15622c593315Sopenharmony_ci return HTTP_SUBSCRIBE; 15632c593315Sopenharmony_ci } 15642c593315Sopenharmony_ci break; 15652c593315Sopenharmony_ci case 'H': 15662c593315Sopenharmony_ci if (util::streq_l("PROPPATC", name, 8)) { 15672c593315Sopenharmony_ci return HTTP_PROPPATCH; 15682c593315Sopenharmony_ci } 15692c593315Sopenharmony_ci break; 15702c593315Sopenharmony_ci } 15712c593315Sopenharmony_ci break; 15722c593315Sopenharmony_ci case 10: 15732c593315Sopenharmony_ci switch (name[9]) { 15742c593315Sopenharmony_ci case 'R': 15752c593315Sopenharmony_ci if (util::streq_l("MKCALENDA", name, 9)) { 15762c593315Sopenharmony_ci return HTTP_MKCALENDAR; 15772c593315Sopenharmony_ci } 15782c593315Sopenharmony_ci break; 15792c593315Sopenharmony_ci case 'Y': 15802c593315Sopenharmony_ci if (util::streq_l("MKACTIVIT", name, 9)) { 15812c593315Sopenharmony_ci return HTTP_MKACTIVITY; 15822c593315Sopenharmony_ci } 15832c593315Sopenharmony_ci break; 15842c593315Sopenharmony_ci } 15852c593315Sopenharmony_ci break; 15862c593315Sopenharmony_ci case 11: 15872c593315Sopenharmony_ci switch (name[10]) { 15882c593315Sopenharmony_ci case 'E': 15892c593315Sopenharmony_ci if (util::streq_l("UNSUBSCRIB", name, 10)) { 15902c593315Sopenharmony_ci return HTTP_UNSUBSCRIBE; 15912c593315Sopenharmony_ci } 15922c593315Sopenharmony_ci break; 15932c593315Sopenharmony_ci } 15942c593315Sopenharmony_ci break; 15952c593315Sopenharmony_ci } 15962c593315Sopenharmony_ci return -1; 15972c593315Sopenharmony_ci} 15982c593315Sopenharmony_ci 15992c593315Sopenharmony_ciStringRef to_method_string(int method_token) { 16002c593315Sopenharmony_ci // we happened to use same value for method with llhttp. 16012c593315Sopenharmony_ci return StringRef{ 16022c593315Sopenharmony_ci llhttp_method_name(static_cast<llhttp_method>(method_token))}; 16032c593315Sopenharmony_ci} 16042c593315Sopenharmony_ci 16052c593315Sopenharmony_ciStringRef get_pure_path_component(const StringRef &uri) { 16062c593315Sopenharmony_ci int rv; 16072c593315Sopenharmony_ci 16082c593315Sopenharmony_ci http_parser_url u{}; 16092c593315Sopenharmony_ci rv = http_parser_parse_url(uri.c_str(), uri.size(), 0, &u); 16102c593315Sopenharmony_ci if (rv != 0) { 16112c593315Sopenharmony_ci return StringRef{}; 16122c593315Sopenharmony_ci } 16132c593315Sopenharmony_ci 16142c593315Sopenharmony_ci if (u.field_set & (1 << UF_PATH)) { 16152c593315Sopenharmony_ci auto &f = u.field_data[UF_PATH]; 16162c593315Sopenharmony_ci return StringRef{uri.c_str() + f.off, f.len}; 16172c593315Sopenharmony_ci } 16182c593315Sopenharmony_ci 16192c593315Sopenharmony_ci return StringRef::from_lit("/"); 16202c593315Sopenharmony_ci} 16212c593315Sopenharmony_ci 16222c593315Sopenharmony_ciint construct_push_component(BlockAllocator &balloc, StringRef &scheme, 16232c593315Sopenharmony_ci StringRef &authority, StringRef &path, 16242c593315Sopenharmony_ci const StringRef &base, const StringRef &uri) { 16252c593315Sopenharmony_ci int rv; 16262c593315Sopenharmony_ci StringRef rel, relq; 16272c593315Sopenharmony_ci 16282c593315Sopenharmony_ci if (uri.size() == 0) { 16292c593315Sopenharmony_ci return -1; 16302c593315Sopenharmony_ci } 16312c593315Sopenharmony_ci 16322c593315Sopenharmony_ci http_parser_url u{}; 16332c593315Sopenharmony_ci 16342c593315Sopenharmony_ci rv = http_parser_parse_url(uri.c_str(), uri.size(), 0, &u); 16352c593315Sopenharmony_ci 16362c593315Sopenharmony_ci if (rv != 0) { 16372c593315Sopenharmony_ci if (uri[0] == '/') { 16382c593315Sopenharmony_ci return -1; 16392c593315Sopenharmony_ci } 16402c593315Sopenharmony_ci 16412c593315Sopenharmony_ci // treat link_url as relative URI. 16422c593315Sopenharmony_ci auto end = std::find(std::begin(uri), std::end(uri), '#'); 16432c593315Sopenharmony_ci auto q = std::find(std::begin(uri), end, '?'); 16442c593315Sopenharmony_ci 16452c593315Sopenharmony_ci rel = StringRef{std::begin(uri), q}; 16462c593315Sopenharmony_ci if (q != end) { 16472c593315Sopenharmony_ci relq = StringRef{q + 1, std::end(uri)}; 16482c593315Sopenharmony_ci } 16492c593315Sopenharmony_ci } else { 16502c593315Sopenharmony_ci if (u.field_set & (1 << UF_SCHEMA)) { 16512c593315Sopenharmony_ci scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); 16522c593315Sopenharmony_ci } 16532c593315Sopenharmony_ci 16542c593315Sopenharmony_ci if (u.field_set & (1 << UF_HOST)) { 16552c593315Sopenharmony_ci auto auth = util::get_uri_field(uri.c_str(), u, UF_HOST); 16562c593315Sopenharmony_ci auto len = auth.size(); 16572c593315Sopenharmony_ci auto port_exists = u.field_set & (1 << UF_PORT); 16582c593315Sopenharmony_ci if (port_exists) { 16592c593315Sopenharmony_ci len += 1 + str_size("65535"); 16602c593315Sopenharmony_ci } 16612c593315Sopenharmony_ci auto iov = make_byte_ref(balloc, len + 1); 16622c593315Sopenharmony_ci auto p = iov.base; 16632c593315Sopenharmony_ci p = std::copy(std::begin(auth), std::end(auth), p); 16642c593315Sopenharmony_ci if (port_exists) { 16652c593315Sopenharmony_ci *p++ = ':'; 16662c593315Sopenharmony_ci p = util::utos(p, u.port); 16672c593315Sopenharmony_ci } 16682c593315Sopenharmony_ci *p = '\0'; 16692c593315Sopenharmony_ci 16702c593315Sopenharmony_ci authority = StringRef{iov.base, p}; 16712c593315Sopenharmony_ci } 16722c593315Sopenharmony_ci 16732c593315Sopenharmony_ci if (u.field_set & (1 << UF_PATH)) { 16742c593315Sopenharmony_ci auto &f = u.field_data[UF_PATH]; 16752c593315Sopenharmony_ci rel = StringRef{uri.c_str() + f.off, f.len}; 16762c593315Sopenharmony_ci } else { 16772c593315Sopenharmony_ci rel = StringRef::from_lit("/"); 16782c593315Sopenharmony_ci } 16792c593315Sopenharmony_ci 16802c593315Sopenharmony_ci if (u.field_set & (1 << UF_QUERY)) { 16812c593315Sopenharmony_ci auto &f = u.field_data[UF_QUERY]; 16822c593315Sopenharmony_ci relq = StringRef{uri.c_str() + f.off, f.len}; 16832c593315Sopenharmony_ci } 16842c593315Sopenharmony_ci } 16852c593315Sopenharmony_ci 16862c593315Sopenharmony_ci path = http2::path_join(balloc, base, StringRef{}, rel, relq); 16872c593315Sopenharmony_ci 16882c593315Sopenharmony_ci return 0; 16892c593315Sopenharmony_ci} 16902c593315Sopenharmony_ci 16912c593315Sopenharmony_cinamespace { 16922c593315Sopenharmony_citemplate <typename InputIt> InputIt eat_file(InputIt first, InputIt last) { 16932c593315Sopenharmony_ci if (first == last) { 16942c593315Sopenharmony_ci *first++ = '/'; 16952c593315Sopenharmony_ci return first; 16962c593315Sopenharmony_ci } 16972c593315Sopenharmony_ci 16982c593315Sopenharmony_ci if (*(last - 1) == '/') { 16992c593315Sopenharmony_ci return last; 17002c593315Sopenharmony_ci } 17012c593315Sopenharmony_ci 17022c593315Sopenharmony_ci auto p = last; 17032c593315Sopenharmony_ci for (; p != first && *(p - 1) != '/'; --p) 17042c593315Sopenharmony_ci ; 17052c593315Sopenharmony_ci if (p == first) { 17062c593315Sopenharmony_ci // this should not happened in normal case, where we expect path 17072c593315Sopenharmony_ci // starts with '/' 17082c593315Sopenharmony_ci *first++ = '/'; 17092c593315Sopenharmony_ci return first; 17102c593315Sopenharmony_ci } 17112c593315Sopenharmony_ci 17122c593315Sopenharmony_ci return p; 17132c593315Sopenharmony_ci} 17142c593315Sopenharmony_ci} // namespace 17152c593315Sopenharmony_ci 17162c593315Sopenharmony_cinamespace { 17172c593315Sopenharmony_citemplate <typename InputIt> InputIt eat_dir(InputIt first, InputIt last) { 17182c593315Sopenharmony_ci auto p = eat_file(first, last); 17192c593315Sopenharmony_ci 17202c593315Sopenharmony_ci --p; 17212c593315Sopenharmony_ci 17222c593315Sopenharmony_ci assert(*p == '/'); 17232c593315Sopenharmony_ci 17242c593315Sopenharmony_ci return eat_file(first, p); 17252c593315Sopenharmony_ci} 17262c593315Sopenharmony_ci} // namespace 17272c593315Sopenharmony_ci 17282c593315Sopenharmony_ciStringRef path_join(BlockAllocator &balloc, const StringRef &base_path, 17292c593315Sopenharmony_ci const StringRef &base_query, const StringRef &rel_path, 17302c593315Sopenharmony_ci const StringRef &rel_query) { 17312c593315Sopenharmony_ci auto res = make_byte_ref( 17322c593315Sopenharmony_ci balloc, std::max(static_cast<size_t>(1), base_path.size()) + 17332c593315Sopenharmony_ci rel_path.size() + 1 + 17342c593315Sopenharmony_ci std::max(base_query.size(), rel_query.size()) + 1); 17352c593315Sopenharmony_ci auto p = res.base; 17362c593315Sopenharmony_ci 17372c593315Sopenharmony_ci if (rel_path.empty()) { 17382c593315Sopenharmony_ci if (base_path.empty()) { 17392c593315Sopenharmony_ci *p++ = '/'; 17402c593315Sopenharmony_ci } else { 17412c593315Sopenharmony_ci p = std::copy(std::begin(base_path), std::end(base_path), p); 17422c593315Sopenharmony_ci } 17432c593315Sopenharmony_ci if (rel_query.empty()) { 17442c593315Sopenharmony_ci if (!base_query.empty()) { 17452c593315Sopenharmony_ci *p++ = '?'; 17462c593315Sopenharmony_ci p = std::copy(std::begin(base_query), std::end(base_query), p); 17472c593315Sopenharmony_ci } 17482c593315Sopenharmony_ci *p = '\0'; 17492c593315Sopenharmony_ci return StringRef{res.base, p}; 17502c593315Sopenharmony_ci } 17512c593315Sopenharmony_ci *p++ = '?'; 17522c593315Sopenharmony_ci p = std::copy(std::begin(rel_query), std::end(rel_query), p); 17532c593315Sopenharmony_ci *p = '\0'; 17542c593315Sopenharmony_ci return StringRef{res.base, p}; 17552c593315Sopenharmony_ci } 17562c593315Sopenharmony_ci 17572c593315Sopenharmony_ci auto first = std::begin(rel_path); 17582c593315Sopenharmony_ci auto last = std::end(rel_path); 17592c593315Sopenharmony_ci 17602c593315Sopenharmony_ci if (rel_path[0] == '/') { 17612c593315Sopenharmony_ci *p++ = '/'; 17622c593315Sopenharmony_ci ++first; 17632c593315Sopenharmony_ci for (; first != last && *first == '/'; ++first) 17642c593315Sopenharmony_ci ; 17652c593315Sopenharmony_ci } else if (base_path.empty()) { 17662c593315Sopenharmony_ci *p++ = '/'; 17672c593315Sopenharmony_ci } else { 17682c593315Sopenharmony_ci p = std::copy(std::begin(base_path), std::end(base_path), p); 17692c593315Sopenharmony_ci } 17702c593315Sopenharmony_ci 17712c593315Sopenharmony_ci for (; first != last;) { 17722c593315Sopenharmony_ci if (*first == '.') { 17732c593315Sopenharmony_ci if (first + 1 == last) { 17742c593315Sopenharmony_ci if (*(p - 1) != '/') { 17752c593315Sopenharmony_ci p = eat_file(res.base, p); 17762c593315Sopenharmony_ci } 17772c593315Sopenharmony_ci break; 17782c593315Sopenharmony_ci } 17792c593315Sopenharmony_ci if (*(first + 1) == '/') { 17802c593315Sopenharmony_ci if (*(p - 1) != '/') { 17812c593315Sopenharmony_ci p = eat_file(res.base, p); 17822c593315Sopenharmony_ci } 17832c593315Sopenharmony_ci first += 2; 17842c593315Sopenharmony_ci continue; 17852c593315Sopenharmony_ci } 17862c593315Sopenharmony_ci if (*(first + 1) == '.') { 17872c593315Sopenharmony_ci if (first + 2 == last) { 17882c593315Sopenharmony_ci p = eat_dir(res.base, p); 17892c593315Sopenharmony_ci break; 17902c593315Sopenharmony_ci } 17912c593315Sopenharmony_ci if (*(first + 2) == '/') { 17922c593315Sopenharmony_ci p = eat_dir(res.base, p); 17932c593315Sopenharmony_ci first += 3; 17942c593315Sopenharmony_ci continue; 17952c593315Sopenharmony_ci } 17962c593315Sopenharmony_ci } 17972c593315Sopenharmony_ci } 17982c593315Sopenharmony_ci if (*(p - 1) != '/') { 17992c593315Sopenharmony_ci p = eat_file(res.base, p); 18002c593315Sopenharmony_ci } 18012c593315Sopenharmony_ci auto slash = std::find(first, last, '/'); 18022c593315Sopenharmony_ci if (slash == last) { 18032c593315Sopenharmony_ci p = std::copy(first, last, p); 18042c593315Sopenharmony_ci break; 18052c593315Sopenharmony_ci } 18062c593315Sopenharmony_ci p = std::copy(first, slash + 1, p); 18072c593315Sopenharmony_ci first = slash + 1; 18082c593315Sopenharmony_ci for (; first != last && *first == '/'; ++first) 18092c593315Sopenharmony_ci ; 18102c593315Sopenharmony_ci } 18112c593315Sopenharmony_ci if (!rel_query.empty()) { 18122c593315Sopenharmony_ci *p++ = '?'; 18132c593315Sopenharmony_ci p = std::copy(std::begin(rel_query), std::end(rel_query), p); 18142c593315Sopenharmony_ci } 18152c593315Sopenharmony_ci *p = '\0'; 18162c593315Sopenharmony_ci return StringRef{res.base, p}; 18172c593315Sopenharmony_ci} 18182c593315Sopenharmony_ci 18192c593315Sopenharmony_ciStringRef normalize_path(BlockAllocator &balloc, const StringRef &path, 18202c593315Sopenharmony_ci const StringRef &query) { 18212c593315Sopenharmony_ci // First, decode %XX for unreserved characters, then do 18222c593315Sopenharmony_ci // http2::path_join 18232c593315Sopenharmony_ci 18242c593315Sopenharmony_ci // We won't find %XX if length is less than 3. 18252c593315Sopenharmony_ci if (path.size() < 3 || 18262c593315Sopenharmony_ci std::find(std::begin(path), std::end(path), '%') == std::end(path)) { 18272c593315Sopenharmony_ci return path_join(balloc, StringRef{}, StringRef{}, path, query); 18282c593315Sopenharmony_ci } 18292c593315Sopenharmony_ci 18302c593315Sopenharmony_ci // includes last terminal NULL. 18312c593315Sopenharmony_ci auto result = make_byte_ref(balloc, path.size() + 1); 18322c593315Sopenharmony_ci auto p = result.base; 18332c593315Sopenharmony_ci 18342c593315Sopenharmony_ci auto it = std::begin(path); 18352c593315Sopenharmony_ci for (; it + 2 < std::end(path);) { 18362c593315Sopenharmony_ci if (*it == '%') { 18372c593315Sopenharmony_ci if (util::is_hex_digit(*(it + 1)) && util::is_hex_digit(*(it + 2))) { 18382c593315Sopenharmony_ci auto c = 18392c593315Sopenharmony_ci (util::hex_to_uint(*(it + 1)) << 4) + util::hex_to_uint(*(it + 2)); 18402c593315Sopenharmony_ci if (util::in_rfc3986_unreserved_chars(c)) { 18412c593315Sopenharmony_ci *p++ = c; 18422c593315Sopenharmony_ci 18432c593315Sopenharmony_ci it += 3; 18442c593315Sopenharmony_ci 18452c593315Sopenharmony_ci continue; 18462c593315Sopenharmony_ci } 18472c593315Sopenharmony_ci *p++ = '%'; 18482c593315Sopenharmony_ci *p++ = util::upcase(*(it + 1)); 18492c593315Sopenharmony_ci *p++ = util::upcase(*(it + 2)); 18502c593315Sopenharmony_ci 18512c593315Sopenharmony_ci it += 3; 18522c593315Sopenharmony_ci 18532c593315Sopenharmony_ci continue; 18542c593315Sopenharmony_ci } 18552c593315Sopenharmony_ci } 18562c593315Sopenharmony_ci *p++ = *it++; 18572c593315Sopenharmony_ci } 18582c593315Sopenharmony_ci 18592c593315Sopenharmony_ci p = std::copy(it, std::end(path), p); 18602c593315Sopenharmony_ci *p = '\0'; 18612c593315Sopenharmony_ci 18622c593315Sopenharmony_ci return path_join(balloc, StringRef{}, StringRef{}, StringRef{result.base, p}, 18632c593315Sopenharmony_ci query); 18642c593315Sopenharmony_ci} 18652c593315Sopenharmony_ci 18662c593315Sopenharmony_ciStringRef normalize_path_colon(BlockAllocator &balloc, const StringRef &path, 18672c593315Sopenharmony_ci const StringRef &query) { 18682c593315Sopenharmony_ci // First, decode %XX for unreserved characters and ':', then do 18692c593315Sopenharmony_ci // http2::path_join 18702c593315Sopenharmony_ci 18712c593315Sopenharmony_ci // We won't find %XX if length is less than 3. 18722c593315Sopenharmony_ci if (path.size() < 3 || 18732c593315Sopenharmony_ci std::find(std::begin(path), std::end(path), '%') == std::end(path)) { 18742c593315Sopenharmony_ci return path_join(balloc, StringRef{}, StringRef{}, path, query); 18752c593315Sopenharmony_ci } 18762c593315Sopenharmony_ci 18772c593315Sopenharmony_ci // includes last terminal NULL. 18782c593315Sopenharmony_ci auto result = make_byte_ref(balloc, path.size() + 1); 18792c593315Sopenharmony_ci auto p = result.base; 18802c593315Sopenharmony_ci 18812c593315Sopenharmony_ci auto it = std::begin(path); 18822c593315Sopenharmony_ci for (; it + 2 < std::end(path);) { 18832c593315Sopenharmony_ci if (*it == '%') { 18842c593315Sopenharmony_ci if (util::is_hex_digit(*(it + 1)) && util::is_hex_digit(*(it + 2))) { 18852c593315Sopenharmony_ci auto c = 18862c593315Sopenharmony_ci (util::hex_to_uint(*(it + 1)) << 4) + util::hex_to_uint(*(it + 2)); 18872c593315Sopenharmony_ci if (util::in_rfc3986_unreserved_chars(c) || c == ':') { 18882c593315Sopenharmony_ci *p++ = c; 18892c593315Sopenharmony_ci 18902c593315Sopenharmony_ci it += 3; 18912c593315Sopenharmony_ci 18922c593315Sopenharmony_ci continue; 18932c593315Sopenharmony_ci } 18942c593315Sopenharmony_ci *p++ = '%'; 18952c593315Sopenharmony_ci *p++ = util::upcase(*(it + 1)); 18962c593315Sopenharmony_ci *p++ = util::upcase(*(it + 2)); 18972c593315Sopenharmony_ci 18982c593315Sopenharmony_ci it += 3; 18992c593315Sopenharmony_ci 19002c593315Sopenharmony_ci continue; 19012c593315Sopenharmony_ci } 19022c593315Sopenharmony_ci } 19032c593315Sopenharmony_ci *p++ = *it++; 19042c593315Sopenharmony_ci } 19052c593315Sopenharmony_ci 19062c593315Sopenharmony_ci p = std::copy(it, std::end(path), p); 19072c593315Sopenharmony_ci *p = '\0'; 19082c593315Sopenharmony_ci 19092c593315Sopenharmony_ci return path_join(balloc, StringRef{}, StringRef{}, StringRef{result.base, p}, 19102c593315Sopenharmony_ci query); 19112c593315Sopenharmony_ci} 19122c593315Sopenharmony_ci 19132c593315Sopenharmony_cistd::string normalize_path(const StringRef &path, const StringRef &query) { 19142c593315Sopenharmony_ci BlockAllocator balloc(1024, 1024); 19152c593315Sopenharmony_ci 19162c593315Sopenharmony_ci return normalize_path(balloc, path, query).str(); 19172c593315Sopenharmony_ci} 19182c593315Sopenharmony_ci 19192c593315Sopenharmony_ciStringRef rewrite_clean_path(BlockAllocator &balloc, const StringRef &src) { 19202c593315Sopenharmony_ci if (src.empty() || src[0] != '/') { 19212c593315Sopenharmony_ci return src; 19222c593315Sopenharmony_ci } 19232c593315Sopenharmony_ci // probably, not necessary most of the case, but just in case. 19242c593315Sopenharmony_ci auto fragment = std::find(std::begin(src), std::end(src), '#'); 19252c593315Sopenharmony_ci auto raw_query = std::find(std::begin(src), fragment, '?'); 19262c593315Sopenharmony_ci auto query = raw_query; 19272c593315Sopenharmony_ci if (query != fragment) { 19282c593315Sopenharmony_ci ++query; 19292c593315Sopenharmony_ci } 19302c593315Sopenharmony_ci return normalize_path(balloc, StringRef{std::begin(src), raw_query}, 19312c593315Sopenharmony_ci StringRef{query, fragment}); 19322c593315Sopenharmony_ci} 19332c593315Sopenharmony_ci 19342c593315Sopenharmony_ciStringRef copy_lower(BlockAllocator &balloc, const StringRef &src) { 19352c593315Sopenharmony_ci auto iov = make_byte_ref(balloc, src.size() + 1); 19362c593315Sopenharmony_ci auto p = iov.base; 19372c593315Sopenharmony_ci p = std::copy(std::begin(src), std::end(src), p); 19382c593315Sopenharmony_ci *p = '\0'; 19392c593315Sopenharmony_ci util::inp_strlower(iov.base, p); 19402c593315Sopenharmony_ci return StringRef{iov.base, p}; 19412c593315Sopenharmony_ci} 19422c593315Sopenharmony_ci 19432c593315Sopenharmony_cibool contains_trailers(const StringRef &s) { 19442c593315Sopenharmony_ci constexpr auto trailers = StringRef::from_lit("trailers"); 19452c593315Sopenharmony_ci 19462c593315Sopenharmony_ci for (auto p = std::begin(s), end = std::end(s);; ++p) { 19472c593315Sopenharmony_ci p = std::find_if(p, end, [](char c) { return c != ' ' && c != '\t'; }); 19482c593315Sopenharmony_ci if (p == end || static_cast<size_t>(end - p) < trailers.size()) { 19492c593315Sopenharmony_ci return false; 19502c593315Sopenharmony_ci } 19512c593315Sopenharmony_ci if (util::strieq(trailers, StringRef{p, p + trailers.size()})) { 19522c593315Sopenharmony_ci // Make sure that there is no character other than white spaces 19532c593315Sopenharmony_ci // before next "," or end of string. 19542c593315Sopenharmony_ci p = std::find_if(p + trailers.size(), end, 19552c593315Sopenharmony_ci [](char c) { return c != ' ' && c != '\t'; }); 19562c593315Sopenharmony_ci if (p == end || *p == ',') { 19572c593315Sopenharmony_ci return true; 19582c593315Sopenharmony_ci } 19592c593315Sopenharmony_ci } 19602c593315Sopenharmony_ci // Skip to next ",". 19612c593315Sopenharmony_ci p = std::find_if(p, end, [](char c) { return c == ','; }); 19622c593315Sopenharmony_ci if (p == end) { 19632c593315Sopenharmony_ci return false; 19642c593315Sopenharmony_ci } 19652c593315Sopenharmony_ci } 19662c593315Sopenharmony_ci} 19672c593315Sopenharmony_ci 19682c593315Sopenharmony_ciStringRef make_websocket_accept_token(uint8_t *dest, const StringRef &key) { 19692c593315Sopenharmony_ci static constexpr uint8_t magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 19702c593315Sopenharmony_ci std::array<uint8_t, base64::encode_length(16) + str_size(magic)> s; 19712c593315Sopenharmony_ci auto p = std::copy(std::begin(key), std::end(key), std::begin(s)); 19722c593315Sopenharmony_ci std::copy_n(magic, str_size(magic), p); 19732c593315Sopenharmony_ci 19742c593315Sopenharmony_ci std::array<uint8_t, 20> h; 19752c593315Sopenharmony_ci if (util::sha1(h.data(), StringRef{std::begin(s), std::end(s)}) != 0) { 19762c593315Sopenharmony_ci return StringRef{}; 19772c593315Sopenharmony_ci } 19782c593315Sopenharmony_ci 19792c593315Sopenharmony_ci auto end = base64::encode(std::begin(h), std::end(h), dest); 19802c593315Sopenharmony_ci return StringRef{dest, end}; 19812c593315Sopenharmony_ci} 19822c593315Sopenharmony_ci 19832c593315Sopenharmony_cibool legacy_http1(int major, int minor) { 19842c593315Sopenharmony_ci return major <= 0 || (major == 1 && minor == 0); 19852c593315Sopenharmony_ci} 19862c593315Sopenharmony_ci 19872c593315Sopenharmony_cibool check_transfer_encoding(const StringRef &s) { 19882c593315Sopenharmony_ci if (s.empty()) { 19892c593315Sopenharmony_ci return false; 19902c593315Sopenharmony_ci } 19912c593315Sopenharmony_ci 19922c593315Sopenharmony_ci auto it = std::begin(s); 19932c593315Sopenharmony_ci 19942c593315Sopenharmony_ci for (;;) { 19952c593315Sopenharmony_ci // token 19962c593315Sopenharmony_ci if (!util::in_token(*it)) { 19972c593315Sopenharmony_ci return false; 19982c593315Sopenharmony_ci } 19992c593315Sopenharmony_ci 20002c593315Sopenharmony_ci ++it; 20012c593315Sopenharmony_ci 20022c593315Sopenharmony_ci for (; it != std::end(s) && util::in_token(*it); ++it) 20032c593315Sopenharmony_ci ; 20042c593315Sopenharmony_ci 20052c593315Sopenharmony_ci if (it == std::end(s)) { 20062c593315Sopenharmony_ci return true; 20072c593315Sopenharmony_ci } 20082c593315Sopenharmony_ci 20092c593315Sopenharmony_ci for (;;) { 20102c593315Sopenharmony_ci // OWS 20112c593315Sopenharmony_ci it = skip_lws(it, std::end(s)); 20122c593315Sopenharmony_ci if (it == std::end(s)) { 20132c593315Sopenharmony_ci return false; 20142c593315Sopenharmony_ci } 20152c593315Sopenharmony_ci 20162c593315Sopenharmony_ci if (*it == ',') { 20172c593315Sopenharmony_ci ++it; 20182c593315Sopenharmony_ci 20192c593315Sopenharmony_ci it = skip_lws(it, std::end(s)); 20202c593315Sopenharmony_ci if (it == std::end(s)) { 20212c593315Sopenharmony_ci return false; 20222c593315Sopenharmony_ci } 20232c593315Sopenharmony_ci 20242c593315Sopenharmony_ci break; 20252c593315Sopenharmony_ci } 20262c593315Sopenharmony_ci 20272c593315Sopenharmony_ci if (*it != ';') { 20282c593315Sopenharmony_ci return false; 20292c593315Sopenharmony_ci } 20302c593315Sopenharmony_ci 20312c593315Sopenharmony_ci ++it; 20322c593315Sopenharmony_ci 20332c593315Sopenharmony_ci // transfer-parameter follows 20342c593315Sopenharmony_ci 20352c593315Sopenharmony_ci // OWS 20362c593315Sopenharmony_ci it = skip_lws(it, std::end(s)); 20372c593315Sopenharmony_ci if (it == std::end(s)) { 20382c593315Sopenharmony_ci return false; 20392c593315Sopenharmony_ci } 20402c593315Sopenharmony_ci 20412c593315Sopenharmony_ci // token 20422c593315Sopenharmony_ci if (!util::in_token(*it)) { 20432c593315Sopenharmony_ci return false; 20442c593315Sopenharmony_ci } 20452c593315Sopenharmony_ci 20462c593315Sopenharmony_ci ++it; 20472c593315Sopenharmony_ci 20482c593315Sopenharmony_ci for (; it != std::end(s) && util::in_token(*it); ++it) 20492c593315Sopenharmony_ci ; 20502c593315Sopenharmony_ci 20512c593315Sopenharmony_ci if (it == std::end(s)) { 20522c593315Sopenharmony_ci return false; 20532c593315Sopenharmony_ci } 20542c593315Sopenharmony_ci 20552c593315Sopenharmony_ci // No BWS allowed 20562c593315Sopenharmony_ci if (*it != '=') { 20572c593315Sopenharmony_ci return false; 20582c593315Sopenharmony_ci } 20592c593315Sopenharmony_ci 20602c593315Sopenharmony_ci ++it; 20612c593315Sopenharmony_ci 20622c593315Sopenharmony_ci if (util::in_token(*it)) { 20632c593315Sopenharmony_ci // token 20642c593315Sopenharmony_ci ++it; 20652c593315Sopenharmony_ci 20662c593315Sopenharmony_ci for (; it != std::end(s) && util::in_token(*it); ++it) 20672c593315Sopenharmony_ci ; 20682c593315Sopenharmony_ci } else if (*it == '"') { 20692c593315Sopenharmony_ci // quoted-string 20702c593315Sopenharmony_ci ++it; 20712c593315Sopenharmony_ci 20722c593315Sopenharmony_ci it = skip_to_right_dquote(it, std::end(s)); 20732c593315Sopenharmony_ci if (it == std::end(s)) { 20742c593315Sopenharmony_ci return false; 20752c593315Sopenharmony_ci } 20762c593315Sopenharmony_ci 20772c593315Sopenharmony_ci ++it; 20782c593315Sopenharmony_ci } else { 20792c593315Sopenharmony_ci return false; 20802c593315Sopenharmony_ci } 20812c593315Sopenharmony_ci 20822c593315Sopenharmony_ci if (it == std::end(s)) { 20832c593315Sopenharmony_ci return true; 20842c593315Sopenharmony_ci } 20852c593315Sopenharmony_ci } 20862c593315Sopenharmony_ci } 20872c593315Sopenharmony_ci} 20882c593315Sopenharmony_ci 20892c593315Sopenharmony_ci} // namespace http2 20902c593315Sopenharmony_ci 20912c593315Sopenharmony_ci} // namespace nghttp2 2092