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