diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-11 16:46:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-11 16:46:30 +0000 |
commit | 8e1187a02b785e56d798660a9a292ca385e1f6aa (patch) | |
tree | b035593aa2ae37c25aeb28b537a3223c52532ab1 /src | |
parent | Adding upstream version 1.61.0. (diff) | |
download | nghttp2-8e1187a02b785e56d798660a9a292ca385e1f6aa.tar.xz nghttp2-8e1187a02b785e56d798660a9a292ca385e1f6aa.zip |
Adding upstream version 1.62.1.upstream/1.62.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src')
74 files changed, 3720 insertions, 4386 deletions
diff --git a/src/HtmlParser.cc b/src/HtmlParser.cc index 591c4c7..a420c93 100644 --- a/src/HtmlParser.cc +++ b/src/HtmlParser.cc @@ -58,11 +58,11 @@ StringRef get_attr(const xmlChar **attrs, const StringRef &name) { namespace { ResourceType get_resource_type_for_preload_as(const StringRef &attribute_value) { - if (util::strieq_l("image", attribute_value)) { + if (util::strieq("image"_sr, attribute_value)) { return REQ_IMG; - } else if (util::strieq_l("style", attribute_value)) { + } else if (util::strieq("style"_sr, attribute_value)) { return REQ_CSS; - } else if (util::strieq_l("script", attribute_value)) { + } else if (util::strieq("script"_sr, attribute_value)) { return REQ_UNBLOCK_JS; } else { return REQ_OTHERS; @@ -74,7 +74,7 @@ namespace { void add_link(ParserData *parser_data, const StringRef &uri, ResourceType res_type) { auto u = xmlBuildURI( - reinterpret_cast<const xmlChar *>(uri.c_str()), + reinterpret_cast<const xmlChar *>(uri.data()), reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str())); if (u) { parser_data->links.push_back( @@ -90,35 +90,35 @@ void start_element_func(void *user_data, const xmlChar *src_name, auto parser_data = static_cast<ParserData *>(user_data); auto name = StringRef{src_name, strlen(reinterpret_cast<const char *>(src_name))}; - if (util::strieq_l("head", name)) { + if (util::strieq("head"_sr, name)) { ++parser_data->inside_head; } - if (util::strieq_l("link", name)) { - auto rel_attr = get_attr(attrs, StringRef::from_lit("rel")); - auto href_attr = get_attr(attrs, StringRef::from_lit("href")); + if (util::strieq("link"_sr, name)) { + auto rel_attr = get_attr(attrs, "rel"_sr); + auto href_attr = get_attr(attrs, "href"_sr); if (rel_attr.empty() || href_attr.empty()) { return; } - if (util::strieq_l("shortcut icon", rel_attr)) { + if (util::strieq("shortcut icon"_sr, rel_attr)) { add_link(parser_data, href_attr, REQ_OTHERS); - } else if (util::strieq_l("stylesheet", rel_attr)) { + } else if (util::strieq("stylesheet"_sr, rel_attr)) { add_link(parser_data, href_attr, REQ_CSS); - } else if (util::strieq_l("preload", rel_attr)) { - auto as_attr = get_attr(attrs, StringRef::from_lit("as")); + } else if (util::strieq("preload"_sr, rel_attr)) { + auto as_attr = get_attr(attrs, "as"_sr); if (as_attr.empty()) { return; } add_link(parser_data, href_attr, get_resource_type_for_preload_as(as_attr)); } - } else if (util::strieq_l("img", name)) { - auto src_attr = get_attr(attrs, StringRef::from_lit("src")); + } else if (util::strieq("img"_sr, name)) { + auto src_attr = get_attr(attrs, "src"_sr); if (src_attr.empty()) { return; } add_link(parser_data, src_attr, REQ_IMG); - } else if (util::strieq_l("script", name)) { - auto src_attr = get_attr(attrs, StringRef::from_lit("src")); + } else if (util::strieq("script"_sr, name)) { + auto src_attr = get_attr(attrs, "src"_sr); if (src_attr.empty()) { return; } @@ -134,8 +134,8 @@ void start_element_func(void *user_data, const xmlChar *src_name, namespace { void end_element_func(void *user_data, const xmlChar *name) { auto parser_data = static_cast<ParserData *>(user_data); - if (util::strieq_l( - "head", + if (util::strieq( + "head"_sr, StringRef{name, strlen(reinterpret_cast<const char *>(name))})) { --parser_data->inside_head; } diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 6b28d1b..fb7b1db 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -78,9 +78,8 @@ namespace nghttp2 { namespace { // TODO could be constexpr -constexpr auto DEFAULT_HTML = StringRef::from_lit("index.html"); -constexpr auto NGHTTPD_SERVER = - StringRef::from_lit("nghttpd nghttp2/" NGHTTP2_VERSION); +constexpr auto DEFAULT_HTML = "index.html"_sr; +constexpr auto NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION ""_sr; } // namespace namespace { @@ -925,28 +924,32 @@ int Http2Handler::submit_file_response(const StringRef &status, Stream *stream, const std::string *content_type, nghttp2_data_provider2 *data_prd) { std::string last_modified_str; - auto nva = make_array(http2::make_nv_ls_nocopy(":status", status), - http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER), - http2::make_nv_ll("cache-control", "max-age=3600"), - http2::make_nv_ls("date", sessions_->get_cached_date()), - http2::make_nv_ll("", ""), http2::make_nv_ll("", ""), - http2::make_nv_ll("", ""), http2::make_nv_ll("", "")); + auto nva = std::to_array({ + http2::make_field(":status"_sr, status), + http2::make_field("server"_sr, NGHTTPD_SERVER), + http2::make_field("cache-control"_sr, "max-age=3600"_sr), + http2::make_field_v("date"_sr, sessions_->get_cached_date()), + {}, + {}, + {}, + {}, + }); size_t nvlen = 4; if (!get_config()->no_content_length) { - nva[nvlen++] = http2::make_nv_ls_nocopy( - "content-length", + nva[nvlen++] = http2::make_field( + "content-length"_sr, util::make_string_ref_uint(stream->balloc, file_length)); } if (last_modified != 0) { last_modified_str = util::http_date(last_modified); - nva[nvlen++] = http2::make_nv_ls("last-modified", last_modified_str); + nva[nvlen++] = http2::make_field_v("last-modified"_sr, last_modified_str); } if (content_type) { - nva[nvlen++] = http2::make_nv_ls("content-type", *content_type); + nva[nvlen++] = http2::make_field_v("content-type"_sr, *content_type); } auto &trailer_names = get_config()->trailer_names; if (!trailer_names.empty()) { - nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names); + nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names); } return nghttp2_submit_response2(session_, stream->stream_id, nva.data(), nvlen, data_prd); @@ -957,19 +960,20 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, nghttp2_data_provider2 *data_prd) { auto nva = std::vector<nghttp2_nv>(); nva.reserve(4 + headers.size()); - nva.push_back(http2::make_nv_ls_nocopy(":status", status)); - nva.push_back(http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER)); - nva.push_back(http2::make_nv_ls("date", sessions_->get_cached_date())); + nva.push_back(http2::make_field(":status"_sr, status)); + nva.push_back(http2::make_field("server"_sr, NGHTTPD_SERVER)); + nva.push_back(http2::make_field_v("date"_sr, sessions_->get_cached_date())); if (data_prd) { auto &trailer_names = get_config()->trailer_names; if (!trailer_names.empty()) { - nva.push_back(http2::make_nv_ls_nocopy("trailer", trailer_names)); + nva.push_back(http2::make_field("trailer"_sr, trailer_names)); } } for (auto &nv : headers) { - nva.push_back(http2::make_nv_nocopy(nv.name, nv.value, nv.no_index)); + nva.push_back( + http2::make_field(nv.name, nv.value, http2::no_index(nv.no_index))); } int r = nghttp2_submit_response2(session_, stream_id, nva.data(), nva.size(), data_prd); @@ -978,16 +982,18 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, nghttp2_data_provider2 *data_prd) { - auto nva = make_array(http2::make_nv_ls_nocopy(":status", status), - http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER), - http2::make_nv_ls("date", sessions_->get_cached_date()), - http2::make_nv_ll("", "")); + auto nva = std::to_array({ + http2::make_field(":status"_sr, status), + http2::make_field("server"_sr, NGHTTPD_SERVER), + http2::make_field_v("date"_sr, sessions_->get_cached_date()), + {}, + }); size_t nvlen = 3; if (data_prd) { auto &trailer_names = get_config()->trailer_names; if (!trailer_names.empty()) { - nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names); + nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names); } } @@ -997,7 +1003,7 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, int Http2Handler::submit_non_final_response(const std::string &status, int32_t stream_id) { - auto nva = make_array(http2::make_nv_ls(":status", status)); + auto nva = std::to_array({http2::make_field_v(":status"_sr, status)}); return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr, nva.data(), nva.size(), nullptr); } @@ -1010,13 +1016,12 @@ int Http2Handler::submit_push_promise(Stream *stream, authority = stream->header.host; } - auto scheme = get_config()->no_tls ? StringRef::from_lit("http") - : StringRef::from_lit("https"); + auto scheme = get_config()->no_tls ? "http"_sr : "https"_sr; - auto nva = make_array(http2::make_nv_ll(":method", "GET"), - http2::make_nv_ls_nocopy(":path", push_path), - http2::make_nv_ls_nocopy(":scheme", scheme), - http2::make_nv_ls_nocopy(":authority", authority)); + auto nva = std::to_array({http2::make_field(":method"_sr, "GET"_sr), + http2::make_field(":path"_sr, push_path), + http2::make_field(":scheme"_sr, scheme), + http2::make_field(":authority"_sr, authority)}); auto promised_stream_id = nghttp2_submit_push_promise( session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(), @@ -1029,7 +1034,7 @@ int Http2Handler::submit_push_promise(Stream *stream, auto promised_stream = std::make_unique<Stream>(this, promised_stream_id); auto &promised_header = promised_stream->header; - promised_header.method = StringRef::from_lit("GET"); + promised_header.method = "GET"_sr; promised_header.path = push_path; promised_header.scheme = scheme; promised_header.authority = @@ -1103,7 +1108,8 @@ nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id, std::vector<nghttp2_nv> nva; nva.reserve(config->trailer.size()); for (auto &kv : config->trailer) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + nva.push_back(http2::make_field_nv(kv.name, kv.value, + http2::no_index(kv.no_index))); } rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); if (rv != 0) { @@ -1140,10 +1146,9 @@ void prepare_status_response(Stream *stream, Http2Handler *hd, int status) { HeaderRefs headers; headers.reserve(2); - headers.emplace_back(StringRef::from_lit("content-type"), - StringRef::from_lit("text/html; charset=UTF-8")); + headers.emplace_back("content-type"_sr, "text/html; charset=UTF-8"_sr); headers.emplace_back( - StringRef::from_lit("content-length"), + "content-length"_sr, util::make_string_ref_uint(stream->balloc, file_ent->length)); hd->submit_response(StringRef{status_page->status}, stream->stream_id, headers, &data_prd); @@ -1167,15 +1172,13 @@ void prepare_echo_response(Stream *stream, Http2Handler *hd) { data_prd.read_callback = file_read_callback; HeaderRefs headers; - headers.emplace_back(StringRef::from_lit("nghttpd-response"), - StringRef::from_lit("echo")); + headers.emplace_back("nghttpd-response"_sr, "echo"_sr); if (!hd->get_config()->no_content_length) { - headers.emplace_back(StringRef::from_lit("content-length"), + headers.emplace_back("content-length"_sr, util::make_string_ref_uint(stream->balloc, length)); } - hd->submit_response(StringRef::from_lit("200"), stream->stream_id, headers, - &data_prd); + hd->submit_response("200"_sr, stream->stream_id, headers, &data_prd); } } // namespace @@ -1209,10 +1212,10 @@ void prepare_redirect_response(Stream *stream, Http2Handler *hd, authority = stream->header.host; } - auto location = concat_string_ref( - stream->balloc, scheme, StringRef::from_lit("://"), authority, path); + auto location = + concat_string_ref(stream->balloc, scheme, "://"_sr, authority, path); - auto headers = HeaderRefs{{StringRef::from_lit("location"), location}}; + auto headers = HeaderRefs{{"location"_sr, location}}; auto sessions = hd->get_sessions(); auto status_page = sessions->get_server()->get_status_page(status); @@ -1245,8 +1248,8 @@ void prepare_response(Stream *stream, Http2Handler *hd, auto query_pos = std::find(std::begin(reqpath), std::end(reqpath), '?'); if (query_pos != std::end(reqpath)) { // Do not response to this request to allow clients to test timeouts. - if (util::streq_l("nghttpd_do_not_respond_to_req=yes", - StringRef{query_pos, std::end(reqpath)})) { + if ("nghttpd_do_not_respond_to_req=yes"_sr == + StringRef{query_pos, std::end(reqpath)}) { return; } raw_path = StringRef{std::begin(reqpath), query_pos}; @@ -1278,7 +1281,7 @@ void prepare_response(Stream *stream, Http2Handler *hd, } if (!hd->get_config()->push.empty()) { - auto push_itr = hd->get_config()->push.find(path.str()); + auto push_itr = hd->get_config()->push.find(std::string{path}); if (allow_push && push_itr != std::end(hd->get_config()->push)) { for (auto &push_path : (*push_itr).second) { rv = hd->submit_push_promise(stream, StringRef{push_path}); @@ -1339,8 +1342,8 @@ void prepare_response(Stream *stream, Http2Handler *hd, if (buf.st_mode & S_IFDIR) { close(file); - auto reqpath = concat_string_ref(stream->balloc, raw_path, - StringRef::from_lit("/"), raw_query); + auto reqpath = + concat_string_ref(stream->balloc, raw_path, "/"_sr, raw_query); prepare_redirect_response(stream, hd, reqpath, 301); @@ -1370,16 +1373,15 @@ void prepare_response(Stream *stream, Http2Handler *hd, stream->file_ent = file_ent; if (last_mod_found && file_ent->mtime <= last_mod) { - hd->submit_response(StringRef::from_lit("304"), stream->stream_id, nullptr); + hd->submit_response("304"_sr, stream->stream_id, nullptr); return; } auto method = stream->header.method; - if (method == StringRef::from_lit("HEAD")) { - hd->submit_file_response(StringRef::from_lit("200"), stream, - file_ent->mtime, file_ent->length, - file_ent->content_type, nullptr); + if (method == "HEAD"_sr) { + hd->submit_file_response("200"_sr, stream, file_ent->mtime, + file_ent->length, file_ent->content_type, nullptr); return; } @@ -1390,8 +1392,8 @@ void prepare_response(Stream *stream, Http2Handler *hd, data_prd.source.fd = file_ent->fd; data_prd.read_callback = file_read_callback; - hd->submit_file_response(StringRef::from_lit("200"), stream, file_ent->mtime, - file_ent->length, file_ent->content_type, &data_prd); + hd->submit_file_response("200"_sr, stream, file_ent->mtime, file_ent->length, + file_ent->content_type, &data_prd); } } // namespace @@ -1425,7 +1427,7 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, stream->header_buffer_size += namebuf.len + valuebuf.len; - auto token = http2::lookup_token(namebuf.base, namebuf.len); + auto token = http2::lookup_token(StringRef{namebuf.base, namebuf.len}); auto &header = stream->header; @@ -1528,14 +1530,13 @@ int hd_on_frame_recv_callback(nghttp2_session *session, auto expect100 = stream->header.expect; - if (util::strieq_l("100-continue", expect100)) { + if (util::strieq("100-continue"_sr, expect100)) { hd->submit_non_final_response("100", frame->hd.stream_id); } auto method = stream->header.method; if (hd->get_config()->echo_upload && - (method == StringRef::from_lit("POST") || - method == StringRef::from_lit("PUT"))) { + (method == "POST"_sr || method == "PUT"_sr)) { if (!prepare_upload_temp_store(stream, hd)) { hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR); return 0; @@ -2129,7 +2130,8 @@ int HttpServer::run() { return -1; } - if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST) == 0) { + if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST.data()) == + 0) { std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl; return -1; } diff --git a/src/HttpServer.h b/src/HttpServer.h index 00fd6bf..348f85a 100644 --- a/src/HttpServer.h +++ b/src/HttpServer.h @@ -245,9 +245,10 @@ private: const Config *config_; }; -ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t length, uint32_t *data_flags, - nghttp2_data_source *source, void *user_data); +nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id, + uint8_t *buf, size_t length, + uint32_t *data_flags, + nghttp2_data_source *source, void *user_data); } // namespace nghttp2 diff --git a/src/allocator.h b/src/allocator.h index 363ee91..b4dee5a 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -33,6 +33,7 @@ #include <cassert> #include <utility> +#include <span> #include "template.h" @@ -48,6 +49,18 @@ struct MemBlock { uint8_t *begin, *last, *end; }; +static_assert((sizeof(MemBlock) & 0xf) == 0); + +struct ChunkHead { + union { + size_t size; + uint64_t pad1; + }; + uint64_t pad2; +}; + +static_assert(sizeof(ChunkHead) == 16); + // BlockAllocator allocates memory block with given size at once, and // cuts the region from it when allocation is requested. If the // requested size is larger than given threshold (plus small internal @@ -88,7 +101,7 @@ struct BlockAllocator { void reset() { for (auto mb = retain; mb;) { auto next = mb->next; - delete[] reinterpret_cast<uint8_t *>(mb); + operator delete[](reinterpret_cast<uint8_t *>(mb), std::align_val_t(16)); mb = next; } @@ -97,36 +110,40 @@ struct BlockAllocator { } MemBlock *alloc_mem_block(size_t size) { - auto block = new uint8_t[sizeof(MemBlock) + size]; + auto block = new (std::align_val_t(16)) uint8_t[sizeof(MemBlock) + size]; auto mb = reinterpret_cast<MemBlock *>(block); mb->next = retain; - mb->begin = mb->last = block + sizeof(MemBlock); + mb->begin = mb->last = reinterpret_cast<uint8_t *>( + (reinterpret_cast<intptr_t>(block + sizeof(MemBlock)) + 0xf) & ~0xf); mb->end = mb->begin + size; retain = mb; return mb; } + constexpr size_t alloc_unit(size_t size) { return sizeof(ChunkHead) + size; } + void *alloc(size_t size) { - if (size + sizeof(size_t) >= isolation_threshold) { - auto len = std::max(static_cast<size_t>(16), size); + auto au = alloc_unit(size); + + if (au >= isolation_threshold) { + size = std::max(static_cast<size_t>(16), size); // We will store the allocated size in size_t field. - auto mb = alloc_mem_block(len + sizeof(size_t)); - auto sp = reinterpret_cast<size_t *>(mb->begin); - *sp = len; + auto mb = alloc_mem_block(alloc_unit(size)); + auto ch = reinterpret_cast<ChunkHead *>(mb->begin); + ch->size = size; mb->last = mb->end; - return mb->begin + sizeof(size_t); + return mb->begin + sizeof(ChunkHead); } - if (!head || - static_cast<size_t>(head->end - head->last) < size + sizeof(size_t)) { + if (!head || static_cast<size_t>(head->end - head->last) < au) { head = alloc_mem_block(block_size); } // We will store the allocated size in size_t field. - auto res = head->last + sizeof(size_t); - auto sp = reinterpret_cast<size_t *>(head->last); - *sp = size; + auto res = head->last + sizeof(ChunkHead); + auto ch = reinterpret_cast<ChunkHead *>(head->last); + ch->size = size; head->last = reinterpret_cast<uint8_t *>( (reinterpret_cast<intptr_t>(res + size) + 0xf) & ~0xf); @@ -137,8 +154,9 @@ struct BlockAllocator { // Returns allocated size for memory pointed by |ptr|. We assume // that |ptr| was returned from alloc() or realloc(). size_t get_alloc_length(void *ptr) { - return *reinterpret_cast<size_t *>(static_cast<uint8_t *>(ptr) - - sizeof(size_t)); + return reinterpret_cast<ChunkHead *>(static_cast<uint8_t *>(ptr) - + sizeof(ChunkHead)) + ->size; } // Allocates memory of at least |size| bytes. If |ptr| is nullptr, @@ -253,19 +271,10 @@ StringRef realloc_concat_string_ref(BlockAllocator &alloc, return StringRef{dst, len}; } -struct ByteRef { - // The pointer to the beginning of the buffer. - uint8_t *base; - // The length of the buffer. - size_t len; -}; - -// Makes a buffer with given size. The resulting byte string might -// not be NULL-terminated. +// Makes an uninitialized buffer with given size. template <typename BlockAllocator> -ByteRef make_byte_ref(BlockAllocator &alloc, size_t size) { - auto dst = static_cast<uint8_t *>(alloc.alloc(size)); - return {dst, size}; +std::span<uint8_t> make_byte_ref(BlockAllocator &alloc, size_t size) { + return {static_cast<uint8_t *>(alloc.alloc(size)), size}; } } // namespace nghttp2 diff --git a/src/app_helper.cc b/src/app_helper.cc index 666d16c..2ccecbe 100644 --- a/src/app_helper.cc +++ b/src/app_helper.cc @@ -115,7 +115,7 @@ std::string strframetype(uint8_t type) { } std::string s = "extension(0x"; - s += util::format_hex(&type, 1); + s += util::format_hex(std::span{&type, 1}); s += ')'; return s; @@ -329,7 +329,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) { case NGHTTP2_PING: print_frame_attr_indent(); fprintf(outfile, "(opaque_data=%s)\n", - util::format_hex(frame->ping.opaque_data, 8).c_str()); + util::format_hex(frame->ping.opaque_data).c_str()); break; case NGHTTP2_GOAWAY: print_frame_attr_indent(); diff --git a/src/base64.h b/src/base64.h index 1bd51af..8789427 100644 --- a/src/base64.h +++ b/src/base64.h @@ -204,18 +204,19 @@ template <typename InputIt> std::string decode(InputIt first, InputIt last) { } template <typename InputIt> -StringRef decode(BlockAllocator &balloc, InputIt first, InputIt last) { +std::span<const uint8_t> decode(BlockAllocator &balloc, InputIt first, + InputIt last) { auto len = std::distance(first, last); if (len % 4 != 0) { - return StringRef::from_lit(""); + return {}; } auto iov = make_byte_ref(balloc, len / 4 * 3 + 1); - auto p = iov.base; + auto p = std::begin(iov); p = decode(first, last, p); *p = '\0'; - return StringRef{iov.base, p}; + return {std::begin(iov), p}; } } // namespace base64 diff --git a/src/base64_test.cc b/src/base64_test.cc index 9ab770f..0aeadf7 100644 --- a/src/base64_test.cc +++ b/src/base64_test.cc @@ -33,6 +33,8 @@ #include "base64.h" +using namespace std::literals; + namespace nghttp2 { namespace { @@ -73,67 +75,68 @@ void test_base64_encode(void) { void test_base64_decode(void) { BlockAllocator balloc(4096, 4096); { - std::string in = "/w=="; + auto in = "/w=="sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("\xff", out); - assert_stdstring_equal( - "\xff", base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal("\xff"sv, out); + assert_stdsv_equal("\xff"sv, StringRef{base64::decode( + balloc, std::begin(in), std::end(in))}); } { - std::string in = "//4="; + auto in = "//4="sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("\xff\xfe", out); - assert_stdstring_equal( - "\xff\xfe", base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal("\xff\xfe"sv, out); + assert_stdsv_equal( + "\xff\xfe"sv, + StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } { - std::string in = "//79"; + auto in = "//79"sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("\xff\xfe\xfd", out); - assert_stdstring_equal( - "\xff\xfe\xfd", - base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal("\xff\xfe\xfd"sv, out); + assert_stdsv_equal( + "\xff\xfe\xfd"sv, + StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } { - std::string in = "//79/A=="; + auto in = "//79/A=="sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("\xff\xfe\xfd\xfc", out); - assert_stdstring_equal( - "\xff\xfe\xfd\xfc", - base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal("\xff\xfe\xfd\xfc"sv, out); + assert_stdsv_equal( + "\xff\xfe\xfd\xfc"sv, + StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } { // we check the number of valid input must be multiples of 4 - std::string in = "//79="; + auto in = "//79="sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("", out); - assert_stdstring_equal( - "", base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal(""sv, out); + assert_stdsv_equal( + ""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } { // ending invalid character at the boundary of multiples of 4 is // bad - std::string in = "bmdodHRw\n"; + auto in = "bmdodHRw\n"sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("", out); - assert_stdstring_equal( - "", base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal("", out); + assert_stdsv_equal( + ""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } { // after seeing '=', subsequent input must be also '='. - std::string in = "//79/A=A"; + auto in = "//79/A=A"sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("", out); - assert_stdstring_equal( - "", base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal(""sv, out); + assert_stdsv_equal( + ""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } { // additional '=' at the end is bad - std::string in = "//79/A======"; + auto in = "//79/A======"sv; auto out = base64::decode(std::begin(in), std::end(in)); - assert_stdstring_equal("", out); - assert_stdstring_equal( - "", base64::decode(balloc, std::begin(in), std::end(in)).str()); + assert_stdsv_equal(""sv, out); + assert_stdsv_equal( + ""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))}); } } diff --git a/src/deflatehd.cc b/src/deflatehd.cc index ad472de..e51bab1 100644 --- a/src/deflatehd.cc +++ b/src/deflatehd.cc @@ -403,21 +403,21 @@ int main(int argc, char **argv) { case 's': { // --table-size auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { fprintf(stderr, "-s: Bad option value\n"); exit(EXIT_FAILURE); } - config.table_size = n; + config.table_size = *n; break; } case 'S': { // --deflate-table-size auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { fprintf(stderr, "-S: Bad option value\n"); exit(EXIT_FAILURE); } - config.deflate_table_size = n; + config.deflate_table_size = *n; break; } case 'd': diff --git a/src/h2load.cc b/src/h2load.cc index 4f9f00e..43931f9 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -47,6 +47,7 @@ #include <thread> #include <future> #include <random> +#include <string_view> #include <openssl/err.h> @@ -826,6 +827,7 @@ void Client::process_request_failure() { << std::endl; } +#ifndef NGHTTP2_OPENSSL_IS_BORINGSSL namespace { void print_server_tmp_key(SSL *ssl) { EVP_PKEY *key; @@ -847,7 +849,7 @@ void print_server_tmp_key(SSL *ssl) { std::cout << "DH " << EVP_PKEY_bits(key) << " bits" << std::endl; break; case EVP_PKEY_EC: { -#if OPENSSL_3_0_0_API +# if OPENSSL_3_0_0_API std::array<char, 64> curve_name; const char *cname; if (!EVP_PKEY_get_utf8_string_param(key, "group", curve_name.data(), @@ -856,7 +858,7 @@ void print_server_tmp_key(SSL *ssl) { } else { cname = curve_name.data(); } -#else // !OPENSSL_3_0_0_API +# else // !OPENSSL_3_0_0_API auto ec = EVP_PKEY_get1_EC_KEY(key); auto ec_del = defer(EC_KEY_free, ec); auto nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); @@ -864,7 +866,7 @@ void print_server_tmp_key(SSL *ssl) { if (!cname) { cname = OBJ_nid2sn(nid); } -#endif // !OPENSSL_3_0_0_API +# endif // !OPENSSL_3_0_0_API std::cout << "ECDH " << cname << " " << EVP_PKEY_bits(key) << " bits" << std::endl; @@ -877,6 +879,7 @@ void print_server_tmp_key(SSL *ssl) { } } } // namespace +#endif // !NGHTTP2_OPENSSL_IS_BORINGSSL void Client::report_tls_info() { if (worker->id == 0 && !worker->tls_info_report_done) { @@ -884,7 +887,9 @@ void Client::report_tls_info() { auto cipher = SSL_get_current_cipher(ssl); std::cout << "TLS Protocol: " << tls::get_tls_protocol(ssl) << "\n" << "Cipher: " << SSL_CIPHER_get_name(cipher) << std::endl; +#ifndef NGHTTP2_OPENSSL_IS_BORINGSSL print_server_tmp_key(ssl); +#endif // !NGHTTP2_OPENSSL_IS_BORINGSSL } } @@ -927,7 +932,7 @@ void Client::on_header(int32_t stream_id, const uint8_t *name, size_t namelen, } if (stream.status_success == -1 && namelen == 7 && - util::streq_l(":status", name, namelen)) { + ":status"_sr == StringRef{name, namelen}) { int status = 0; for (size_t i = 0; i < valuelen; ++i) { if ('0' <= value[i] && value[i] <= '9') { @@ -1101,20 +1106,19 @@ int Client::connection_made() { if (config.is_quic()) { #ifdef ENABLE_HTTP3 assert(session); - if (!util::streq(StringRef{&NGHTTP3_ALPN_H3[1]}, proto) && - !util::streq_l("h3-29", proto)) { + if ("h3"_sr != proto && "h3-29"_sr != proto) { return -1; } #endif // ENABLE_HTTP3 } else if (util::check_h2_is_selected(proto)) { session = std::make_unique<Http2Session>(this); - } else if (util::streq(NGHTTP2_H1_1, proto)) { + } else if (NGHTTP2_H1_1 == proto) { session = std::make_unique<Http1Session>(this); } // Just assign next_proto to selected_proto anyway to show the // negotiation result. - selected_proto = proto.str(); + selected_proto = proto; } else if (config.is_quic()) { std::cerr << "QUIC requires ALPN negotiation" << std::endl; return -1; @@ -1123,11 +1127,11 @@ int Client::connection_made() { << std::endl; for (const auto &proto : config.alpn_list) { - if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{proto})) { + if (NGHTTP2_H1_1_ALPN == proto) { std::cout << "Server does not support ALPN. Falling back to HTTP/1.1." << std::endl; session = std::make_unique<Http1Session>(this); - selected_proto = NGHTTP2_H1_1.str(); + selected_proto = NGHTTP2_H1_1; break; } } @@ -1155,7 +1159,7 @@ int Client::connection_made() { break; case Config::PROTO_HTTP1_1: session = std::make_unique<Http1Session>(this); - selected_proto = NGHTTP2_H1_1.str(); + selected_proto = NGHTTP2_H1_1; break; default: // unreachable @@ -1861,7 +1865,7 @@ std::string get_reqline(const char *uri, const http_parser_url &u) { std::string reqline; if (util::has_uri_field(u, UF_PATH)) { - reqline = util::get_uri_field(uri, u, UF_PATH).str(); + reqline = util::get_uri_field(uri, u, UF_PATH); } else { reqline = "/"; } @@ -1876,20 +1880,20 @@ std::string get_reqline(const char *uri, const http_parser_url &u) { } // namespace namespace { -constexpr char UNIX_PATH_PREFIX[] = "unix:"; +constexpr auto UNIX_PATH_PREFIX = "unix:"_sr; } // namespace namespace { bool parse_base_uri(const StringRef &base_uri) { http_parser_url u{}; - if (http_parser_parse_url(base_uri.c_str(), base_uri.size(), 0, &u) != 0 || + if (http_parser_parse_url(base_uri.data(), base_uri.size(), 0, &u) != 0 || !util::has_uri_field(u, UF_SCHEMA) || !util::has_uri_field(u, UF_HOST)) { return false; } - config.scheme = util::get_uri_field(base_uri.c_str(), u, UF_SCHEMA).str(); - config.host = util::get_uri_field(base_uri.c_str(), u, UF_HOST).str(); - config.default_port = util::get_default_port(base_uri.c_str(), u); + config.scheme = util::get_uri_field(base_uri.data(), u, UF_SCHEMA); + config.host = util::get_uri_field(base_uri.data(), u, UF_HOST); + config.default_port = util::get_default_port(base_uri.data(), u); if (util::has_uri_field(u, UF_PORT)) { config.port = u.port; } else { @@ -2033,7 +2037,7 @@ namespace { int parse_header_table_size(uint32_t &dst, const char *opt, const char *optarg) { auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "--" << opt << ": Bad option value: " << optarg << std::endl; return -1; } @@ -2044,7 +2048,7 @@ int parse_header_table_size(uint32_t &dst, const char *opt, return -1; } - dst = n; + dst = *n; return 0; } @@ -2086,7 +2090,7 @@ benchmarking tool for HTTP/2 server)" } // namespace namespace { -constexpr char DEFAULT_ALPN_LIST[] = "h2,h2-16,h2-14,http/1.1"; +constexpr auto DEFAULT_ALPN_LIST = "h2,h2-16,h2-14,http/1.1"_sr; } // namespace namespace { @@ -2373,21 +2377,21 @@ int main(int argc, char **argv) { switch (c) { case 'n': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-n: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.nreqs = n; + config.nreqs = *n; nreqs_set_manually = true; break; } case 'c': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-c: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.nclients = n; + config.nclients = *n; break; } case 'd': @@ -2399,55 +2403,55 @@ int main(int argc, char **argv) { << "no threads created." << std::endl; #else auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-t: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.nthreads = n; + config.nthreads = *n; #endif // NOTHREADS break; } case 'm': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-m: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.max_concurrent_streams = n; + config.max_concurrent_streams = *n; break; } case 'w': case 'W': { auto n = util::parse_uint(optarg); - if (n == -1 || n > 30) { + if (!n || n > 30) { std::cerr << "-" << static_cast<char>(c) << ": specify the integer in the range [0, 30], inclusive" << std::endl; exit(EXIT_FAILURE); } if (c == 'w') { - config.window_bits = n; + config.window_bits = *n; } else { - config.connection_window_bits = n; + config.connection_window_bits = *n; } break; } case 'f': { auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "--max-frame-size: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - if (static_cast<uint64_t>(n) < 16_k) { + if (static_cast<uint64_t>(*n) < 16_k) { std::cerr << "--max-frame-size: minimum 16384" << std::endl; exit(EXIT_FAILURE); } - if (static_cast<uint64_t>(n) > 16_m - 1) { + if (static_cast<uint64_t>(*n) > 16_m - 1) { std::cerr << "--max-frame-size: maximum 16777215" << std::endl; exit(EXIT_FAILURE); } - config.max_frame_size = n; + config.max_frame_size = *n; break; } case 'H': { @@ -2481,8 +2485,7 @@ int main(int argc, char **argv) { break; case 'p': { auto proto = StringRef{optarg}; - if (util::strieq(StringRef::from_lit(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID), - proto)) { + if (util::strieq(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID ""_sr, proto)) { config.no_tls_proto = Config::PROTO_HTTP2; } else if (util::strieq(NGHTTP2_H1_1, proto)) { config.no_tls_proto = Config::PROTO_HTTP1_1; @@ -2494,7 +2497,7 @@ int main(int argc, char **argv) { } case 'r': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-r: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } @@ -2503,36 +2506,40 @@ int main(int argc, char **argv) { << "must be positive." << std::endl; exit(EXIT_FAILURE); } - config.rate = n; + config.rate = *n; break; } - case 'T': - config.conn_active_timeout = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.conn_active_timeout)) { + case 'T': { + auto d = util::parse_duration_with_unit(optarg); + if (!d) { std::cerr << "-T: bad value for the conn_active_timeout wait time: " << optarg << std::endl; exit(EXIT_FAILURE); } + config.conn_active_timeout = *d; break; - case 'N': - config.conn_inactivity_timeout = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.conn_inactivity_timeout)) { + } + case 'N': { + auto d = util::parse_duration_with_unit(optarg); + if (!d) { std::cerr << "-N: bad value for the conn_inactivity_timeout wait time: " << optarg << std::endl; exit(EXIT_FAILURE); } + config.conn_inactivity_timeout = *d; break; + } case 'B': { auto arg = StringRef{optarg}; config.base_uri = ""; config.base_uri_unix = false; - if (util::istarts_with_l(arg, UNIX_PATH_PREFIX)) { + if (util::istarts_with(arg, UNIX_PATH_PREFIX)) { // UNIX domain socket path sockaddr_un un; - auto path = StringRef{std::begin(arg) + str_size(UNIX_PATH_PREFIX), - std::end(arg)}; + auto path = + StringRef{std::begin(arg) + UNIX_PATH_PREFIX.size(), std::end(arg)}; if (path.size() == 0 || path.size() + 1 > sizeof(un.sun_path)) { std::cerr << "--base-uri: invalid UNIX domain socket path: " << arg @@ -2555,16 +2562,18 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - config.base_uri = arg.str(); + config.base_uri = arg; break; } - case 'D': - config.duration = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.duration)) { + case 'D': { + auto d = util::parse_duration_with_unit(optarg); + if (!d) { std::cerr << "-D: value error " << optarg << std::endl; exit(EXIT_FAILURE); } + config.duration = *d; break; + } case 'v': config.verbose = true; break; @@ -2589,18 +2598,19 @@ int main(int argc, char **argv) { config.ifile = optarg; config.timing_script = true; break; - case 5: + case 5: { // rate-period - config.rate_period = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.rate_period)) { + auto d = util::parse_duration_with_unit(optarg); + if (!d) { std::cerr << "--rate-period: value error " << optarg << std::endl; exit(EXIT_FAILURE); } + config.rate_period = *d; break; + } case 6: // --h1 - config.alpn_list = - util::parse_config_str_list(StringRef::from_lit("http/1.1")); + config.alpn_list = util::parse_config_str_list("http/1.1"_sr); config.no_tls_proto = Config::PROTO_HTTP1_1; break; case 7: @@ -2617,14 +2627,16 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } break; - case 9: + case 9: { // --warm-up-time - config.warm_up_time = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.warm_up_time)) { + auto d = util::parse_duration_with_unit(optarg); + if (!d) { std::cerr << "--warm-up-time: value error " << optarg << std::endl; exit(EXIT_FAILURE); } + config.warm_up_time = *d; break; + } case 10: // --log-file logfile = optarg; @@ -2634,11 +2646,12 @@ int main(int argc, char **argv) { auto p = util::split_hostport(StringRef{optarg}); int64_t port = 0; if (p.first.empty() || - (!p.second.empty() && (port = util::parse_uint(p.second)) == -1)) { + (!p.second.empty() && + (port = util::parse_uint(p.second).value_or(-1)) == -1)) { std::cerr << "--connect-to: Invalid value " << optarg << std::endl; exit(EXIT_FAILURE); } - config.connect_to_host = p.first.str(); + config.connect_to_host = p.first; config.connect_to_port = port; break; } @@ -2672,17 +2685,17 @@ int main(int argc, char **argv) { case 17: { // --max-udp-payload-size auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "--max-udp-payload-size: bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - if (static_cast<uint64_t>(n) > 64_k) { + if (static_cast<uint64_t>(*n) > 64_k) { std::cerr << "--max-udp-payload-size: must not exceed 65536" << std::endl; exit(EXIT_FAILURE); } - config.max_udp_payload_size = n; + config.max_udp_payload_size = *n; break; } case 18: @@ -2723,8 +2736,7 @@ int main(int argc, char **argv) { } if (config.alpn_list.empty()) { - config.alpn_list = - util::parse_config_str_list(StringRef::from_lit(DEFAULT_ALPN_LIST)); + config.alpn_list = util::parse_config_str_list(DEFAULT_ALPN_LIST); } // serialize the APLN tokens @@ -2991,8 +3003,8 @@ int main(int argc, char **argv) { shared_nva.emplace_back("user-agent", user_agent); // list header fields that can be overridden. - auto override_hdrs = make_array<std::string>(":authority", "host", ":method", - ":scheme", "user-agent"); + auto override_hdrs = std::to_array<std::string_view>( + {":authority", "host", ":method", ":scheme", "user-agent"}); for (auto &kv : config.custom_headers) { if (std::find(std::begin(override_hdrs), std::end(override_hdrs), @@ -3059,15 +3071,15 @@ int main(int argc, char **argv) { // 2 for :path, and possible content-length nva.reserve(2 + shared_nva.size()); - nva.push_back(http2::make_nv_ls(":path", req)); + nva.push_back(http2::make_field_v(":path"_sr, req)); for (auto &nv : shared_nva) { - nva.push_back(http2::make_nv(nv.name, nv.value, false)); + nva.push_back(http2::make_field_nv(nv.name, nv.value)); } if (!content_length_str.empty()) { - nva.push_back(http2::make_nv(StringRef::from_lit("content-length"), - StringRef{content_length_str})); + nva.push_back( + http2::make_field_nv("content-length"_sr, content_length_str)); } config.nva.push_back(std::move(nva)); diff --git a/src/h2load_quic.cc b/src/h2load_quic.cc index 8b3c552..5187ca0 100644 --- a/src/h2load_quic.cc +++ b/src/h2load_quic.cc @@ -646,17 +646,13 @@ int Client::write_quic() { } std::array<nghttp3_vec, 16> vec; - size_t pktcnt = 0; auto max_udp_payload_size = ngtcp2_conn_get_max_tx_udp_payload_size(quic.conn); -#ifdef UDP_SEGMENT auto path_max_udp_payload_size = ngtcp2_conn_get_path_max_tx_udp_payload_size(quic.conn); -#endif // UDP_SEGMENT - auto max_pktcnt = - std::max(ngtcp2_conn_get_send_quantum(quic.conn) / max_udp_payload_size, - static_cast<size_t>(1)); uint8_t *bufpos = quic.tx.data.get(); + auto bufleft = std::max(ngtcp2_conn_get_send_quantum(quic.conn), + path_max_udp_payload_size); ngtcp2_path_storage ps; size_t gso_size = 0; @@ -686,9 +682,11 @@ int Client::write_quic() { flags |= NGTCP2_WRITE_STREAM_FLAG_FIN; } + auto buflen = bufleft >= max_udp_payload_size ? max_udp_payload_size + : path_max_udp_payload_size; auto nwrite = ngtcp2_conn_writev_stream( - quic.conn, &ps.path, nullptr, bufpos, max_udp_payload_size, &ndatalen, - flags, stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt, ts); + quic.conn, &ps.path, nullptr, bufpos, buflen, &ndatalen, flags, + stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt, ts); if (nwrite < 0) { switch (nwrite) { case NGTCP2_ERR_STREAM_DATA_BLOCKED: @@ -730,7 +728,11 @@ int Client::write_quic() { return 0; } + auto first_pkt = bufpos == quic.tx.data.get(); + (void)first_pkt; + bufpos += nwrite; + bufleft -= nwrite; #ifdef UDP_SEGMENT if (worker->config->no_udp_gso) { @@ -745,7 +747,7 @@ int Client::write_quic() { return 0; } - if (++pktcnt == max_pktcnt) { + if (bufleft < path_max_udp_payload_size) { signal_write(); return 0; } @@ -758,7 +760,7 @@ int Client::write_quic() { #endif // UDP_SEGMENT #ifdef UDP_SEGMENT - if (pktcnt == 0) { + if (first_pkt) { gso_size = nwrite; } else if (static_cast<size_t>(nwrite) > gso_size || (gso_size > path_max_udp_payload_size && @@ -784,7 +786,8 @@ int Client::write_quic() { } // Assume that the path does not change. - if (++pktcnt == max_pktcnt || static_cast<size_t>(nwrite) < gso_size) { + if (bufleft < path_max_udp_payload_size || + static_cast<size_t>(nwrite) < gso_size) { auto data = quic.tx.data.get(); auto datalen = bufpos - quic.tx.data.get(); rv = write_udp(ps.path.remote.addr, ps.path.remote.addrlen, data, datalen, diff --git a/src/http2.cc b/src/http2.cc index 661c4c9..2815229 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -35,107 +35,107 @@ namespace http2 { StringRef get_reason_phrase(unsigned int status_code) { switch (status_code) { case 100: - return StringRef::from_lit("Continue"); + return "Continue"_sr; case 101: - return StringRef::from_lit("Switching Protocols"); + return "Switching Protocols"_sr; case 103: - return StringRef::from_lit("Early Hints"); + return "Early Hints"_sr; case 200: - return StringRef::from_lit("OK"); + return "OK"_sr; case 201: - return StringRef::from_lit("Created"); + return "Created"_sr; case 202: - return StringRef::from_lit("Accepted"); + return "Accepted"_sr; case 203: - return StringRef::from_lit("Non-Authoritative Information"); + return "Non-Authoritative Information"_sr; case 204: - return StringRef::from_lit("No Content"); + return "No Content"_sr; case 205: - return StringRef::from_lit("Reset Content"); + return "Reset Content"_sr; case 206: - return StringRef::from_lit("Partial Content"); + return "Partial Content"_sr; case 300: - return StringRef::from_lit("Multiple Choices"); + return "Multiple Choices"_sr; case 301: - return StringRef::from_lit("Moved Permanently"); + return "Moved Permanently"_sr; case 302: - return StringRef::from_lit("Found"); + return "Found"_sr; case 303: - return StringRef::from_lit("See Other"); + return "See Other"_sr; case 304: - return StringRef::from_lit("Not Modified"); + return "Not Modified"_sr; case 305: - return StringRef::from_lit("Use Proxy"); - // case 306: return StringRef::from_lit("(Unused)"); + return "Use Proxy"_sr; + // case 306: return "(Unused)"_sr; case 307: - return StringRef::from_lit("Temporary Redirect"); + return "Temporary Redirect"_sr; case 308: - return StringRef::from_lit("Permanent Redirect"); + return "Permanent Redirect"_sr; case 400: - return StringRef::from_lit("Bad Request"); + return "Bad Request"_sr; case 401: - return StringRef::from_lit("Unauthorized"); + return "Unauthorized"_sr; case 402: - return StringRef::from_lit("Payment Required"); + return "Payment Required"_sr; case 403: - return StringRef::from_lit("Forbidden"); + return "Forbidden"_sr; case 404: - return StringRef::from_lit("Not Found"); + return "Not Found"_sr; case 405: - return StringRef::from_lit("Method Not Allowed"); + return "Method Not Allowed"_sr; case 406: - return StringRef::from_lit("Not Acceptable"); + return "Not Acceptable"_sr; case 407: - return StringRef::from_lit("Proxy Authentication Required"); + return "Proxy Authentication Required"_sr; case 408: - return StringRef::from_lit("Request Timeout"); + return "Request Timeout"_sr; case 409: - return StringRef::from_lit("Conflict"); + return "Conflict"_sr; case 410: - return StringRef::from_lit("Gone"); + return "Gone"_sr; case 411: - return StringRef::from_lit("Length Required"); + return "Length Required"_sr; case 412: - return StringRef::from_lit("Precondition Failed"); + return "Precondition Failed"_sr; case 413: - return StringRef::from_lit("Payload Too Large"); + return "Payload Too Large"_sr; case 414: - return StringRef::from_lit("URI Too Long"); + return "URI Too Long"_sr; case 415: - return StringRef::from_lit("Unsupported Media Type"); + return "Unsupported Media Type"_sr; case 416: - return StringRef::from_lit("Requested Range Not Satisfiable"); + return "Requested Range Not Satisfiable"_sr; case 417: - return StringRef::from_lit("Expectation Failed"); + return "Expectation Failed"_sr; case 421: - return StringRef::from_lit("Misdirected Request"); + return "Misdirected Request"_sr; case 425: // https://tools.ietf.org/html/rfc8470 - return StringRef::from_lit("Too Early"); + return "Too Early"_sr; case 426: - return StringRef::from_lit("Upgrade Required"); + return "Upgrade Required"_sr; case 428: - return StringRef::from_lit("Precondition Required"); + return "Precondition Required"_sr; case 429: - return StringRef::from_lit("Too Many Requests"); + return "Too Many Requests"_sr; case 431: - return StringRef::from_lit("Request Header Fields Too Large"); + return "Request Header Fields Too Large"_sr; case 451: - return StringRef::from_lit("Unavailable For Legal Reasons"); + return "Unavailable For Legal Reasons"_sr; case 500: - return StringRef::from_lit("Internal Server Error"); + return "Internal Server Error"_sr; case 501: - return StringRef::from_lit("Not Implemented"); + return "Not Implemented"_sr; case 502: - return StringRef::from_lit("Bad Gateway"); + return "Bad Gateway"_sr; case 503: - return StringRef::from_lit("Service Unavailable"); + return "Service Unavailable"_sr; case 504: - return StringRef::from_lit("Gateway Timeout"); + return "Gateway Timeout"_sr; case 505: - return StringRef::from_lit("HTTP Version Not Supported"); + return "HTTP Version Not Supported"_sr; case 511: - return StringRef::from_lit("Network Authentication Required"); + return "Network Authentication Required"_sr; default: return StringRef{}; } @@ -144,104 +144,104 @@ StringRef get_reason_phrase(unsigned int status_code) { StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code) { switch (status_code) { case 100: - return StringRef::from_lit("100"); + return "100"_sr; case 101: - return StringRef::from_lit("101"); + return "101"_sr; case 103: - return StringRef::from_lit("103"); + return "103"_sr; case 200: - return StringRef::from_lit("200"); + return "200"_sr; case 201: - return StringRef::from_lit("201"); + return "201"_sr; case 202: - return StringRef::from_lit("202"); + return "202"_sr; case 203: - return StringRef::from_lit("203"); + return "203"_sr; case 204: - return StringRef::from_lit("204"); + return "204"_sr; case 205: - return StringRef::from_lit("205"); + return "205"_sr; case 206: - return StringRef::from_lit("206"); + return "206"_sr; case 300: - return StringRef::from_lit("300"); + return "300"_sr; case 301: - return StringRef::from_lit("301"); + return "301"_sr; case 302: - return StringRef::from_lit("302"); + return "302"_sr; case 303: - return StringRef::from_lit("303"); + return "303"_sr; case 304: - return StringRef::from_lit("304"); + return "304"_sr; case 305: - return StringRef::from_lit("305"); - // case 306: return StringRef::from_lit("306"); + return "305"_sr; + // case 306: return "306"_sr; case 307: - return StringRef::from_lit("307"); + return "307"_sr; case 308: - return StringRef::from_lit("308"); + return "308"_sr; case 400: - return StringRef::from_lit("400"); + return "400"_sr; case 401: - return StringRef::from_lit("401"); + return "401"_sr; case 402: - return StringRef::from_lit("402"); + return "402"_sr; case 403: - return StringRef::from_lit("403"); + return "403"_sr; case 404: - return StringRef::from_lit("404"); + return "404"_sr; case 405: - return StringRef::from_lit("405"); + return "405"_sr; case 406: - return StringRef::from_lit("406"); + return "406"_sr; case 407: - return StringRef::from_lit("407"); + return "407"_sr; case 408: - return StringRef::from_lit("408"); + return "408"_sr; case 409: - return StringRef::from_lit("409"); + return "409"_sr; case 410: - return StringRef::from_lit("410"); + return "410"_sr; case 411: - return StringRef::from_lit("411"); + return "411"_sr; case 412: - return StringRef::from_lit("412"); + return "412"_sr; case 413: - return StringRef::from_lit("413"); + return "413"_sr; case 414: - return StringRef::from_lit("414"); + return "414"_sr; case 415: - return StringRef::from_lit("415"); + return "415"_sr; case 416: - return StringRef::from_lit("416"); + return "416"_sr; case 417: - return StringRef::from_lit("417"); + return "417"_sr; case 421: - return StringRef::from_lit("421"); + return "421"_sr; case 426: - return StringRef::from_lit("426"); + return "426"_sr; case 428: - return StringRef::from_lit("428"); + return "428"_sr; case 429: - return StringRef::from_lit("429"); + return "429"_sr; case 431: - return StringRef::from_lit("431"); + return "431"_sr; case 451: - return StringRef::from_lit("451"); + return "451"_sr; case 500: - return StringRef::from_lit("500"); + return "500"_sr; case 501: - return StringRef::from_lit("501"); + return "501"_sr; case 502: - return StringRef::from_lit("502"); + return "502"_sr; case 503: - return StringRef::from_lit("503"); + return "503"_sr; case 504: - return StringRef::from_lit("504"); + return "504"_sr; case 505: - return StringRef::from_lit("505"); + return "505"_sr; case 511: - return StringRef::from_lit("511"); + return "511"_sr; default: return util::make_string_ref_uint(balloc, status_code); } @@ -278,27 +278,16 @@ void copy_url_component(std::string &dest, const http_parser_url *u, int field, } } -Headers::value_type to_header(const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, +Headers::value_type to_header(const StringRef &name, const StringRef &value, bool no_index, int32_t token) { - return Header(std::string(reinterpret_cast<const char *>(name), namelen), - std::string(reinterpret_cast<const char *>(value), valuelen), - no_index, token); + return Header(std::string{std::begin(name), std::end(name)}, + std::string{std::begin(value), std::end(value)}, no_index, + token); } -void add_header(Headers &nva, const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, bool no_index, - int32_t token) { - if (valuelen > 0) { - size_t i, j; - for (i = 0; i < valuelen && (value[i] == ' ' || value[i] == '\t'); ++i) - ; - for (j = valuelen - 1; j > i && (value[j] == ' ' || value[j] == '\t'); --j) - ; - value += i; - valuelen -= i + (valuelen - j - 1); - } - nva.push_back(to_header(name, namelen, value, valuelen, no_index, token)); +void add_header(Headers &nva, const StringRef &name, const StringRef &value, + bool no_index, int32_t token) { + nva.push_back(to_header(name, value, no_index, token)); } const Headers::value_type *get_header(const Headers &nva, const char *name) { @@ -316,56 +305,6 @@ bool non_empty_value(const HeaderRefs::value_type *nv) { } namespace { -nghttp2_nv make_nv_internal(const std::string &name, const std::string &value, - bool no_index, uint8_t nv_flags) { - uint8_t flags; - - flags = - nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE); - - return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), - value.size(), flags}; -} -} // namespace - -namespace { -nghttp2_nv make_nv_internal(const StringRef &name, const StringRef &value, - bool no_index, uint8_t nv_flags) { - uint8_t flags; - - flags = - nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE); - - return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), - value.size(), flags}; -} -} // namespace - -nghttp2_nv make_nv(const std::string &name, const std::string &value, - bool no_index) { - return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE); -} - -nghttp2_nv make_nv(const StringRef &name, const StringRef &value, - bool no_index) { - return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE); -} - -nghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value, - bool no_index) { - return make_nv_internal(name, value, no_index, - NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE); -} - -nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value, - bool no_index) { - return make_nv_internal(name, value, no_index, - NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE); -} - -namespace { void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva, const HeaderRefs &headers, uint8_t nv_flags, uint32_t flags) { @@ -459,8 +398,8 @@ void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva, it_via = it; break; } - nva.push_back( - make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags)); + nva.push_back(make_field_flags(kv->name, kv->value, + nv_flags | no_index(kv->no_index))); } } } // namespace @@ -617,7 +556,7 @@ void dump_nv(FILE *out, const Headers &nva) { void dump_nv(FILE *out, const HeaderRefs &nva) { for (auto &nv : nva) { - fprintf(out, "%s: %s\n", nv.name.c_str(), nv.value.c_str()); + fprintf(out, "%s: %s\n", nv.name.data(), nv.value.data()); } fputc('\n', out); fflush(out); @@ -665,7 +604,7 @@ StringRef rewrite_location_uri(BlockAllocator &balloc, const StringRef &uri, } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); if (!request_authority.empty()) { p = std::copy(std::begin(upstream_scheme), std::end(upstream_scheme), p); @@ -690,7 +629,7 @@ StringRef rewrite_location_uri(BlockAllocator &balloc, const StringRef &uri, *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } int parse_http_status_code(const StringRef &src) { @@ -714,18 +653,14 @@ int parse_http_status_code(const StringRef &src) { return status; } -int lookup_token(const StringRef &name) { - return lookup_token(name.byte(), name.size()); -} - // This function was generated by genheaderfunc.py. Inspired by h2o // header lookup. https://github.com/h2o/h2o -int lookup_token(const uint8_t *name, size_t namelen) { - switch (namelen) { +int lookup_token(const StringRef &name) { + switch (name.size()) { case 2: switch (name[1]) { case 'e': - if (util::streq_l("t", name, 1)) { + if (util::streq("t"_sr, name, 1)) { return HD_TE; } break; @@ -734,7 +669,7 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 3: switch (name[2]) { case 'a': - if (util::streq_l("vi", name, 2)) { + if (util::streq("vi"_sr, name, 2)) { return HD_VIA; } break; @@ -743,17 +678,17 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 4: switch (name[3]) { case 'e': - if (util::streq_l("dat", name, 3)) { + if (util::streq("dat"_sr, name, 3)) { return HD_DATE; } break; case 'k': - if (util::streq_l("lin", name, 3)) { + if (util::streq("lin"_sr, name, 3)) { return HD_LINK; } break; case 't': - if (util::streq_l("hos", name, 3)) { + if (util::streq("hos"_sr, name, 3)) { return HD_HOST; } break; @@ -762,12 +697,12 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 5: switch (name[4]) { case 'h': - if (util::streq_l(":pat", name, 4)) { + if (util::streq(":pat"_sr, name, 4)) { return HD__PATH; } break; case 't': - if (util::streq_l(":hos", name, 4)) { + if (util::streq(":hos"_sr, name, 4)) { return HD__HOST; } break; @@ -776,17 +711,17 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 6: switch (name[5]) { case 'e': - if (util::streq_l("cooki", name, 5)) { + if (util::streq("cooki"_sr, name, 5)) { return HD_COOKIE; } break; case 'r': - if (util::streq_l("serve", name, 5)) { + if (util::streq("serve"_sr, name, 5)) { return HD_SERVER; } break; case 't': - if (util::streq_l("expec", name, 5)) { + if (util::streq("expec"_sr, name, 5)) { return HD_EXPECT; } break; @@ -795,30 +730,30 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 7: switch (name[6]) { case 'c': - if (util::streq_l("alt-sv", name, 6)) { + if (util::streq("alt-sv"_sr, name, 6)) { return HD_ALT_SVC; } break; case 'd': - if (util::streq_l(":metho", name, 6)) { + if (util::streq(":metho"_sr, name, 6)) { return HD__METHOD; } break; case 'e': - if (util::streq_l(":schem", name, 6)) { + if (util::streq(":schem"_sr, name, 6)) { return HD__SCHEME; } - if (util::streq_l("upgrad", name, 6)) { + if (util::streq("upgrad"_sr, name, 6)) { return HD_UPGRADE; } break; case 'r': - if (util::streq_l("traile", name, 6)) { + if (util::streq("traile"_sr, name, 6)) { return HD_TRAILER; } break; case 's': - if (util::streq_l(":statu", name, 6)) { + if (util::streq(":statu"_sr, name, 6)) { return HD__STATUS; } break; @@ -827,12 +762,12 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 8: switch (name[7]) { case 'n': - if (util::streq_l("locatio", name, 7)) { + if (util::streq("locatio"_sr, name, 7)) { return HD_LOCATION; } break; case 'y': - if (util::streq_l("priorit", name, 7)) { + if (util::streq("priorit"_sr, name, 7)) { return HD_PRIORITY; } break; @@ -841,12 +776,12 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 9: switch (name[8]) { case 'd': - if (util::streq_l("forwarde", name, 8)) { + if (util::streq("forwarde"_sr, name, 8)) { return HD_FORWARDED; } break; case 'l': - if (util::streq_l(":protoco", name, 8)) { + if (util::streq(":protoco"_sr, name, 8)) { return HD__PROTOCOL; } break; @@ -855,27 +790,27 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 10: switch (name[9]) { case 'a': - if (util::streq_l("early-dat", name, 9)) { + if (util::streq("early-dat"_sr, name, 9)) { return HD_EARLY_DATA; } break; case 'e': - if (util::streq_l("keep-aliv", name, 9)) { + if (util::streq("keep-aliv"_sr, name, 9)) { return HD_KEEP_ALIVE; } break; case 'n': - if (util::streq_l("connectio", name, 9)) { + if (util::streq("connectio"_sr, name, 9)) { return HD_CONNECTION; } break; case 't': - if (util::streq_l("user-agen", name, 9)) { + if (util::streq("user-agen"_sr, name, 9)) { return HD_USER_AGENT; } break; case 'y': - if (util::streq_l(":authorit", name, 9)) { + if (util::streq(":authorit"_sr, name, 9)) { return HD__AUTHORITY; } break; @@ -884,7 +819,7 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 12: switch (name[11]) { case 'e': - if (util::streq_l("content-typ", name, 11)) { + if (util::streq("content-typ"_sr, name, 11)) { return HD_CONTENT_TYPE; } break; @@ -893,7 +828,7 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 13: switch (name[12]) { case 'l': - if (util::streq_l("cache-contro", name, 12)) { + if (util::streq("cache-contro"_sr, name, 12)) { return HD_CACHE_CONTROL; } break; @@ -902,12 +837,12 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 14: switch (name[13]) { case 'h': - if (util::streq_l("content-lengt", name, 13)) { + if (util::streq("content-lengt"_sr, name, 13)) { return HD_CONTENT_LENGTH; } break; case 's': - if (util::streq_l("http2-setting", name, 13)) { + if (util::streq("http2-setting"_sr, name, 13)) { return HD_HTTP2_SETTINGS; } break; @@ -916,17 +851,17 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 15: switch (name[14]) { case 'e': - if (util::streq_l("accept-languag", name, 14)) { + if (util::streq("accept-languag"_sr, name, 14)) { return HD_ACCEPT_LANGUAGE; } break; case 'g': - if (util::streq_l("accept-encodin", name, 14)) { + if (util::streq("accept-encodin"_sr, name, 14)) { return HD_ACCEPT_ENCODING; } break; case 'r': - if (util::streq_l("x-forwarded-fo", name, 14)) { + if (util::streq("x-forwarded-fo"_sr, name, 14)) { return HD_X_FORWARDED_FOR; } break; @@ -935,7 +870,7 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 16: switch (name[15]) { case 'n': - if (util::streq_l("proxy-connectio", name, 15)) { + if (util::streq("proxy-connectio"_sr, name, 15)) { return HD_PROXY_CONNECTION; } break; @@ -944,22 +879,22 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 17: switch (name[16]) { case 'e': - if (util::streq_l("if-modified-sinc", name, 16)) { + if (util::streq("if-modified-sinc"_sr, name, 16)) { return HD_IF_MODIFIED_SINCE; } break; case 'g': - if (util::streq_l("transfer-encodin", name, 16)) { + if (util::streq("transfer-encodin"_sr, name, 16)) { return HD_TRANSFER_ENCODING; } break; case 'o': - if (util::streq_l("x-forwarded-prot", name, 16)) { + if (util::streq("x-forwarded-prot"_sr, name, 16)) { return HD_X_FORWARDED_PROTO; } break; case 'y': - if (util::streq_l("sec-websocket-ke", name, 16)) { + if (util::streq("sec-websocket-ke"_sr, name, 16)) { return HD_SEC_WEBSOCKET_KEY; } break; @@ -968,7 +903,7 @@ int lookup_token(const uint8_t *name, size_t namelen) { case 20: switch (name[19]) { case 't': - if (util::streq_l("sec-websocket-accep", name, 19)) { + if (util::streq("sec-websocket-accep"_sr, name, 19)) { return HD_SEC_WEBSOCKET_ACCEPT; } break; @@ -1384,7 +1319,8 @@ std::string path_join(const StringRef &base_path, const StringRef &base_query, const StringRef &rel_path, const StringRef &rel_query) { BlockAllocator balloc(1024, 1024); - return path_join(balloc, base_path, base_query, rel_path, rel_query).str(); + return std::string{ + path_join(balloc, base_path, base_query, rel_path, rel_query)}; } bool expect_response_body(int status_code) { @@ -1400,25 +1336,21 @@ bool expect_response_body(int method_token, int status_code) { return method_token != HTTP_HEAD && expect_response_body(status_code); } -int lookup_method_token(const StringRef &name) { - return lookup_method_token(name.byte(), name.size()); -} - // This function was generated by genmethodfunc.py. -int lookup_method_token(const uint8_t *name, size_t namelen) { - switch (namelen) { +int lookup_method_token(const StringRef &name) { + switch (name.size()) { case 3: switch (name[2]) { case 'L': - if (util::streq_l("AC", name, 2)) { + if (util::streq("AC"_sr, name, 2)) { return HTTP_ACL; } break; case 'T': - if (util::streq_l("GE", name, 2)) { + if (util::streq("GE"_sr, name, 2)) { return HTTP_GET; } - if (util::streq_l("PU", name, 2)) { + if (util::streq("PU"_sr, name, 2)) { return HTTP_PUT; } break; @@ -1427,33 +1359,33 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 4: switch (name[3]) { case 'D': - if (util::streq_l("BIN", name, 3)) { + if (util::streq("BIN"_sr, name, 3)) { return HTTP_BIND; } - if (util::streq_l("HEA", name, 3)) { + if (util::streq("HEA"_sr, name, 3)) { return HTTP_HEAD; } break; case 'E': - if (util::streq_l("MOV", name, 3)) { + if (util::streq("MOV"_sr, name, 3)) { return HTTP_MOVE; } break; case 'K': - if (util::streq_l("LIN", name, 3)) { + if (util::streq("LIN"_sr, name, 3)) { return HTTP_LINK; } - if (util::streq_l("LOC", name, 3)) { + if (util::streq("LOC"_sr, name, 3)) { return HTTP_LOCK; } break; case 'T': - if (util::streq_l("POS", name, 3)) { + if (util::streq("POS"_sr, name, 3)) { return HTTP_POST; } break; case 'Y': - if (util::streq_l("COP", name, 3)) { + if (util::streq("COP"_sr, name, 3)) { return HTTP_COPY; } break; @@ -1462,23 +1394,23 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 5: switch (name[4]) { case 'E': - if (util::streq_l("MERG", name, 4)) { + if (util::streq("MERG"_sr, name, 4)) { return HTTP_MERGE; } - if (util::streq_l("PURG", name, 4)) { + if (util::streq("PURG"_sr, name, 4)) { return HTTP_PURGE; } - if (util::streq_l("TRAC", name, 4)) { + if (util::streq("TRAC"_sr, name, 4)) { return HTTP_TRACE; } break; case 'H': - if (util::streq_l("PATC", name, 4)) { + if (util::streq("PATC"_sr, name, 4)) { return HTTP_PATCH; } break; case 'L': - if (util::streq_l("MKCO", name, 4)) { + if (util::streq("MKCO"_sr, name, 4)) { return HTTP_MKCOL; } break; @@ -1487,41 +1419,41 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 6: switch (name[5]) { case 'D': - if (util::streq_l("REBIN", name, 5)) { + if (util::streq("REBIN"_sr, name, 5)) { return HTTP_REBIND; } - if (util::streq_l("UNBIN", name, 5)) { + if (util::streq("UNBIN"_sr, name, 5)) { return HTTP_UNBIND; } break; case 'E': - if (util::streq_l("DELET", name, 5)) { + if (util::streq("DELET"_sr, name, 5)) { return HTTP_DELETE; } - if (util::streq_l("SOURC", name, 5)) { + if (util::streq("SOURC"_sr, name, 5)) { return HTTP_SOURCE; } break; case 'H': - if (util::streq_l("SEARC", name, 5)) { + if (util::streq("SEARC"_sr, name, 5)) { return HTTP_SEARCH; } break; case 'K': - if (util::streq_l("UNLIN", name, 5)) { + if (util::streq("UNLIN"_sr, name, 5)) { return HTTP_UNLINK; } - if (util::streq_l("UNLOC", name, 5)) { + if (util::streq("UNLOC"_sr, name, 5)) { return HTTP_UNLOCK; } break; case 'T': - if (util::streq_l("REPOR", name, 5)) { + if (util::streq("REPOR"_sr, name, 5)) { return HTTP_REPORT; } break; case 'Y': - if (util::streq_l("NOTIF", name, 5)) { + if (util::streq("NOTIF"_sr, name, 5)) { return HTTP_NOTIFY; } break; @@ -1530,17 +1462,17 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 7: switch (name[6]) { case 'H': - if (util::streq_l("MSEARC", name, 6)) { + if (util::streq("MSEARC"_sr, name, 6)) { return HTTP_MSEARCH; } break; case 'S': - if (util::streq_l("OPTION", name, 6)) { + if (util::streq("OPTION"_sr, name, 6)) { return HTTP_OPTIONS; } break; case 'T': - if (util::streq_l("CONNEC", name, 6)) { + if (util::streq("CONNEC"_sr, name, 6)) { return HTTP_CONNECT; } break; @@ -1549,12 +1481,12 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 8: switch (name[7]) { case 'D': - if (util::streq_l("PROPFIN", name, 7)) { + if (util::streq("PROPFIN"_sr, name, 7)) { return HTTP_PROPFIND; } break; case 'T': - if (util::streq_l("CHECKOU", name, 7)) { + if (util::streq("CHECKOU"_sr, name, 7)) { return HTTP_CHECKOUT; } break; @@ -1563,12 +1495,12 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 9: switch (name[8]) { case 'E': - if (util::streq_l("SUBSCRIB", name, 8)) { + if (util::streq("SUBSCRIB"_sr, name, 8)) { return HTTP_SUBSCRIBE; } break; case 'H': - if (util::streq_l("PROPPATC", name, 8)) { + if (util::streq("PROPPATC"_sr, name, 8)) { return HTTP_PROPPATCH; } break; @@ -1577,12 +1509,12 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 10: switch (name[9]) { case 'R': - if (util::streq_l("MKCALENDA", name, 9)) { + if (util::streq("MKCALENDA"_sr, name, 9)) { return HTTP_MKCALENDAR; } break; case 'Y': - if (util::streq_l("MKACTIVIT", name, 9)) { + if (util::streq("MKACTIVIT"_sr, name, 9)) { return HTTP_MKACTIVITY; } break; @@ -1591,7 +1523,7 @@ int lookup_method_token(const uint8_t *name, size_t namelen) { case 11: switch (name[10]) { case 'E': - if (util::streq_l("UNSUBSCRIB", name, 10)) { + if (util::streq("UNSUBSCRIB"_sr, name, 10)) { return HTTP_UNSUBSCRIBE; } break; @@ -1611,17 +1543,17 @@ StringRef get_pure_path_component(const StringRef &uri) { int rv; http_parser_url u{}; - rv = http_parser_parse_url(uri.c_str(), uri.size(), 0, &u); + rv = http_parser_parse_url(uri.data(), uri.size(), 0, &u); if (rv != 0) { return StringRef{}; } if (u.field_set & (1 << UF_PATH)) { auto &f = u.field_data[UF_PATH]; - return StringRef{uri.c_str() + f.off, f.len}; + return StringRef{uri.data() + f.off, f.len}; } - return StringRef::from_lit("/"); + return "/"_sr; } int construct_push_component(BlockAllocator &balloc, StringRef &scheme, @@ -1636,7 +1568,7 @@ int construct_push_component(BlockAllocator &balloc, StringRef &scheme, http_parser_url u{}; - rv = http_parser_parse_url(uri.c_str(), uri.size(), 0, &u); + rv = http_parser_parse_url(uri.data(), uri.size(), 0, &u); if (rv != 0) { if (uri[0] == '/') { @@ -1653,18 +1585,18 @@ int construct_push_component(BlockAllocator &balloc, StringRef &scheme, } } else { if (u.field_set & (1 << UF_SCHEMA)) { - scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); + scheme = util::get_uri_field(uri.data(), u, UF_SCHEMA); } if (u.field_set & (1 << UF_HOST)) { - auto auth = util::get_uri_field(uri.c_str(), u, UF_HOST); + auto auth = util::get_uri_field(uri.data(), u, UF_HOST); auto len = auth.size(); auto port_exists = u.field_set & (1 << UF_PORT); if (port_exists) { len += 1 + str_size("65535"); } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); p = std::copy(std::begin(auth), std::end(auth), p); if (port_exists) { *p++ = ':'; @@ -1672,23 +1604,23 @@ int construct_push_component(BlockAllocator &balloc, StringRef &scheme, } *p = '\0'; - authority = StringRef{iov.base, p}; + authority = StringRef{std::span{std::begin(iov), p}}; } if (u.field_set & (1 << UF_PATH)) { auto &f = u.field_data[UF_PATH]; - rel = StringRef{uri.c_str() + f.off, f.len}; + rel = StringRef{uri.data() + f.off, f.len}; } else { - rel = StringRef::from_lit("/"); + rel = "/"_sr; } if (u.field_set & (1 << UF_QUERY)) { auto &f = u.field_data[UF_QUERY]; - relq = StringRef{uri.c_str() + f.off, f.len}; + relq = StringRef{uri.data() + f.off, f.len}; } } - path = http2::path_join(balloc, base, StringRef{}, rel, relq); + path = path_join(balloc, base, StringRef{}, rel, relq); return 0; } @@ -1737,7 +1669,7 @@ StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, balloc, std::max(static_cast<size_t>(1), base_path.size()) + rel_path.size() + 1 + std::max(base_query.size(), rel_query.size()) + 1); - auto p = res.base; + auto p = std::begin(res); if (rel_path.empty()) { if (base_path.empty()) { @@ -1751,12 +1683,12 @@ StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, p = std::copy(std::begin(base_query), std::end(base_query), p); } *p = '\0'; - return StringRef{res.base, p}; + return StringRef{std::span{std::begin(res), p}}; } *p++ = '?'; p = std::copy(std::begin(rel_query), std::end(rel_query), p); *p = '\0'; - return StringRef{res.base, p}; + return StringRef{std::span{std::begin(res), p}}; } auto first = std::begin(rel_path); @@ -1777,31 +1709,31 @@ StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, if (*first == '.') { if (first + 1 == last) { if (*(p - 1) != '/') { - p = eat_file(res.base, p); + p = eat_file(std::begin(res), p); } break; } if (*(first + 1) == '/') { if (*(p - 1) != '/') { - p = eat_file(res.base, p); + p = eat_file(std::begin(res), p); } first += 2; continue; } if (*(first + 1) == '.') { if (first + 2 == last) { - p = eat_dir(res.base, p); + p = eat_dir(std::begin(res), p); break; } if (*(first + 2) == '/') { - p = eat_dir(res.base, p); + p = eat_dir(std::begin(res), p); first += 3; continue; } } } if (*(p - 1) != '/') { - p = eat_file(res.base, p); + p = eat_file(std::begin(res), p); } auto slash = std::find(first, last, '/'); if (slash == last) { @@ -1818,7 +1750,7 @@ StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, p = std::copy(std::begin(rel_query), std::end(rel_query), p); } *p = '\0'; - return StringRef{res.base, p}; + return StringRef{std::span{std::begin(res), p}}; } StringRef normalize_path(BlockAllocator &balloc, const StringRef &path, @@ -1834,7 +1766,7 @@ StringRef normalize_path(BlockAllocator &balloc, const StringRef &path, // includes last terminal NULL. auto result = make_byte_ref(balloc, path.size() + 1); - auto p = result.base; + auto p = std::begin(result); auto it = std::begin(path); for (; it + 2 < std::end(path);) { @@ -1864,8 +1796,8 @@ StringRef normalize_path(BlockAllocator &balloc, const StringRef &path, p = std::copy(it, std::end(path), p); *p = '\0'; - return path_join(balloc, StringRef{}, StringRef{}, StringRef{result.base, p}, - query); + return path_join(balloc, StringRef{}, StringRef{}, + StringRef{std::span{std::begin(result), p}}, query); } StringRef normalize_path_colon(BlockAllocator &balloc, const StringRef &path, @@ -1881,7 +1813,7 @@ StringRef normalize_path_colon(BlockAllocator &balloc, const StringRef &path, // includes last terminal NULL. auto result = make_byte_ref(balloc, path.size() + 1); - auto p = result.base; + auto p = std::begin(result); auto it = std::begin(path); for (; it + 2 < std::end(path);) { @@ -1911,14 +1843,14 @@ StringRef normalize_path_colon(BlockAllocator &balloc, const StringRef &path, p = std::copy(it, std::end(path), p); *p = '\0'; - return path_join(balloc, StringRef{}, StringRef{}, StringRef{result.base, p}, - query); + return path_join(balloc, StringRef{}, StringRef{}, + StringRef{std::span{std::begin(result), p}}, query); } std::string normalize_path(const StringRef &path, const StringRef &query) { BlockAllocator balloc(1024, 1024); - return normalize_path(balloc, path, query).str(); + return std::string{normalize_path(balloc, path, query)}; } StringRef rewrite_clean_path(BlockAllocator &balloc, const StringRef &src) { @@ -1938,15 +1870,15 @@ StringRef rewrite_clean_path(BlockAllocator &balloc, const StringRef &src) { StringRef copy_lower(BlockAllocator &balloc, const StringRef &src) { auto iov = make_byte_ref(balloc, src.size() + 1); - auto p = iov.base; + auto p = std::begin(iov); p = std::copy(std::begin(src), std::end(src), p); *p = '\0'; - util::inp_strlower(iov.base, p); - return StringRef{iov.base, p}; + util::inp_strlower(std::begin(iov), p); + return StringRef{std::span{std::begin(iov), p}}; } bool contains_trailers(const StringRef &s) { - constexpr auto trailers = StringRef::from_lit("trailers"); + constexpr auto trailers = "trailers"_sr; for (auto p = std::begin(s), end = std::end(s);; ++p) { p = std::find_if(p, end, [](char c) { return c != ' ' && c != '\t'; }); @@ -1971,18 +1903,18 @@ bool contains_trailers(const StringRef &s) { } StringRef make_websocket_accept_token(uint8_t *dest, const StringRef &key) { - static constexpr uint8_t magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - std::array<uint8_t, base64::encode_length(16) + str_size(magic)> s; + static constexpr char magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + std::array<char, base64::encode_length(16) + str_size(magic)> s; auto p = std::copy(std::begin(key), std::end(key), std::begin(s)); std::copy_n(magic, str_size(magic), p); std::array<uint8_t, 20> h; - if (util::sha1(h.data(), StringRef{std::begin(s), std::end(s)}) != 0) { + if (util::sha1(h.data(), StringRef{s}) != 0) { return StringRef{}; } auto end = base64::encode(std::begin(h), std::end(h), dest); - return StringRef{dest, end}; + return StringRef{std::span{dest, end}}; } bool legacy_http1(int major, int minor) { diff --git a/src/http2.h b/src/http2.h index 7cfe461..df7f187 100644 --- a/src/http2.h +++ b/src/http2.h @@ -113,16 +113,14 @@ bool lws(const char *value); void copy_url_component(std::string &dest, const http_parser_url *u, int field, const char *url); -Headers::value_type to_header(const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, +Headers::value_type to_header(const StringRef &name, const StringRef &value, bool no_index, int32_t token); // Add name/value pairs to |nva|. If |no_index| is true, this // name/value pair won't be indexed when it is forwarded to the next -// hop. This function strips white spaces around |value|. -void add_header(Headers &nva, const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, bool no_index, - int32_t token); +// hop. +void add_header(Headers &nva, const StringRef &name, const StringRef &value, + bool no_index, int32_t token); // Returns pointer to the entry in |nva| which has name |name|. If // more than one entries which have the name |name|, last occurrence @@ -132,60 +130,48 @@ const Headers::value_type *get_header(const Headers &nva, const char *name); // Returns true if the value of |nv| is not empty. bool non_empty_value(const HeaderRefs::value_type *nv); -// Creates nghttp2_nv using |name| and |value| and returns it. The -// returned value only references the data pointer to name.c_str() and -// value.c_str(). If |no_index| is true, nghttp2_nv flags member has -// NGHTTP2_NV_FLAG_NO_INDEX flag set. -nghttp2_nv make_nv(const std::string &name, const std::string &value, - bool no_index = false); +// Create nghttp2_nv from |name|, |value| and |flags|. +inline nghttp2_nv make_field_flags(const StringRef &name, + const StringRef &value, + uint8_t flags = NGHTTP2_NV_FLAG_NONE) { + auto ns = as_uint8_span(std::span{name}); + auto vs = as_uint8_span(std::span{value}); -nghttp2_nv make_nv(const StringRef &name, const StringRef &value, - bool no_index = false); - -nghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value, - bool no_index = false); - -nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value, - bool no_index = false); - -// Create nghttp2_nv from string literal |name| and |value|. -template <size_t N, size_t M> -constexpr nghttp2_nv make_nv_ll(const char (&name)[N], const char (&value)[M]) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, M - 1, - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; -} - -// Create nghttp2_nv from string literal |name| and c-string |value|. -template <size_t N> -nghttp2_nv make_nv_lc(const char (&name)[N], const char *value) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), - NGHTTP2_NV_FLAG_NO_COPY_NAME}; + return {const_cast<uint8_t *>(ns.data()), const_cast<uint8_t *>(vs.data()), + ns.size(), vs.size(), flags}; } -template <size_t N> -nghttp2_nv make_nv_lc_nocopy(const char (&name)[N], const char *value) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; +// Creates nghttp2_nv from |name|, |value| and |flags|. nghttp2 +// library does not copy them. +inline nghttp2_nv make_field(const StringRef &name, const StringRef &value, + uint8_t flags = NGHTTP2_NV_FLAG_NONE) { + return make_field_flags(name, value, + static_cast<uint8_t>(NGHTTP2_NV_FLAG_NO_COPY_NAME | + NGHTTP2_NV_FLAG_NO_COPY_VALUE | + flags)); } -// Create nghttp2_nv from string literal |name| and std::string -// |value|. -template <size_t N> -nghttp2_nv make_nv_ls(const char (&name)[N], const std::string &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP2_NV_FLAG_NO_COPY_NAME}; +// Creates nghttp2_nv from |name|, |value| and |flags|. nghttp2 +// library copies |value| unless |flags| includes +// NGHTTP2_NV_FLAG_NO_COPY_VALUE. +inline nghttp2_nv make_field_v(const StringRef &name, const StringRef &value, + uint8_t flags = NGHTTP2_NV_FLAG_NONE) { + return make_field_flags( + name, value, static_cast<uint8_t>(NGHTTP2_NV_FLAG_NO_COPY_NAME | flags)); } -template <size_t N> -nghttp2_nv make_nv_ls_nocopy(const char (&name)[N], const std::string &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; +// Creates nghttp2_nv from |name|, |value| and |flags|. nghttp2 +// library copies |name| and |value| unless |flags| includes +// NGHTTP2_NV_FLAG_NO_COPY_NAME or NGHTTP2_NV_FLAG_NO_COPY_VALUE. +inline nghttp2_nv make_field_nv(const StringRef &name, const StringRef &value, + uint8_t flags = NGHTTP2_NV_FLAG_NONE) { + return make_field_flags(name, value, flags); } -template <size_t N> -nghttp2_nv make_nv_ls_nocopy(const char (&name)[N], const StringRef &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; +// Returns NGHTTP2_NV_FLAG_NO_INDEX if |no_index| is true, otherwise +// NGHTTP2_NV_FLAG_NONE. +inline uint8_t no_index(bool no_index) { + return no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE; } enum HeaderBuildOp { @@ -340,10 +326,9 @@ enum { using HeaderIndex = std::array<int16_t, HD_MAXIDX>; -// Looks up header token for header name |name| of length |namelen|. -// Only headers we are interested in are tokenized. If header name -// cannot be tokenized, returns -1. -int lookup_token(const uint8_t *name, size_t namelen); +// Looks up header token for header name |name|. Only headers we are +// interested in are tokenized. If header name cannot be tokenized, +// returns -1. int lookup_token(const StringRef &name); // Initializes |hdidx|, header index. The |hdidx| must point to the @@ -390,10 +375,9 @@ bool expect_response_body(int method_token, int status_code); // true if response has body, taking into account status code only. bool expect_response_body(int status_code); -// Looks up method token for method name |name| of length |namelen|. -// Only methods defined in llhttp.h (llhttp_method) are tokenized. If -// method name cannot be tokenized, returns -1. -int lookup_method_token(const uint8_t *name, size_t namelen); +// Looks up method token for method name |name|. Only methods defined +// in llhttp.h (llhttp_method) are tokenized. If method name cannot +// be tokenized, returns -1. int lookup_method_token(const StringRef &name); // Returns string representation of |method_token|. This is wrapper diff --git a/src/http2_test.cc b/src/http2_test.cc index 3cb0b71..304f350 100644 --- a/src/http2_test.cc +++ b/src/http2_test.cc @@ -36,6 +36,7 @@ #include "util.h" using namespace nghttp2; +using namespace std::literals; #define MAKE_NV(K, V) \ { \ @@ -76,60 +77,32 @@ namespace { void check_nv(const HeaderRef &a, const nghttp2_nv *b) { assert_size(a.name.size(), ==, b->namelen); assert_size(a.value.size(), ==, b->valuelen); - assert_memory_equal(b->namelen, a.name.c_str(), b->name); - assert_memory_equal(b->valuelen, a.value.c_str(), b->value); + assert_memory_equal(b->namelen, a.name.data(), b->name); + assert_memory_equal(b->valuelen, a.value.data(), b->value); } } // namespace void test_http2_add_header(void) { auto nva = Headers(); - http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3, - false, -1); + http2::add_header(nva, "alpha"_sr, "123"_sr, false, -1); assert_true(Headers::value_type("alpha", "123") == nva[0]); assert_false(nva[0].no_index); nva.clear(); - http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0, - true, -1); + http2::add_header(nva, "alpha"_sr, ""_sr, true, -1); assert_true(Headers::value_type("alpha", "") == nva[0]); assert_true(nva[0].no_index); nva.clear(); - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b", 2, - false, -1); + http2::add_header(nva, "a"_sr, "b"_sr, false, -1); assert_true(Headers::value_type("a", "b") == nva[0]); nva.clear(); - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"b ", 2, - false, -1); - assert_true(Headers::value_type("a", "b") == nva[0]); - - nva.clear(); - - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b ", 5, - false, -1); - assert_true(Headers::value_type("a", "b") == nva[0]); - - nva.clear(); - - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" bravo ", - 9, false, -1); - assert_true(Headers::value_type("a", "bravo") == nva[0]); - - nva.clear(); - - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" ", 4, - false, -1); - assert_true(Headers::value_type("a", "") == nva[0]); - - nva.clear(); - - http2::add_header(nva, (const uint8_t *)"te", 2, (const uint8_t *)"trailers", - 8, false, http2::HD_TE); + http2::add_header(nva, "te"_sr, "trailers"_sr, false, http2::HD_TE); assert_int32(http2::HD_TE, ==, nva[0].token); } @@ -158,43 +131,31 @@ void test_http2_get_header(void) { namespace { auto headers = HeaderRefs{ - {StringRef::from_lit("alpha"), StringRef::from_lit("0"), true}, - {StringRef::from_lit("bravo"), StringRef::from_lit("1")}, - {StringRef::from_lit("connection"), StringRef::from_lit("2"), false, - http2::HD_CONNECTION}, - {StringRef::from_lit("connection"), StringRef::from_lit("3"), false, - http2::HD_CONNECTION}, - {StringRef::from_lit("delta"), StringRef::from_lit("4")}, - {StringRef::from_lit("expect"), StringRef::from_lit("5")}, - {StringRef::from_lit("foxtrot"), StringRef::from_lit("6")}, - {StringRef::from_lit("tango"), StringRef::from_lit("7")}, - {StringRef::from_lit("te"), StringRef::from_lit("8"), false, http2::HD_TE}, - {StringRef::from_lit("te"), StringRef::from_lit("9"), false, http2::HD_TE}, - {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("10"), false, - http2::HD_X_FORWARDED_FOR}, - {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("11"), false, - http2::HD_X_FORWARDED_FOR}, - {StringRef::from_lit("zulu"), StringRef::from_lit("12")}}; + {"alpha"_sr, "0"_sr, true}, + {"bravo"_sr, "1"_sr}, + {"connection"_sr, "2"_sr, false, http2::HD_CONNECTION}, + {"connection"_sr, "3"_sr, false, http2::HD_CONNECTION}, + {"delta"_sr, "4"_sr}, + {"expect"_sr, "5"_sr}, + {"foxtrot"_sr, "6"_sr}, + {"tango"_sr, "7"_sr}, + {"te"_sr, "8"_sr, false, http2::HD_TE}, + {"te"_sr, "9"_sr, false, http2::HD_TE}, + {"x-forwarded-proto"_sr, "10"_sr, false, http2::HD_X_FORWARDED_FOR}, + {"x-forwarded-proto"_sr, "11"_sr, false, http2::HD_X_FORWARDED_FOR}, + {"zulu"_sr, "12"_sr}}; } // namespace namespace { auto headers2 = HeaderRefs{ - {StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff1"), false, - http2::HD_X_FORWARDED_FOR}, - {StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff2"), false, - http2::HD_X_FORWARDED_FOR}, - {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp1"), - false, http2::HD_X_FORWARDED_PROTO}, - {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp2"), - false, http2::HD_X_FORWARDED_PROTO}, - {StringRef::from_lit("forwarded"), StringRef::from_lit("fwd1"), false, - http2::HD_FORWARDED}, - {StringRef::from_lit("forwarded"), StringRef::from_lit("fwd2"), false, - http2::HD_FORWARDED}, - {StringRef::from_lit("via"), StringRef::from_lit("via1"), false, - http2::HD_VIA}, - {StringRef::from_lit("via"), StringRef::from_lit("via2"), false, - http2::HD_VIA}, + {"x-forwarded-for"_sr, "xff1"_sr, false, http2::HD_X_FORWARDED_FOR}, + {"x-forwarded-for"_sr, "xff2"_sr, false, http2::HD_X_FORWARDED_FOR}, + {"x-forwarded-proto"_sr, "xfp1"_sr, false, http2::HD_X_FORWARDED_PROTO}, + {"x-forwarded-proto"_sr, "xfp2"_sr, false, http2::HD_X_FORWARDED_PROTO}, + {"forwarded"_sr, "fwd1"_sr, false, http2::HD_FORWARDED}, + {"forwarded"_sr, "fwd2"_sr, false, http2::HD_FORWARDED}, + {"via"_sr, "via1"_sr, false, http2::HD_VIA}, + {"via"_sr, "via2"_sr, false, http2::HD_VIA}, }; } // namespace @@ -298,7 +259,7 @@ void check_rewrite_location_uri(const std::string &want, const std::string &uri, auto got = http2::rewrite_location_uri( balloc, StringRef{uri}, u, StringRef{match_host}, StringRef{req_authority}, StringRef{upstream_scheme}); - assert_stdstring_equal(want, got.str()); + assert_stdsv_equal(want, got); } } // namespace @@ -330,14 +291,12 @@ void test_http2_rewrite_location_uri(void) { } void test_http2_parse_http_status_code(void) { - assert_int(200, ==, - http2::parse_http_status_code(StringRef::from_lit("200"))); - assert_int(102, ==, - http2::parse_http_status_code(StringRef::from_lit("102"))); - assert_int(-1, ==, http2::parse_http_status_code(StringRef::from_lit("099"))); - assert_int(-1, ==, http2::parse_http_status_code(StringRef::from_lit("99"))); - assert_int(-1, ==, http2::parse_http_status_code(StringRef::from_lit("-1"))); - assert_int(-1, ==, http2::parse_http_status_code(StringRef::from_lit("20a"))); + assert_int(200, ==, http2::parse_http_status_code("200"_sr)); + assert_int(102, ==, http2::parse_http_status_code("102"_sr)); + assert_int(-1, ==, http2::parse_http_status_code("099"_sr)); + assert_int(-1, ==, http2::parse_http_status_code("99"_sr)); + assert_int(-1, ==, http2::parse_http_status_code("-1"_sr)); + assert_int(-1, ==, http2::parse_http_status_code("20a"_sr)); assert_int(-1, ==, http2::parse_http_status_code(StringRef{})); } @@ -352,536 +311,491 @@ void test_http2_index_header(void) { } void test_http2_lookup_token(void) { - assert_int(http2::HD__AUTHORITY, ==, - http2::lookup_token(StringRef::from_lit(":authority"))); - assert_int(-1, ==, http2::lookup_token(StringRef::from_lit(":authorit"))); - assert_int(-1, ==, http2::lookup_token(StringRef::from_lit(":Authority"))); - assert_int(http2::HD_EXPECT, ==, - http2::lookup_token(StringRef::from_lit("expect"))); + assert_int(http2::HD__AUTHORITY, ==, http2::lookup_token(":authority"_sr)); + assert_int(-1, ==, http2::lookup_token(":authorit"_sr)); + assert_int(-1, ==, http2::lookup_token(":Authority"_sr)); + assert_int(http2::HD_EXPECT, ==, http2::lookup_token("expect"_sr)); } void test_http2_parse_link_header(void) { { // only URI appears; we don't extract URI unless it bears rel=preload - auto res = http2::parse_link_header(StringRef::from_lit("<url>")); + auto res = http2::parse_link_header("<url>"_sr); assert_size(0, ==, res.size()); } { // URI url should be extracted - auto res = - http2::parse_link_header(StringRef::from_lit("<url>; rel=preload")); + auto res = http2::parse_link_header("<url>; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // With extra link-param. URI url should be extracted - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload; as=file")); + auto res = http2::parse_link_header("<url>; rel=preload; as=file"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // With extra link-param. URI url should be extracted - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; as=file; rel=preload")); + auto res = http2::parse_link_header("<url>; as=file; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // With extra link-param and quote-string. URI url should be // extracted - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; title="foo,bar")")); + auto res = + http2::parse_link_header(R"(<url>; rel=preload; title="foo,bar")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // With extra link-param and quote-string. URI url should be // extracted - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; title="foo,bar"; rel=preload)")); + auto res = + http2::parse_link_header(R"(<url>; title="foo,bar"; rel=preload)"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // ',' after quote-string auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; title="foo,bar", <url2>; rel=preload)")); + R"(<url>; title="foo,bar", <url2>; rel=preload)"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url2", res[0].uri.str()); + assert_stdsv_equal("url2"sv, res[0].uri); } { // Only first URI should be extracted. - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload, <url2>")); + auto res = http2::parse_link_header("<url>; rel=preload, <url2>"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // Both have rel=preload, so both urls should be extracted - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload, <url2>; rel=preload")); + auto res = + http2::parse_link_header("<url>; rel=preload, <url2>; rel=preload"_sr); assert_size(2, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); - assert_stdstring_equal("url2", res[1].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); + assert_stdsv_equal("url2"sv, res[1].uri); } { // Second URI uri should be extracted. - auto res = http2::parse_link_header( - StringRef::from_lit("<url>, <url2>;rel=preload")); + auto res = http2::parse_link_header("<url>, <url2>;rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url2", res[0].uri.str()); + assert_stdsv_equal("url2"sv, res[0].uri); } { // Error if input ends with ';' - auto res = - http2::parse_link_header(StringRef::from_lit("<url>;rel=preload;")); + auto res = http2::parse_link_header("<url>;rel=preload;"_sr); assert_size(0, ==, res.size()); } { // Error if link header ends with ';' - auto res = http2::parse_link_header( - StringRef::from_lit("<url>;rel=preload;, <url>")); + auto res = http2::parse_link_header("<url>;rel=preload;, <url>"_sr); assert_size(0, ==, res.size()); } { // OK if input ends with ',' - auto res = - http2::parse_link_header(StringRef::from_lit("<url>;rel=preload,")); + auto res = http2::parse_link_header("<url>;rel=preload,"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // Multiple repeated ','s between fields is OK - auto res = http2::parse_link_header( - StringRef::from_lit("<url>,,,<url2>;rel=preload")); + auto res = http2::parse_link_header("<url>,,,<url2>;rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url2", res[0].uri.str()); + assert_stdsv_equal("url2"sv, res[0].uri); } { // Error if url is not enclosed by <> - auto res = - http2::parse_link_header(StringRef::from_lit("url>;rel=preload")); + auto res = http2::parse_link_header("url>;rel=preload"_sr); assert_size(0, ==, res.size()); } { // Error if url is not enclosed by <> - auto res = - http2::parse_link_header(StringRef::from_lit("<url;rel=preload")); + auto res = http2::parse_link_header("<url;rel=preload"_sr); assert_size(0, ==, res.size()); } { // Empty parameter value is not allowed - auto res = - http2::parse_link_header(StringRef::from_lit("<url>;rel=preload; as=")); + auto res = http2::parse_link_header("<url>;rel=preload; as="_sr); assert_size(0, ==, res.size()); } { // Empty parameter value is not allowed - auto res = - http2::parse_link_header(StringRef::from_lit("<url>;as=;rel=preload")); + auto res = http2::parse_link_header("<url>;as=;rel=preload"_sr); assert_size(0, ==, res.size()); } { // Empty parameter value is not allowed - auto res = http2::parse_link_header( - StringRef::from_lit("<url>;as=, <url>;rel=preload")); + auto res = http2::parse_link_header("<url>;as=, <url>;rel=preload"_sr); assert_size(0, ==, res.size()); } { // Empty parameter name is not allowed - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; =file; rel=preload")); + auto res = http2::parse_link_header("<url>; =file; rel=preload"_sr); assert_size(0, ==, res.size()); } { // Without whitespaces auto res = http2::parse_link_header( - StringRef::from_lit("<url>;as=file;rel=preload,<url2>;rel=preload")); + "<url>;as=file;rel=preload,<url2>;rel=preload"_sr); assert_size(2, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); - assert_stdstring_equal("url2", res[1].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); + assert_stdsv_equal("url2"sv, res[1].uri); } { // link-extension may have no value - auto res = - http2::parse_link_header(StringRef::from_lit("<url>; as; rel=preload")); + auto res = http2::parse_link_header("<url>; as; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // ext-name-star - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; foo*=bar; rel=preload")); + auto res = http2::parse_link_header("<url>; foo*=bar; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // '*' is not allowed expect for trailing one - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; *=bar; rel=preload")); + auto res = http2::parse_link_header("<url>; *=bar; rel=preload"_sr); assert_size(0, ==, res.size()); } { // '*' is not allowed expect for trailing one - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; foo*bar=buzz; rel=preload")); + auto res = http2::parse_link_header("<url>; foo*bar=buzz; rel=preload"_sr); assert_size(0, ==, res.size()); } { // ext-name-star must be followed by '=' - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; foo*; rel=preload")); + auto res = http2::parse_link_header("<url>; foo*; rel=preload"_sr); assert_size(0, ==, res.size()); } { // '>' is not followed by ';' - auto res = - http2::parse_link_header(StringRef::from_lit("<url> rel=preload")); + auto res = http2::parse_link_header("<url> rel=preload"_sr); assert_size(0, ==, res.size()); } { // Starting with whitespace is no problem. - auto res = - http2::parse_link_header(StringRef::from_lit(" <url>; rel=preload")); + auto res = http2::parse_link_header(" <url>; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload is a prefix of bogus rel parameter value - auto res = - http2::parse_link_header(StringRef::from_lit("<url>; rel=preloadx")); + auto res = http2::parse_link_header("<url>; rel=preloadx"_sr); assert_size(0, ==, res.size()); } { // preload in relation-types list - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload")")); + auto res = http2::parse_link_header(R"(<url>; rel="preload")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list followed by another parameter - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload foo")")); + auto res = http2::parse_link_header(R"(<url>; rel="preload foo")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list following another parameter - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="foo preload")")); + auto res = http2::parse_link_header(R"(<url>; rel="foo preload")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list between other parameters - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="foo preload bar")")); + auto res = http2::parse_link_header(R"(<url>; rel="foo preload bar")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list between other parameters - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="foo preload bar")")); + auto res = + http2::parse_link_header(R"(<url>; rel="foo preload bar")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // no preload in relation-types list - auto res = - http2::parse_link_header(StringRef::from_lit(R"(<url>; rel="foo")")); + auto res = http2::parse_link_header(R"(<url>; rel="foo")"_sr); assert_size(0, ==, res.size()); } { // no preload in relation-types list, multiple unrelated elements. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="foo bar")")); + auto res = http2::parse_link_header(R"(<url>; rel="foo bar")"_sr); assert_size(0, ==, res.size()); } { // preload in relation-types list, followed by another link-value. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload", <url2>)")); + auto res = http2::parse_link_header(R"(<url>; rel="preload", <url2>)"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list, following another link-value. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>, <url2>; rel="preload")")); + auto res = http2::parse_link_header(R"(<url>, <url2>; rel="preload")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url2", res[0].uri.str()); + assert_stdsv_equal("url2"sv, res[0].uri); } { // preload in relation-types list, followed by another link-param. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload"; as="font")")); + auto res = + http2::parse_link_header(R"(<url>; rel="preload"; as="font")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list, followed by character other // than ';' or ',' - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload".)")); + auto res = http2::parse_link_header(R"(<url>; rel="preload".)"_sr); assert_size(0, ==, res.size()); } { // preload in relation-types list, followed by ';' but it // terminates input - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload";)")); + auto res = http2::parse_link_header(R"(<url>; rel="preload";)"_sr); assert_size(0, ==, res.size()); } { // preload in relation-types list, followed by ',' but it // terminates input - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload",)")); + auto res = http2::parse_link_header(R"(<url>; rel="preload",)"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // preload in relation-types list but there is preceding white // space. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=" preload")")); + auto res = http2::parse_link_header(R"(<url>; rel=" preload")"_sr); assert_size(0, ==, res.size()); } { // preload in relation-types list but there is trailing white // space. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel="preload ")")); + auto res = http2::parse_link_header(R"(<url>; rel="preload ")"_sr); assert_size(0, ==, res.size()); } { // backslash escaped characters in quoted-string auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; title="foo\"baz\"bar")")); + R"(<url>; rel=preload; title="foo\"baz\"bar")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // anchor="" is acceptable - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; anchor="")")); + auto res = http2::parse_link_header(R"(<url>; rel=preload; anchor="")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // With anchor="#foo", url should be ignored - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; anchor="#foo")")); + auto res = + http2::parse_link_header(R"(<url>; rel=preload; anchor="#foo")"_sr); assert_size(0, ==, res.size()); } { // With anchor=f, url should be ignored - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload; anchor=f")); + auto res = http2::parse_link_header("<url>; rel=preload; anchor=f"_sr); assert_size(0, ==, res.size()); } { // First url is ignored With anchor="#foo", but url should be // accepted. - auto res = http2::parse_link_header(StringRef::from_lit( - R"(<url>; rel=preload; anchor="#foo", <url2>; rel=preload)")); + auto res = http2::parse_link_header( + R"(<url>; rel=preload; anchor="#foo", <url2>; rel=preload)"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url2", res[0].uri.str()); + assert_stdsv_equal("url2"sv, res[0].uri); } { // With loadpolicy="next", url should be ignored - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; loadpolicy="next")")); + auto res = + http2::parse_link_header(R"(<url>; rel=preload; loadpolicy="next")"_sr); assert_size(0, ==, res.size()); } { // url should be picked up if empty loadpolicy is specified - auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; loadpolicy="")")); + auto res = + http2::parse_link_header(R"(<url>; rel=preload; loadpolicy="")"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // case-insensitive match auto res = http2::parse_link_header( - StringRef::from_lit(R"(<url>; rel=preload; ANCHOR="#foo", <url2>; )" - R"(REL=PRELOAD, <url3>; REL="foo PRELOAD bar")")); + R"(<url>; rel=preload; ANCHOR="#foo", <url2>; )" + R"(REL=PRELOAD, <url3>; REL="foo PRELOAD bar")"_sr); assert_size(2, ==, res.size()); - assert_stdstring_equal("url2", res[0].uri.str()); - assert_stdstring_equal("url3", res[1].uri.str()); + assert_stdsv_equal("url2"sv, res[0].uri); + assert_stdsv_equal("url3"sv, res[1].uri); } { // nopush at the end of input - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload; nopush")); + auto res = http2::parse_link_header("<url>; rel=preload; nopush"_sr); assert_size(0, ==, res.size()); } { // nopush followed by ';' - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload; nopush; foo")); + auto res = http2::parse_link_header("<url>; rel=preload; nopush; foo"_sr); assert_size(0, ==, res.size()); } { // nopush followed by ',' - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; nopush; rel=preload")); + auto res = http2::parse_link_header("<url>; nopush; rel=preload"_sr); assert_size(0, ==, res.size()); } { // string whose prefix is nopush - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; nopushyes; rel=preload")); + auto res = http2::parse_link_header("<url>; nopushyes; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } { // rel=preload twice - auto res = http2::parse_link_header( - StringRef::from_lit("<url>; rel=preload; rel=preload")); + auto res = http2::parse_link_header("<url>; rel=preload; rel=preload"_sr); assert_size(1, ==, res.size()); - assert_stdstring_equal("url", res[0].uri.str()); + assert_stdsv_equal("url"sv, res[0].uri); } } void test_http2_path_join(void) { { - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/"); + auto base = "/"_sr; + auto rel = "/"_sr; assert_stdstring_equal( "/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha"); + auto base = "/"_sr; + auto rel = "/alpha"_sr; assert_stdstring_equal( "/alpha", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // rel ends with trailing '/' - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha/"); + auto base = "/"_sr; + auto rel = "/alpha/"_sr; assert_stdstring_equal( "/alpha/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // rel contains multiple components - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha/bravo"); + auto base = "/"_sr; + auto rel = "/alpha/bravo"_sr; assert_stdstring_equal( "/alpha/bravo", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // rel is relative - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("alpha/bravo"); + auto base = "/"_sr; + auto rel = "alpha/bravo"_sr; assert_stdstring_equal( "/alpha/bravo", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // rel is relative and base ends without /, which means it refers // to file. - auto base = StringRef::from_lit("/alpha"); - auto rel = StringRef::from_lit("bravo/charlie"); + auto base = "/alpha"_sr; + auto rel = "bravo/charlie"_sr; assert_stdstring_equal( "/bravo/charlie", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // rel contains repeated '/'s - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha/////bravo/////"); + auto base = "/"_sr; + auto rel = "/alpha/////bravo/////"_sr; assert_stdstring_equal( "/alpha/bravo/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // base ends with '/', so '..' eats 'bravo' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../charlie/delta"); + auto base = "/alpha/bravo/"_sr; + auto rel = "../charlie/delta"_sr; assert_stdstring_equal( "/alpha/charlie/delta", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // base does not end with '/', so '..' eats 'alpha/bravo' - auto base = StringRef::from_lit("/alpha/bravo"); - auto rel = StringRef::from_lit("../charlie"); + auto base = "/alpha/bravo"_sr; + auto rel = "../charlie"_sr; assert_stdstring_equal( "/charlie", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // 'charlie' is eaten by following '..' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../charlie/../delta"); + auto base = "/alpha/bravo/"_sr; + auto rel = "../charlie/../delta"_sr; assert_stdstring_equal( "/alpha/delta", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // excessive '..' results in '/' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../../../"); + auto base = "/alpha/bravo/"_sr; + auto rel = "../../../"_sr; assert_stdstring_equal( "/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // excessive '..' and path component - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../../../charlie"); + auto base = "/alpha/bravo/"_sr; + auto rel = "../../../charlie"_sr; assert_stdstring_equal( "/charlie", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // rel ends with '..' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("charlie/.."); + auto base = "/alpha/bravo/"_sr; + auto rel = "charlie/.."_sr; assert_stdstring_equal( "/alpha/bravo/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // base empty and rel contains '..' auto base = StringRef{}; - auto rel = StringRef::from_lit("charlie/.."); + auto rel = "charlie/.."_sr; assert_stdstring_equal( "/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // '.' is ignored - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("charlie/././././delta"); + auto base = "/"_sr; + auto rel = "charlie/././././delta"_sr; assert_stdstring_equal( "/charlie/delta", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // trailing '.' is ignored - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("charlie/."); + auto base = "/"_sr; + auto rel = "charlie/."_sr; assert_stdstring_equal( "/charlie/", http2::path_join(base, StringRef{}, rel, StringRef{})); } { // query - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/"); - auto relq = StringRef::from_lit("q"); + auto base = "/"_sr; + auto rel = "/"_sr; + auto relq = "q"_sr; assert_stdstring_equal("/?q", http2::path_join(base, StringRef{}, rel, relq)); } { // empty rel and query - auto base = StringRef::from_lit("/alpha"); + auto base = "/alpha"_sr; auto rel = StringRef{}; - auto relq = StringRef::from_lit("q"); + auto relq = "q"_sr; assert_stdstring_equal("/alpha?q", http2::path_join(base, StringRef{}, rel, relq)); } { // both rel and query are empty - auto base = StringRef::from_lit("/alpha"); - auto baseq = StringRef::from_lit("r"); + auto base = "/alpha"_sr; + auto baseq = "r"_sr; auto rel = StringRef{}; auto relq = StringRef{}; assert_stdstring_equal("/alpha?r", @@ -890,7 +804,7 @@ void test_http2_path_join(void) { { // empty base auto base = StringRef{}; - auto rel = StringRef::from_lit("/alpha"); + auto rel = "/alpha"_sr; assert_stdstring_equal( "/alpha", http2::path_join(base, StringRef{}, rel, StringRef{})); } @@ -902,7 +816,7 @@ void test_http2_path_join(void) { { // only baseq is not empty auto base = StringRef{}; - auto baseq = StringRef::from_lit("r"); + auto baseq = "r"_sr; auto rel = StringRef{}; assert_stdstring_equal("/?r", http2::path_join(base, baseq, rel, StringRef{})); @@ -911,60 +825,60 @@ void test_http2_path_join(void) { // path starts with multiple '/'s. auto base = StringRef{}; auto baseq = StringRef{}; - auto rel = StringRef::from_lit("//alpha//bravo"); - auto relq = StringRef::from_lit("charlie"); + auto rel = "//alpha//bravo"_sr; + auto relq = "charlie"_sr; assert_stdstring_equal("/alpha/bravo?charlie", http2::path_join(base, baseq, rel, relq)); } // Test cases from RFC 3986, section 5.4. - constexpr auto base = StringRef::from_lit("/b/c/d;p"); - constexpr auto baseq = StringRef::from_lit("q"); + constexpr auto base = "/b/c/d;p"_sr; + constexpr auto baseq = "q"_sr; { - auto rel = StringRef::from_lit("g"); + auto rel = "g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("./g"); + auto rel = "./g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g/"); + auto rel = "g/"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("/g"); + auto rel = "/g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/g", http2::path_join(base, baseq, rel, relq)); } { auto rel = StringRef{}; - auto relq = StringRef::from_lit("y"); + auto relq = "y"_sr; assert_stdstring_equal("/b/c/d;p?y", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g"); - auto relq = StringRef::from_lit("y"); + auto rel = "g"_sr; + auto relq = "y"_sr; assert_stdstring_equal("/b/c/g?y", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit(";x"); + auto rel = ";x"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/;x", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g;x"); + auto rel = "g;x"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g;x", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g;x"); - auto relq = StringRef::from_lit("y"); + auto rel = "g;x"_sr; + auto relq = "y"_sr; assert_stdstring_equal("/b/c/g;x?y", http2::path_join(base, baseq, rel, relq)); } @@ -975,116 +889,116 @@ void test_http2_path_join(void) { http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("."); + auto rel = "."_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("./"); + auto rel = "./"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit(".."); + auto rel = ".."_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../"); + auto rel = "../"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../g"); + auto rel = "../g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../.."); + auto rel = "../.."_sr; auto relq = StringRef{}; assert_stdstring_equal("/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../../"); + auto rel = "../../"_sr; auto relq = StringRef{}; assert_stdstring_equal("/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../../g"); + auto rel = "../../g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../../../g"); + auto rel = "../../../g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("../../../../g"); + auto rel = "../../../../g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("/./g"); + auto rel = "/./g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("/../g"); + auto rel = "/../g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g."); + auto rel = "g."_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g.", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit(".g"); + auto rel = ".g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/.g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g.."); + auto rel = "g.."_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g..", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("..g"); + auto rel = "..g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/..g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("./../g"); + auto rel = "./../g"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/g", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("./g/."); + auto rel = "./g/."_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g/", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g/./h"); + auto rel = "g/./h"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g/h", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g/../h"); + auto rel = "g/../h"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/h", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g;x=1/./y"); + auto rel = "g;x=1/./y"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/g;x=1/y", http2::path_join(base, baseq, rel, relq)); } { - auto rel = StringRef::from_lit("g;x=1/../y"); + auto rel = "g;x=1/../y"_sr; auto relq = StringRef{}; assert_stdstring_equal("/b/c/y", http2::path_join(base, baseq, rel, relq)); } @@ -1093,95 +1007,67 @@ void test_http2_path_join(void) { void test_http2_normalize_path(void) { assert_stdstring_equal( "/alpha/charlie", - http2::normalize_path(StringRef::from_lit("/alpha/bravo/../charlie"), - StringRef{})); + http2::normalize_path("/alpha/bravo/../charlie"_sr, StringRef{})); assert_stdstring_equal( - "/alpha", http2::normalize_path(StringRef::from_lit("/a%6c%70%68%61"), - StringRef{})); + "/alpha", http2::normalize_path("/a%6c%70%68%61"_sr, StringRef{})); - assert_stdstring_equal( - "/alpha%2F%3A", - http2::normalize_path(StringRef::from_lit("/alpha%2f%3a"), StringRef{})); + assert_stdstring_equal("/alpha%2F%3A", + http2::normalize_path("/alpha%2f%3a"_sr, StringRef{})); - assert_stdstring_equal( - "/%2F", http2::normalize_path(StringRef::from_lit("%2f"), StringRef{})); + assert_stdstring_equal("/%2F", http2::normalize_path("%2f"_sr, StringRef{})); - assert_stdstring_equal( - "/%f", http2::normalize_path(StringRef::from_lit("%f"), StringRef{})); + assert_stdstring_equal("/%f", http2::normalize_path("%f"_sr, StringRef{})); - assert_stdstring_equal( - "/%", http2::normalize_path(StringRef::from_lit("%"), StringRef{})); + assert_stdstring_equal("/%", http2::normalize_path("%"_sr, StringRef{})); assert_stdstring_equal("/", http2::normalize_path(StringRef{}, StringRef{})); assert_stdstring_equal("/alpha?bravo", - http2::normalize_path(StringRef::from_lit("/alpha"), - StringRef::from_lit("bravo"))); + http2::normalize_path("/alpha"_sr, "bravo"_sr)); } void test_http2_rewrite_clean_path(void) { BlockAllocator balloc(4096, 4096); // unreserved characters - assert_stdstring_equal( - "/alpha/bravo/", - http2::rewrite_clean_path(balloc, StringRef::from_lit("/alpha/%62ravo/")) - .str()); + assert_stdsv_equal("/alpha/bravo/"sv, + http2::rewrite_clean_path(balloc, "/alpha/%62ravo/"_sr)); // percent-encoding is converted to upper case. - assert_stdstring_equal( - "/delta%3A", - http2::rewrite_clean_path(balloc, StringRef::from_lit("/delta%3a")) - .str()); + assert_stdsv_equal("/delta%3A"sv, + http2::rewrite_clean_path(balloc, "/delta%3a"_sr)); // path component is normalized before matching - assert_stdstring_equal( - "/alpha/bravo/", - http2::rewrite_clean_path( - balloc, StringRef::from_lit("/alpha/charlie/%2e././bravo/delta/..")) - .str()); + assert_stdsv_equal("/alpha/bravo/"sv, + http2::rewrite_clean_path( + balloc, "/alpha/charlie/%2e././bravo/delta/.."_sr)); - assert_stdstring_equal( - "alpha%3a", - http2::rewrite_clean_path(balloc, StringRef::from_lit("alpha%3a")).str()); + assert_stdsv_equal("alpha%3a"sv, + http2::rewrite_clean_path(balloc, "alpha%3a"_sr)); - assert_stdstring_equal("", - http2::rewrite_clean_path(balloc, StringRef{}).str()); + assert_stdsv_equal(""sv, http2::rewrite_clean_path(balloc, StringRef{})); - assert_stdstring_equal( - "/alpha?bravo", - http2::rewrite_clean_path(balloc, StringRef::from_lit("//alpha?bravo")) - .str()); + assert_stdsv_equal("/alpha?bravo"sv, + http2::rewrite_clean_path(balloc, "//alpha?bravo"_sr)); } void test_http2_get_pure_path_component(void) { - assert_stdstring_equal( - "/", http2::get_pure_path_component(StringRef::from_lit("/")).str()); + assert_stdsv_equal("/"sv, http2::get_pure_path_component("/"_sr)); - assert_stdstring_equal( - "/foo", - http2::get_pure_path_component(StringRef::from_lit("/foo")).str()); + assert_stdsv_equal("/foo"sv, http2::get_pure_path_component("/foo"_sr)); - assert_stdstring_equal("/bar", - http2::get_pure_path_component( - StringRef::from_lit("https://example.org/bar")) - .str()); + assert_stdsv_equal( + "/bar"sv, http2::get_pure_path_component("https://example.org/bar"_sr)); - assert_stdstring_equal( - "/alpha", http2::get_pure_path_component( - StringRef::from_lit("https://example.org/alpha?q=a")) - .str()); + assert_stdsv_equal("/alpha"sv, http2::get_pure_path_component( + "https://example.org/alpha?q=a"_sr)); - assert_stdstring_equal( - "/bravo", - http2::get_pure_path_component( - StringRef::from_lit("https://example.org/bravo?q=a#fragment")) - .str()); + assert_stdsv_equal("/bravo"sv, + http2::get_pure_path_component( + "https://example.org/bravo?q=a#fragment"_sr)); - assert_stdstring_equal( - "", - http2::get_pure_path_component(StringRef::from_lit("\x01\x02")).str()); + assert_stdsv_equal(""sv, http2::get_pure_path_component("\x01\x02"_sr)); } void test_http2_construct_push_component(void) { @@ -1189,41 +1075,41 @@ void test_http2_construct_push_component(void) { StringRef base, uri; StringRef scheme, authority, path; - base = StringRef::from_lit("/b/"); - uri = StringRef::from_lit("https://example.org/foo"); + base = "/b/"_sr; + uri = "https://example.org/foo"_sr; assert_int(0, ==, http2::construct_push_component(balloc, scheme, authority, path, base, uri)); - assert_stdstring_equal("https", scheme.str()); - assert_stdstring_equal("example.org", authority.str()); - assert_stdstring_equal("/foo", path.str()); + assert_stdsv_equal("https"sv, scheme); + assert_stdsv_equal("example.org"sv, authority); + assert_stdsv_equal("/foo"sv, path); scheme = StringRef{}; authority = StringRef{}; path = StringRef{}; - uri = StringRef::from_lit("/foo/bar?q=a"); + uri = "/foo/bar?q=a"_sr; assert_int(0, ==, http2::construct_push_component(balloc, scheme, authority, path, base, uri)); - assert_stdstring_equal("", scheme.str()); - assert_stdstring_equal("", authority.str()); - assert_stdstring_equal("/foo/bar?q=a", path.str()); + assert_stdsv_equal(""sv, scheme); + assert_stdsv_equal(""sv, authority); + assert_stdsv_equal("/foo/bar?q=a"sv, path); scheme = StringRef{}; authority = StringRef{}; path = StringRef{}; - uri = StringRef::from_lit("foo/../bar?q=a"); + uri = "foo/../bar?q=a"_sr; assert_int(0, ==, http2::construct_push_component(balloc, scheme, authority, path, base, uri)); - assert_stdstring_equal("", scheme.str()); - assert_stdstring_equal("", authority.str()); - assert_stdstring_equal("/b/bar?q=a", path.str()); + assert_stdsv_equal(""sv, scheme); + assert_stdsv_equal(""sv, authority); + assert_stdsv_equal("/b/bar?q=a"sv, path); scheme = StringRef{}; authority = StringRef{}; @@ -1238,91 +1124,69 @@ void test_http2_construct_push_component(void) { authority = StringRef{}; path = StringRef{}; - uri = StringRef::from_lit("?q=a"); + uri = "?q=a"_sr; assert_int(0, ==, http2::construct_push_component(balloc, scheme, authority, path, base, uri)); - assert_stdstring_equal("", scheme.str()); - assert_stdstring_equal("", authority.str()); - assert_stdstring_equal("/b/?q=a", path.str()); + assert_stdsv_equal(""sv, scheme); + assert_stdsv_equal(""sv, authority); + assert_stdsv_equal("/b/?q=a"sv, path); } void test_http2_contains_trailers(void) { - assert_false(http2::contains_trailers(StringRef::from_lit(""))); - assert_true(http2::contains_trailers(StringRef::from_lit("trailers"))); + assert_false(http2::contains_trailers(""_sr)); + assert_true(http2::contains_trailers("trailers"_sr)); // Match must be case-insensitive. - assert_true(http2::contains_trailers(StringRef::from_lit("TRAILERS"))); - assert_false(http2::contains_trailers(StringRef::from_lit("trailer"))); - assert_false(http2::contains_trailers(StringRef::from_lit("trailers 3"))); - assert_true(http2::contains_trailers(StringRef::from_lit("trailers,"))); - assert_true(http2::contains_trailers(StringRef::from_lit("trailers,foo"))); - assert_true(http2::contains_trailers(StringRef::from_lit("foo,trailers"))); - assert_true( - http2::contains_trailers(StringRef::from_lit("foo,trailers,bar"))); - assert_true( - http2::contains_trailers(StringRef::from_lit("foo, trailers ,bar"))); - assert_true(http2::contains_trailers(StringRef::from_lit(",trailers"))); + assert_true(http2::contains_trailers("TRAILERS"_sr)); + assert_false(http2::contains_trailers("trailer"_sr)); + assert_false(http2::contains_trailers("trailers 3"_sr)); + assert_true(http2::contains_trailers("trailers,"_sr)); + assert_true(http2::contains_trailers("trailers,foo"_sr)); + assert_true(http2::contains_trailers("foo,trailers"_sr)); + assert_true(http2::contains_trailers("foo,trailers,bar"_sr)); + assert_true(http2::contains_trailers("foo, trailers ,bar"_sr)); + assert_true(http2::contains_trailers(",trailers"_sr)); } void test_http2_check_transfer_encoding(void) { - assert_true(http2::check_transfer_encoding(StringRef::from_lit("chunked"))); - assert_true( - http2::check_transfer_encoding(StringRef::from_lit("foo,chunked"))); - assert_true( - http2::check_transfer_encoding(StringRef::from_lit("foo, chunked"))); - assert_true( - http2::check_transfer_encoding(StringRef::from_lit("foo , chunked"))); - assert_true( - http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar"))); - assert_true( - http2::check_transfer_encoding(StringRef::from_lit("chunked ; foo=bar"))); - assert_true(http2::check_transfer_encoding( - StringRef::from_lit(R"(chunked;foo="bar")"))); - assert_true(http2::check_transfer_encoding( - StringRef::from_lit(R"(chunked;foo="\bar\"";FOO=BAR)"))); + assert_true(http2::check_transfer_encoding("chunked"_sr)); + assert_true(http2::check_transfer_encoding("foo,chunked"_sr)); + assert_true(http2::check_transfer_encoding("foo, chunked"_sr)); + assert_true(http2::check_transfer_encoding("foo , chunked"_sr)); + assert_true(http2::check_transfer_encoding("chunked;foo=bar"_sr)); + assert_true(http2::check_transfer_encoding("chunked ; foo=bar"_sr)); + assert_true(http2::check_transfer_encoding(R"(chunked;foo="bar")"_sr)); assert_true( - http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="")"))); - assert_true(http2::check_transfer_encoding( - StringRef::from_lit(R"(chunked;foo="bar" , gzip)"))); + http2::check_transfer_encoding(R"(chunked;foo="\bar\"";FOO=BAR)"_sr)); + assert_true(http2::check_transfer_encoding(R"(chunked;foo="")"_sr)); + assert_true(http2::check_transfer_encoding(R"(chunked;foo="bar" , gzip)"_sr)); assert_false(http2::check_transfer_encoding(StringRef{})); - assert_false(http2::check_transfer_encoding(StringRef::from_lit(",chunked"))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit("chunked,"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("chunked, "))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("foo,,chunked"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("chunked;foo"))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit("chunked;"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar;"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("chunked;?=bar"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("chunked;=bar"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit("chunked;;"))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit("chunked?"))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit(","))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit(" "))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit(";"))); - assert_false(http2::check_transfer_encoding(StringRef::from_lit("\""))); - assert_false(http2::check_transfer_encoding( - StringRef::from_lit(R"(chunked;foo="bar)"))); - assert_false(http2::check_transfer_encoding( - StringRef::from_lit(R"(chunked;foo="bar\)"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="bar\)" - "\x0a" - R"(")"))); - assert_false( - http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo=")" - "\x0a" - R"(")"))); - assert_false(http2::check_transfer_encoding( - StringRef::from_lit(R"(chunked;foo="bar",,gzip)"))); + assert_false(http2::check_transfer_encoding(",chunked"_sr)); + assert_false(http2::check_transfer_encoding("chunked,"_sr)); + assert_false(http2::check_transfer_encoding("chunked, "_sr)); + assert_false(http2::check_transfer_encoding("foo,,chunked"_sr)); + assert_false(http2::check_transfer_encoding("chunked;foo"_sr)); + assert_false(http2::check_transfer_encoding("chunked;"_sr)); + assert_false(http2::check_transfer_encoding("chunked;foo=bar;"_sr)); + assert_false(http2::check_transfer_encoding("chunked;?=bar"_sr)); + assert_false(http2::check_transfer_encoding("chunked;=bar"_sr)); + assert_false(http2::check_transfer_encoding("chunked;;"_sr)); + assert_false(http2::check_transfer_encoding("chunked?"_sr)); + assert_false(http2::check_transfer_encoding(","_sr)); + assert_false(http2::check_transfer_encoding(" "_sr)); + assert_false(http2::check_transfer_encoding(";"_sr)); + assert_false(http2::check_transfer_encoding("\""_sr)); + assert_false(http2::check_transfer_encoding(R"(chunked;foo="bar)"_sr)); + assert_false(http2::check_transfer_encoding(R"(chunked;foo="bar\)"_sr)); + assert_false(http2::check_transfer_encoding(R"(chunked;foo="bar\)" + "\x0a" + R"(")"_sr)); + assert_false(http2::check_transfer_encoding(R"(chunked;foo=")" + "\x0a" + R"(")"_sr)); + assert_false(http2::check_transfer_encoding(R"(chunked;foo="bar",,gzip)"_sr)); } } // namespace shrpx diff --git a/src/http3.cc b/src/http3.cc index 61134ad..9bf33de 100644 --- a/src/http3.cc +++ b/src/http3.cc @@ -29,56 +29,6 @@ namespace nghttp2 { namespace http3 { namespace { -nghttp3_nv make_nv_internal(const std::string &name, const std::string &value, - bool never_index, uint8_t nv_flags) { - uint8_t flags; - - flags = nv_flags | - (never_index ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE); - - return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), - value.size(), flags}; -} -} // namespace - -namespace { -nghttp3_nv make_nv_internal(const StringRef &name, const StringRef &value, - bool never_index, uint8_t nv_flags) { - uint8_t flags; - - flags = nv_flags | - (never_index ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE); - - return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), - value.size(), flags}; -} -} // namespace - -nghttp3_nv make_nv(const std::string &name, const std::string &value, - bool never_index) { - return make_nv_internal(name, value, never_index, NGHTTP3_NV_FLAG_NONE); -} - -nghttp3_nv make_nv(const StringRef &name, const StringRef &value, - bool never_index) { - return make_nv_internal(name, value, never_index, NGHTTP3_NV_FLAG_NONE); -} - -nghttp3_nv make_nv_nocopy(const std::string &name, const std::string &value, - bool never_index) { - return make_nv_internal(name, value, never_index, - NGHTTP3_NV_FLAG_NO_COPY_NAME | - NGHTTP3_NV_FLAG_NO_COPY_VALUE); -} - -nghttp3_nv make_nv_nocopy(const StringRef &name, const StringRef &value, - bool never_index) { - return make_nv_internal(name, value, never_index, - NGHTTP3_NV_FLAG_NO_COPY_NAME | - NGHTTP3_NV_FLAG_NO_COPY_VALUE); -} - -namespace { void copy_headers_to_nva_internal(std::vector<nghttp3_nv> &nva, const HeaderRefs &headers, uint8_t nv_flags, uint32_t flags) { @@ -172,17 +122,12 @@ void copy_headers_to_nva_internal(std::vector<nghttp3_nv> &nva, it_via = it; break; } - nva.push_back( - make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags)); + nva.push_back(make_field_flags(kv->name, kv->value, + nv_flags | never_index(kv->no_index))); } } } // namespace -void copy_headers_to_nva(std::vector<nghttp3_nv> &nva, - const HeaderRefs &headers, uint32_t flags) { - copy_headers_to_nva_internal(nva, headers, NGHTTP3_NV_FLAG_NONE, flags); -} - void copy_headers_to_nva_nocopy(std::vector<nghttp3_nv> &nva, const HeaderRefs &headers, uint32_t flags) { copy_headers_to_nva_internal( @@ -190,17 +135,6 @@ void copy_headers_to_nva_nocopy(std::vector<nghttp3_nv> &nva, NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE, flags); } -int check_nv(const uint8_t *name, size_t namelen, const uint8_t *value, - size_t valuelen) { - if (!nghttp3_check_header_name(name, namelen)) { - return 0; - } - if (!nghttp3_check_header_value(value, valuelen)) { - return 0; - } - return 1; -} - } // namespace http3 } // namespace nghttp2 diff --git a/src/http3.h b/src/http3.h index 81ee0d7..cd68922 100644 --- a/src/http3.h +++ b/src/http3.h @@ -40,82 +40,38 @@ namespace nghttp2 { namespace http3 { -// Creates nghttp3_nv using |name| and |value| and returns it. The -// returned value only references the data pointer to name.c_str() and -// value.c_str(). If |no_index| is true, nghttp3_nv flags member has -// NGHTTP3_NV_FLAG_NEVER_INDEX flag set. -nghttp3_nv make_nv(const std::string &name, const std::string &value, - bool never_index = false); - -nghttp3_nv make_nv(const StringRef &name, const StringRef &value, - bool never_index = false); - -nghttp3_nv make_nv_nocopy(const std::string &name, const std::string &value, - bool never_index = false); - -nghttp3_nv make_nv_nocopy(const StringRef &name, const StringRef &value, - bool never_index = false); - -// Create nghttp3_nv from string literal |name| and |value|. -template <size_t N, size_t M> -constexpr nghttp3_nv make_nv_ll(const char (&name)[N], const char (&value)[M]) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, M - 1, - NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE}; -} - -// Create nghttp3_nv from string literal |name| and c-string |value|. -template <size_t N> -nghttp3_nv make_nv_lc(const char (&name)[N], const char *value) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), - NGHTTP3_NV_FLAG_NO_COPY_NAME}; +// Create nghttp3_nv from |name|, |value| and |flags|. +inline nghttp3_nv make_field_flags(const StringRef &name, + const StringRef &value, + uint8_t flags = NGHTTP3_NV_FLAG_NONE) { + auto ns = as_uint8_span(std::span{name}); + auto vs = as_uint8_span(std::span{value}); + + return {const_cast<uint8_t *>(ns.data()), const_cast<uint8_t *>(vs.data()), + ns.size(), vs.size(), flags}; } -template <size_t N> -nghttp3_nv make_nv_lc_nocopy(const char (&name)[N], const char *value) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), - NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE}; +// Creates nghttp3_nv from |name|, |value| and |flags|. nghttp3 +// library does not copy them. +inline nghttp3_nv make_field(const StringRef &name, const StringRef &value, + uint8_t flags = NGHTTP3_NV_FLAG_NONE) { + return make_field_flags(name, value, + static_cast<uint8_t>(NGHTTP3_NV_FLAG_NO_COPY_NAME | + NGHTTP3_NV_FLAG_NO_COPY_VALUE | + flags)); } -// Create nghttp3_nv from string literal |name| and std::string -// |value|. -template <size_t N> -nghttp3_nv make_nv_ls(const char (&name)[N], const std::string &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP3_NV_FLAG_NO_COPY_NAME}; +// Returns NGHTTP3_NV_FLAG_NEVER_INDEX if |never_index| is true, +// otherwise NGHTTP3_NV_FLAG_NONE. +inline uint8_t never_index(bool never_index) { + return never_index ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE; } -template <size_t N> -nghttp3_nv make_nv_ls_nocopy(const char (&name)[N], const std::string &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE}; -} - -template <size_t N> -nghttp3_nv make_nv_ls_nocopy(const char (&name)[N], const StringRef &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE}; -} - -// Appends headers in |headers| to |nv|. |headers| must be indexed -// before this call (its element's token field is assigned). Certain -// headers, including disallowed headers in HTTP/3 spec and headers -// which require special handling (i.e. via), are not copied. |flags| -// is one or more of HeaderBuildOp flags. They tell function that -// certain header fields should not be added. -void copy_headers_to_nva(std::vector<nghttp3_nv> &nva, - const HeaderRefs &headers, uint32_t flags); - // Just like copy_headers_to_nva(), but this adds // NGHTTP3_NV_FLAG_NO_COPY_NAME and NGHTTP3_NV_FLAG_NO_COPY_VALUE. void copy_headers_to_nva_nocopy(std::vector<nghttp3_nv> &nva, const HeaderRefs &headers, uint32_t flags); -// Checks the header name/value pair using nghttp3_check_header_name() -// and nghttp3_check_header_value(). If both function returns nonzero, -// this function returns nonzero. -int check_nv(const uint8_t *name, size_t namelen, const uint8_t *value, - size_t valuelen); - } // namespace http3 } // namespace nghttp2 diff --git a/src/memchunk.h b/src/memchunk.h index 7a7f2e9..7026184 100644 --- a/src/memchunk.h +++ b/src/memchunk.h @@ -199,7 +199,7 @@ template <typename Memchunk> struct Memchunks { return append(s, N - 1); } size_t append(const std::string &s) { return append(s.c_str(), s.size()); } - size_t append(const StringRef &s) { return append(s.c_str(), s.size()); } + size_t append(const StringRef &s) { return append(s.data(), s.size()); } size_t append(const ImmutableString &s) { return append(s.c_str(), s.size()); } diff --git a/src/nghttp.cc b/src/nghttp.cc index 6684374..8ca37bb 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -89,13 +89,13 @@ enum { }; namespace { -constexpr auto anchors = std::array<Anchor, 5>{{ +constexpr auto anchors = std::to_array<Anchor>({ {3, 0, 201}, {5, 0, 101}, {7, 0, 1}, {9, 7, 1}, {11, 3, 1}, -}}; +}); } // namespace Config::Config() @@ -201,9 +201,9 @@ StringRef Request::get_real_host() const { uint16_t Request::get_real_port() const { auto scheme = get_real_scheme(); return config.host_override.empty() ? util::has_uri_field(u, UF_PORT) ? u.port - : scheme == "https" ? 443 + : scheme == "https"_sr ? 443 : 80 - : config.port_override == 0 ? scheme == "https" ? 443 : 80 + : config.port_override == 0 ? scheme == "https"_sr ? 443 : 80 : config.port_override; } @@ -215,7 +215,7 @@ void Request::init_html_parser() { auto ipv6_lit = std::find(std::begin(host), std::end(host), ':') != std::end(host); - auto base_uri = scheme.str(); + auto base_uri = std::string{scheme}; base_uri += "://"; if (ipv6_lit) { base_uri += '['; @@ -224,8 +224,8 @@ void Request::init_html_parser() { if (ipv6_lit) { base_uri += ']'; } - if (!((scheme == "https" && port == 443) || - (scheme == "http" && port == 80))) { + if (!((scheme == "https"_sr && port == 443) || + (scheme == "http"_sr && port == 80))) { base_uri += ':'; base_uri += util::utos(port); } @@ -247,9 +247,9 @@ int Request::update_html_parser(const uint8_t *data, size_t len, int fin) { } std::string Request::make_reqpath() const { - std::string path = util::has_uri_field(u, UF_PATH) - ? util::get_uri_field(uri.c_str(), u, UF_PATH).str() - : "/"; + auto path = util::has_uri_field(u, UF_PATH) + ? std::string{util::get_uri_field(uri.c_str(), u, UF_PATH)} + : "/"s; if (util::has_uri_field(u, UF_QUERY)) { path += '?'; path.append(uri.c_str() + u.field_data[UF_QUERY].off, @@ -266,15 +266,15 @@ std::string decode_host(const StringRef &host) { if (zone_start == std::end(host) || !util::ipv6_numeric_addr( std::string(std::begin(host), zone_start).c_str())) { - return host.str(); + return std::string{host}; } // case: ::1% if (zone_start + 1 == std::end(host)) { - return StringRef{host.c_str(), host.size() - 1}.str(); + return {host.data(), host.size() - 1}; } // case: ::1%12 or ::1%1 if (zone_start + 3 >= std::end(host)) { - return host.str(); + return std::string{host}; } // If we see "%25", followed by more characters, then decode %25 as // '%'. @@ -454,7 +454,7 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) { auto scheme = util::get_uri_field(req->uri.c_str(), req->u, UF_SCHEMA); auto build_headers = Headers{{":method", req->data_prd ? "POST" : "GET"}, {":path", req->make_reqpath()}, - {":scheme", scheme.str()}, + {":scheme", std::string{scheme}}, {":authority", client->hostport}, {"accept", "*/*"}, {"accept-encoding", "gzip, deflate"}, @@ -500,7 +500,8 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) { nva.reserve(build_headers.size()); for (auto &kv : build_headers) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + nva.push_back( + http2::make_field_nv(kv.name, kv.value, http2::no_index(kv.no_index))); } auto method = http2::get_header(build_headers, ":method"); @@ -515,7 +516,7 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) { trailer_names += ", "; trailer_names += config.trailer[i].name; } - nva.push_back(http2::make_nv_ls("trailer", trailer_names)); + nva.push_back(http2::make_field_v("trailer"_sr, trailer_names)); } int32_t stream_id; @@ -975,9 +976,9 @@ int HttpClient::on_upgrade_connect() { // If the request contains upload data, use OPTIONS * to upgrade req = "OPTIONS *"; } else { - auto meth = std::find_if( - std::begin(config.headers), std::end(config.headers), - [](const Header &kv) { return util::streq_l(":method", kv.name); }); + auto meth = + std::find_if(std::begin(config.headers), std::end(config.headers), + [](const auto &kv) { return ":method"_sr == kv.name; }); if (meth == std::end(config.headers)) { req = "GET "; @@ -1424,8 +1425,7 @@ void HttpClient::update_hostport() { if (reqvec.empty()) { return; } - scheme = util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA) - .str(); + scheme = util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA); std::stringstream ss; if (reqvec[0]->is_ipv6_literal_addr()) { // we may have zone ID, which must start with "%25", or "%". RFC @@ -1435,7 +1435,7 @@ void HttpClient::update_hostport() { util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST); auto end = std::find(std::begin(host), std::end(host), '%'); ss << "["; - ss.write(host.c_str(), end - std::begin(host)); + ss.write(host.data(), end - std::begin(host)); ss << "]"; } else { util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST); @@ -1688,7 +1688,7 @@ void update_html_parser(HttpClient *client, Request *req, const uint8_t *data, } auto link_port = util::has_uri_field(u, UF_PORT) ? u.port - : scheme == "https" ? 443 + : scheme == "https"_sr ? 443 : 80; if (port != link_port) { @@ -1800,8 +1800,8 @@ void check_response_header(nghttp2_session *session, Request *req) { for (auto &nv : req->res_nva) { if ("content-encoding" == nv.name) { - gzip = util::strieq_l("gzip", nv.value) || - util::strieq_l("deflate", nv.value); + gzip = util::strieq("gzip"_sr, nv.value) || + util::strieq("deflate"_sr, nv.value); continue; } } @@ -1915,10 +1915,12 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, req->header_buffer_size += namelen + valuelen; - auto token = http2::lookup_token(name, namelen); + auto nameref = StringRef{name, namelen}; + auto valueref = StringRef{value, valuelen}; + auto token = http2::lookup_token(nameref); http2::index_header(req->res_hdidx, token, req->res_nva.size()); - http2::add_header(req->res_nva, name, namelen, value, valuelen, + http2::add_header(req->res_nva, nameref, valueref, flags & NGHTTP2_NV_FLAG_NO_INDEX, token); break; } @@ -1939,10 +1941,12 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, req->header_buffer_size += namelen + valuelen; - auto token = http2::lookup_token(name, namelen); + auto nameref = StringRef{name, namelen}; + auto valueref = StringRef{value, valuelen}; + auto token = http2::lookup_token(nameref); http2::index_header(req->req_hdidx, token, req->req_nva.size()); - http2::add_header(req->req_nva, name, namelen, value, valuelen, + http2::add_header(req->req_nva, nameref, valueref, flags & NGHTTP2_NV_FLAG_NO_INDEX, token); break; } @@ -2283,7 +2287,8 @@ int communicate( goto fin; } - if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST) == 0) { + if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST.data()) == + 0) { std::cerr << "[ERROR] " << ERR_error_string(ERR_get_error(), nullptr) << std::endl; result = -1; @@ -2437,7 +2442,8 @@ nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id, std::vector<nghttp2_nv> nva; nva.reserve(config.trailer.size()); for (auto &kv : config.trailer) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + nva.push_back(http2::make_field_nv(kv.name, kv.value, + http2::no_index(kv.no_index))); } rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); if (rv != 0) { @@ -2609,7 +2615,7 @@ int run(char **uris, int n) { } requests.clear(); } - prev_scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA).str(); + prev_scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); prev_host = std::move(host); prev_port = port; } @@ -2818,11 +2824,11 @@ int main(int argc, char **argv) { case 'M': { // peer-max-concurrent-streams option auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-M: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.peer_max_concurrent_streams = n; + config.peer_max_concurrent_streams = *n; break; } case 'O': @@ -2833,11 +2839,11 @@ int main(int argc, char **argv) { exit(EXIT_SUCCESS); case 'b': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-b: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.padding = n; + config.padding = *n; break; } case 'n': @@ -2845,13 +2851,13 @@ int main(int argc, char **argv) { break; case 'p': { auto n = util::parse_uint(optarg); - if (n == -1 || NGHTTP2_MIN_WEIGHT > n || n > NGHTTP2_MAX_WEIGHT) { + if (!n || NGHTTP2_MIN_WEIGHT > n || n > NGHTTP2_MAX_WEIGHT) { std::cerr << "-p: specify the integer in the range [" << NGHTTP2_MIN_WEIGHT << ", " << NGHTTP2_MAX_WEIGHT << "], inclusive" << std::endl; exit(EXIT_FAILURE); } - config.weight.push_back(n); + config.weight.push_back(*n); break; } case 'r': @@ -2865,29 +2871,31 @@ int main(int argc, char **argv) { case 'v': ++config.verbose; break; - case 't': - config.timeout = util::parse_duration_with_unit(optarg); - if (config.timeout == std::numeric_limits<double>::infinity()) { + case 't': { + auto d = util::parse_duration_with_unit(optarg); + if (!d) { std::cerr << "-t: bad timeout value: " << optarg << std::endl; exit(EXIT_FAILURE); } + config.timeout = *d; break; + } case 'u': config.upgrade = true; break; case 'w': case 'W': { auto n = util::parse_uint(optarg); - if (n == -1 || n > 30) { + if (!n || n > 30) { std::cerr << "-" << static_cast<char>(c) << ": specify the integer in the range [0, 30], inclusive" << std::endl; exit(EXIT_FAILURE); } if (c == 'w') { - config.window_bits = n; + config.window_bits = *n; } else { - config.connection_window_bits = n; + config.connection_window_bits = *n; } break; } @@ -2931,16 +2939,16 @@ int main(int argc, char **argv) { break; case 'm': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-m: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.multiply = n; + config.multiply = *n; break; } case 'c': { auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "-c: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } @@ -2949,8 +2957,8 @@ int main(int argc, char **argv) { << std::numeric_limits<uint32_t>::max() << std::endl; exit(EXIT_FAILURE); } - config.header_table_size = n; - config.min_header_table_size = std::min(config.min_header_table_size, n); + config.header_table_size = *n; + config.min_header_table_size = std::min(config.min_header_table_size, *n); break; } case 'y': @@ -3024,12 +3032,12 @@ int main(int argc, char **argv) { case 12: { // max-concurrent-streams option auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "--max-concurrent-streams: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.max_concurrent_streams = n; + config.max_concurrent_streams = *n; break; } case 13: @@ -3039,7 +3047,7 @@ int main(int argc, char **argv) { case 14: { // encoder-header-table-size option auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "--encoder-header-table-size: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); @@ -3050,7 +3058,7 @@ int main(int argc, char **argv) { << std::numeric_limits<uint32_t>::max() << std::endl; exit(EXIT_FAILURE); } - config.encoder_header_table_size = n; + config.encoder_header_table_size = *n; break; } case 15: @@ -3105,7 +3113,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - config.host_override = util::get_uri_field(uri.c_str(), u, UF_HOST).str(); + config.host_override = util::get_uri_field(uri.c_str(), u, UF_HOST); if (util::has_uri_field(u, UF_PORT)) { config.port_override = u.port; } diff --git a/src/nghttpd.cc b/src/nghttpd.cc index 9cad874..de62953 100644 --- a/src/nghttpd.cc +++ b/src/nghttpd.cc @@ -246,11 +246,11 @@ int main(int argc, char **argv) { break; case 'b': { auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-b: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.padding = n; + config.padding = *n; break; } case 'd': @@ -262,11 +262,11 @@ int main(int argc, char **argv) { case 'm': { // max-concurrent-streams option auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-m: invalid argument: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.max_concurrent_streams = n; + config.max_concurrent_streams = *n; break; } case 'n': { @@ -275,11 +275,11 @@ int main(int argc, char **argv) { << "no threads created." << std::endl; #else auto n = util::parse_uint(optarg); - if (n == -1) { + if (!n) { std::cerr << "-n: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.num_worker = n; + config.num_worker = *n; #endif // NOTHREADS break; } @@ -291,7 +291,7 @@ int main(int argc, char **argv) { break; case 'c': { auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "-c: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } @@ -300,7 +300,7 @@ int main(int argc, char **argv) { << std::numeric_limits<uint32_t>::max() << std::endl; exit(EXIT_FAILURE); } - config.header_table_size = n; + config.header_table_size = *n; break; } case 'p': @@ -311,7 +311,7 @@ int main(int argc, char **argv) { case 'w': case 'W': { auto n = util::parse_uint(optarg); - if (n == -1 || n > 30) { + if (!n || n > 30) { std::cerr << "-" << static_cast<char>(c) << ": specify the integer in the range [0, 30], inclusive" << std::endl; @@ -319,9 +319,9 @@ int main(int argc, char **argv) { } if (c == 'w') { - config.window_bits = n; + config.window_bits = *n; } else { - config.connection_window_bits = n; + config.connection_window_bits = *n; } break; @@ -395,7 +395,7 @@ int main(int argc, char **argv) { case 11: { // encoder-header-table-size option auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { std::cerr << "--encoder-header-table-size: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); @@ -406,7 +406,7 @@ int main(int argc, char **argv) { << std::numeric_limits<uint32_t>::max() << std::endl; exit(EXIT_FAILURE); } - config.encoder_header_table_size = n; + config.encoder_header_table_size = *n; break; } case 12: @@ -432,11 +432,11 @@ int main(int argc, char **argv) { { auto portStr = argv[optind++]; auto n = util::parse_uint(portStr); - if (n == -1 || n > std::numeric_limits<uint16_t>::max()) { + if (!n || n > std::numeric_limits<uint16_t>::max()) { std::cerr << "<PORT>: Bad value: " << portStr << std::endl; exit(EXIT_FAILURE); } - config.port = n; + config.port = *n; } if (!config.no_tls) { diff --git a/src/shrpx.cc b/src/shrpx.cc index 89a7787..86d00dc 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -71,6 +71,7 @@ #include <vector> #include <initializer_list> #include <random> +#include <span> #include <openssl/ssl.h> #include <openssl/err.h> @@ -112,19 +113,19 @@ namespace shrpx { // Deprecated: Environment variables to tell new binary the listening // socket's file descriptors. They are not close-on-exec. -constexpr auto ENV_LISTENER4_FD = StringRef::from_lit("NGHTTPX_LISTENER4_FD"); -constexpr auto ENV_LISTENER6_FD = StringRef::from_lit("NGHTTPX_LISTENER6_FD"); +constexpr auto ENV_LISTENER4_FD = "NGHTTPX_LISTENER4_FD"_sr; +constexpr auto ENV_LISTENER6_FD = "NGHTTPX_LISTENER6_FD"_sr; // Deprecated: Environment variable to tell new binary the port number // the current binary is listening to. -constexpr auto ENV_PORT = StringRef::from_lit("NGHTTPX_PORT"); +constexpr auto ENV_PORT = "NGHTTPX_PORT"_sr; // Deprecated: Environment variable to tell new binary the listening // socket's file descriptor if frontend listens UNIX domain socket. -constexpr auto ENV_UNIX_FD = StringRef::from_lit("NGHTTP2_UNIX_FD"); +constexpr auto ENV_UNIX_FD = "NGHTTP2_UNIX_FD"_sr; // Deprecated: Environment variable to tell new binary the UNIX domain // socket path. -constexpr auto ENV_UNIX_PATH = StringRef::from_lit("NGHTTP2_UNIX_PATH"); +constexpr auto ENV_UNIX_PATH = "NGHTTP2_UNIX_PATH"_sr; // Prefix of environment variables to tell new binary the listening // socket's file descriptor. They are not close-on-exec. For TCP @@ -132,13 +133,13 @@ constexpr auto ENV_UNIX_PATH = StringRef::from_lit("NGHTTP2_UNIX_PATH"); // <FD> is file descriptor. For UNIX domain socket, the value must be // comma separated 3 parameters: unix,<FD>,<PATH>. <FD> is file // descriptor. <PATH> is a path to UNIX domain socket. -constexpr auto ENV_ACCEPT_PREFIX = StringRef::from_lit("NGHTTPX_ACCEPT_"); +constexpr auto ENV_ACCEPT_PREFIX = "NGHTTPX_ACCEPT_"_sr; // This environment variable contains PID of the original main // process, assuming that it created this main process as a result of // SIGUSR2. The new main process is expected to send QUIT signal to // the original main process to shut it down gracefully. -constexpr auto ENV_ORIG_PID = StringRef::from_lit("NGHTTPX_ORIG_PID"); +constexpr auto ENV_ORIG_PID = "NGHTTPX_ORIG_PID"_sr; // Prefix of environment variables to tell new binary the QUIC IPC // file descriptor and Worker ID of the lingering worker process. The @@ -149,7 +150,7 @@ constexpr auto ENV_ORIG_PID = StringRef::from_lit("NGHTTPX_ORIG_PID"); // <FD> is the file descriptor. <WORKER_ID_I> is the I-th Worker ID // in hex encoded string. constexpr auto ENV_QUIC_WORKER_PROCESS_PREFIX = - StringRef::from_lit("NGHTTPX_QUIC_WORKER_PROCESS_"); + "NGHTTPX_QUIC_WORKER_PROCESS_"_sr; #ifndef _KERNEL_FASTOPEN # define _KERNEL_FASTOPEN @@ -398,7 +399,7 @@ int save_pid() { std::array<char, STRERROR_BUFSIZE> errbuf; auto config = get_config(); - constexpr auto SUFFIX = StringRef::from_lit(".XXXXXX"); + constexpr auto SUFFIX = ".XXXXXX"_sr; auto &pid_file = config->pid_file; auto len = config->pid_file.size() + SUFFIX.size(); @@ -437,7 +438,7 @@ int save_pid() { close(fd); - if (rename(temp_path, pid_file.c_str()) == -1) { + if (rename(temp_path, pid_file.data()) == -1) { auto error = errno; LOG(ERROR) << "Could not save PID to file " << pid_file << ": " << xsi_strerror(error, errbuf.data(), errbuf.size()); @@ -448,7 +449,7 @@ int save_pid() { } if (config->uid != 0) { - if (chown(pid_file.c_str(), config->uid, config->gid) == -1) { + if (chown(pid_file.data(), config->uid, config->gid) == -1) { auto error = errno; LOG(WARN) << "Changing owner of pid file " << pid_file << " failed: " << xsi_strerror(error, errbuf.data(), errbuf.size()); @@ -558,7 +559,7 @@ void exec_binary() { std::vector<ImmutableString> fd_envs; for (size_t i = 0; i < listenerconf.addrs.size(); ++i) { auto &addr = listenerconf.addrs[i]; - auto s = ENV_ACCEPT_PREFIX.str(); + auto s = std::string{ENV_ACCEPT_PREFIX}; s += util::utos(i + 1); s += '='; if (addr.host_unix) { @@ -575,7 +576,7 @@ void exec_binary() { envp[envidx++] = const_cast<char *>(fd_envs.back().c_str()); } - auto ipc_fd_str = ENV_ORIG_PID.str(); + auto ipc_fd_str = std::string{ENV_ORIG_PID}; ipc_fd_str += '='; ipc_fd_str += util::utos(config->pid); envp[envidx++] = const_cast<char *>(ipc_fd_str.c_str()); @@ -584,14 +585,13 @@ void exec_binary() { std::vector<ImmutableString> quic_lwps; for (size_t i = 0; i < worker_processes.size(); ++i) { auto &wp = worker_processes[i]; - auto s = ENV_QUIC_WORKER_PROCESS_PREFIX.str(); + auto s = std::string{ENV_QUIC_WORKER_PROCESS_PREFIX}; s += util::utos(i + 1); s += '='; s += util::utos(wp->quic_ipc_fd); for (auto &wid : wp->worker_ids) { s += ','; - s += util::format_hex(reinterpret_cast<const unsigned char *>(&wid), - sizeof(wid)); + s += util::format_hex(std::span{&wid, 1}); } quic_lwps.emplace_back(s); @@ -741,7 +741,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr, << (faddr.tls ? ", tls" : ""); (*found).used = true; faddr.fd = (*found).fd; - faddr.hostport = StringRef::from_lit("localhost"); + faddr.hostport = "localhost"_sr; return 0; } @@ -783,10 +783,10 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr, return -1; } // copy path including terminal NULL - std::copy_n(faddr.host.c_str(), faddr.host.size() + 1, addr.un.sun_path); + std::copy_n(faddr.host.data(), faddr.host.size() + 1, addr.un.sun_path); // unlink (remove) already existing UNIX domain socket path - unlink(faddr.host.c_str()); + unlink(faddr.host.data()); if (bind(fd, &addr.sa, sizeof(addr.un)) != 0) { auto error = errno; @@ -810,7 +810,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr, << (faddr.tls ? ", tls" : ""); faddr.fd = fd; - faddr.hostport = StringRef::from_lit("localhost"); + faddr.hostport = "localhost"_sr; return 0; } @@ -834,8 +834,7 @@ int create_tcp_server_socket(UpstreamAddr &faddr, hints.ai_flags |= AI_ADDRCONFIG; #endif // AI_ADDRCONFIG - auto node = - faddr.host == StringRef::from_lit("*") ? nullptr : faddr.host.c_str(); + auto node = faddr.host == "*"_sr ? nullptr : faddr.host.data(); addrinfo *res, *rp; rv = getaddrinfo(node, service.c_str(), &hints, &res); @@ -867,10 +866,12 @@ int create_tcp_server_socket(UpstreamAddr &faddr, continue; } + auto host_sr = StringRef{host.data()}; + auto found = std::find_if(std::begin(iaddrs), std::end(iaddrs), - [&host, &faddr](const InheritedAddr &ia) { + [&host_sr, &faddr](const InheritedAddr &ia) { return !ia.used && !ia.host_unix && - ia.host == host.data() && + ia.host == host_sr && ia.port == faddr.port; }); @@ -1056,13 +1057,13 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { { // Upgrade from 1.7.0 or earlier - auto portenv = getenv(ENV_PORT.c_str()); + auto portenv = getenv(ENV_PORT.data()); if (portenv) { size_t i = 1; for (const auto &env_name : {ENV_LISTENER4_FD, ENV_LISTENER6_FD}) { - auto fdenv = getenv(env_name.c_str()); + auto fdenv = getenv(env_name.data()); if (fdenv) { - auto name = ENV_ACCEPT_PREFIX.str(); + auto name = std::string{ENV_ACCEPT_PREFIX}; name += util::utos(i); std::string value = "tcp,"; value += fdenv; @@ -1072,20 +1073,20 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { } } else { // The return value of getenv may be allocated statically. - if (getenv(ENV_UNIX_PATH.c_str()) && getenv(ENV_UNIX_FD.c_str())) { - auto name = ENV_ACCEPT_PREFIX.str(); + if (getenv(ENV_UNIX_PATH.data()) && getenv(ENV_UNIX_FD.data())) { + auto name = std::string{ENV_ACCEPT_PREFIX}; name += '1'; std::string value = "unix,"; - value += getenv(ENV_UNIX_FD.c_str()); + value += getenv(ENV_UNIX_FD.data()); value += ','; - value += getenv(ENV_UNIX_PATH.c_str()); + value += getenv(ENV_UNIX_PATH.data()); setenv(name.c_str(), value.c_str(), 0); } } } for (size_t i = 1;; ++i) { - auto name = ENV_ACCEPT_PREFIX.str(); + auto name = std::string{ENV_ACCEPT_PREFIX}; name += util::utos(i); auto env = getenv(name.c_str()); if (!env) { @@ -1104,14 +1105,13 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { auto type = StringRef(env, end_type); auto value = end_type + 1; - if (type == StringRef::from_lit("unix")) { + if (type == "unix"_sr) { auto endfd = strchr(value, ','); if (!endfd) { continue; } - auto fd = util::parse_uint(reinterpret_cast<const uint8_t *>(value), - endfd - value); - if (fd == -1) { + auto fd = util::parse_uint(StringRef{value, endfd}); + if (!fd) { LOG(WARN) << "Could not parse file descriptor from " << std::string(value, endfd - value); continue; @@ -1119,26 +1119,26 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { auto path = endfd + 1; if (strlen(path) == 0) { - LOG(WARN) << "Empty UNIX domain socket path (fd=" << fd << ")"; - close(fd); + LOG(WARN) << "Empty UNIX domain socket path (fd=" << *fd << ")"; + close(*fd); continue; } if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Inherit UNIX domain socket fd=" << fd + LOG(INFO) << "Inherit UNIX domain socket fd=" << *fd << ", path=" << path; } InheritedAddr addr{}; addr.host = make_string_ref(config->balloc, StringRef{path}); addr.host_unix = true; - addr.fd = static_cast<int>(fd); + addr.fd = static_cast<int>(*fd); iaddrs.push_back(std::move(addr)); } - if (type == StringRef::from_lit("tcp")) { + if (type == "tcp"_sr) { auto fd = util::parse_uint(value); - if (fd == -1) { + if (!fd) { LOG(WARN) << "Could not parse file descriptor from " << value; continue; } @@ -1146,11 +1146,11 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { sockaddr_union su; socklen_t salen = sizeof(su); - if (getsockname(fd, &su.sa, &salen) != 0) { + if (getsockname(*fd, &su.sa, &salen) != 0) { auto error = errno; - LOG(WARN) << "getsockname() syscall failed (fd=" << fd + LOG(WARN) << "getsockname() syscall failed (fd=" << *fd << "): " << xsi_strerror(error, errbuf.data(), errbuf.size()); - close(fd); + close(*fd); continue; } @@ -1164,7 +1164,7 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { port = ntohs(su.in6.sin6_port); break; default: - close(fd); + close(*fd); continue; } @@ -1172,21 +1172,21 @@ std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) { rv = getnameinfo(&su.sa, salen, host.data(), host.size(), nullptr, 0, NI_NUMERICHOST); if (rv != 0) { - LOG(WARN) << "getnameinfo() failed (fd=" << fd + LOG(WARN) << "getnameinfo() failed (fd=" << *fd << "): " << gai_strerror(rv); - close(fd); + close(*fd); continue; } if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Inherit TCP socket fd=" << fd + LOG(INFO) << "Inherit TCP socket fd=" << *fd << ", address=" << host.data() << ", port=" << port; } InheritedAddr addr{}; addr.host = make_string_ref(config->balloc, StringRef{host.data()}); addr.port = static_cast<uint16_t>(port); - addr.fd = static_cast<int>(fd); + addr.fd = static_cast<int>(*fd); iaddrs.push_back(std::move(addr)); continue; } @@ -1213,11 +1213,11 @@ namespace { // Returns the PID of the original main process from environment // variable ENV_ORIG_PID. pid_t get_orig_pid_from_env() { - auto s = getenv(ENV_ORIG_PID.c_str()); + auto s = getenv(ENV_ORIG_PID.data()); if (s == nullptr) { return -1; } - return util::parse_uint(s); + return util::parse_uint(s).value_or(-1); } } // namespace @@ -1233,7 +1233,7 @@ get_inherited_quic_lingering_worker_process_from_env() { std::vector<QUICLingeringWorkerProcess> lwps; for (size_t i = 1;; ++i) { - auto name = ENV_QUIC_WORKER_PROCESS_PREFIX.str(); + auto name = std::string{ENV_QUIC_WORKER_PROCESS_PREFIX}; name += util::utos(i); auto env = getenv(name.c_str()); if (!env) { @@ -1251,19 +1251,18 @@ get_inherited_quic_lingering_worker_process_from_env() { continue; } - auto fd = - util::parse_uint(reinterpret_cast<const uint8_t *>(env), end_fd - env); - if (fd == -1) { + auto fd = util::parse_uint(StringRef{env, end_fd}); + if (!fd) { LOG(WARN) << "Could not parse file descriptor from " << StringRef{env, static_cast<size_t>(end_fd - env)}; continue; } if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Inherit worker process QUIC IPC socket fd=" << fd; + LOG(INFO) << "Inherit worker process QUIC IPC socket fd=" << *fd; } - util::make_socket_closeonexec(fd); + util::make_socket_closeonexec(*fd); std::vector<WorkerID> worker_ids; @@ -1294,7 +1293,7 @@ get_inherited_quic_lingering_worker_process_from_env() { p = end + 1; } - lwps.emplace_back(std::move(worker_ids), fd); + lwps.emplace_back(std::move(worker_ids), *fd); } if (!lwps.empty()) { @@ -1326,7 +1325,7 @@ int create_acceptor_socket(Config *config, std::vector<InheritedAddr> &iaddrs) { if (config->uid != 0) { // fd is not associated to inode, so we cannot use fchown(2) // here. https://lkml.org/lkml/2004/11/1/84 - if (chown(addr.host.c_str(), config->uid, config->gid) == -1) { + if (chown(addr.host.data(), config->uid, config->gid) == -1) { auto error = errno; LOG(WARN) << "Changing owner of UNIX domain socket " << addr.host << " failed: " @@ -1367,7 +1366,7 @@ namespace { // communication is unidirectional; that is main process sends // messages to the worker process. On success, ipc_fd[0] is for // reading, and ipc_fd[1] for writing, just like pipe(2). -int create_ipc_socket(std::array<int, 2> &ipc_fd) { +int create_ipc_socket(std::span<int, 2> ipc_fd) { std::array<char, STRERROR_BUFSIZE> errbuf; int rv; @@ -1379,8 +1378,7 @@ int create_ipc_socket(std::array<int, 2> &ipc_fd) { return -1; } - for (int i = 0; i < 2; ++i) { - auto fd = ipc_fd[i]; + for (auto fd : ipc_fd) { util::make_socket_nonblocking(fd); util::make_socket_closeonexec(fd); } @@ -1390,7 +1388,7 @@ int create_ipc_socket(std::array<int, 2> &ipc_fd) { } // namespace namespace { -int create_worker_process_ready_ipc_socket(std::array<int, 2> &ipc_fd) { +int create_worker_process_ready_ipc_socket(std::span<int, 2> ipc_fd) { std::array<char, STRERROR_BUFSIZE> errbuf; int rv; @@ -1415,7 +1413,7 @@ int create_worker_process_ready_ipc_socket(std::array<int, 2> &ipc_fd) { #ifdef ENABLE_HTTP3 namespace { -int create_quic_ipc_socket(std::array<int, 2> &quic_ipc_fd) { +int create_quic_ipc_socket(std::span<int, 2> quic_ipc_fd) { std::array<char, STRERROR_BUFSIZE> errbuf; int rv; @@ -1929,30 +1927,29 @@ bool conf_exists(const char *path) { } // namespace namespace { -constexpr auto DEFAULT_ALPN_LIST = - StringRef::from_lit("h2,h2-16,h2-14,http/1.1"); +constexpr auto DEFAULT_ALPN_LIST = "h2,h2-16,h2-14,http/1.1"_sr; } // namespace namespace { -constexpr auto DEFAULT_TLS_MIN_PROTO_VERSION = StringRef::from_lit("TLSv1.2"); +constexpr auto DEFAULT_TLS_MIN_PROTO_VERSION = "TLSv1.2"_sr; #ifdef TLS1_3_VERSION -constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.3"); +constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = "TLSv1.3"_sr; #else // !TLS1_3_VERSION -constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.2"); +constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = "TLSv1.2"_sr; #endif // !TLS1_3_VERSION } // namespace namespace { constexpr auto DEFAULT_ACCESSLOG_FORMAT = - StringRef::from_lit(R"($remote_addr - - [$time_local] )" - R"("$request" $status $body_bytes_sent )" - R"("$http_referer" "$http_user_agent")"); + R"($remote_addr - - [$time_local] )" + R"("$request" $status $body_bytes_sent )" + R"("$http_referer" "$http_user_agent")"_sr; } // namespace namespace { void fill_default_config(Config *config) { config->num_worker = 1; - config->conf_path = StringRef::from_lit("/etc/nghttpx/nghttpx.conf"); + config->conf_path = "/etc/nghttpx/nghttpx.conf"_sr; config->pid = getpid(); #ifdef NOTHREADS @@ -1987,8 +1984,7 @@ void fill_default_config(Config *config) { auto &ocspconf = tlsconf.ocsp; // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o ocspconf.update_interval = 4_h; - ocspconf.fetch_ocsp_response_file = - StringRef::from_lit(PKGDATADIR "/fetch-ocsp-response"); + ocspconf.fetch_ocsp_response_file = PKGDATADIR "/fetch-ocsp-response"_sr; } { @@ -1998,28 +1994,26 @@ void fill_default_config(Config *config) { } tlsconf.session_timeout = std::chrono::hours(12); - tlsconf.ciphers = StringRef::from_lit(nghttp2::tls::DEFAULT_CIPHER_LIST); - tlsconf.tls13_ciphers = - StringRef::from_lit(nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST); - tlsconf.client.ciphers = - StringRef::from_lit(nghttp2::tls::DEFAULT_CIPHER_LIST); + tlsconf.ciphers = StringRef{nghttp2::tls::DEFAULT_CIPHER_LIST}; + tlsconf.tls13_ciphers = StringRef{nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST}; + tlsconf.client.ciphers = StringRef{nghttp2::tls::DEFAULT_CIPHER_LIST}; tlsconf.client.tls13_ciphers = - StringRef::from_lit(nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST); + StringRef{nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST}; tlsconf.min_proto_version = tls::proto_version_from_string(DEFAULT_TLS_MIN_PROTO_VERSION); tlsconf.max_proto_version = tls::proto_version_from_string(DEFAULT_TLS_MAX_PROTO_VERSION); tlsconf.max_early_data = 16_k; - tlsconf.ecdh_curves = StringRef::from_lit("X25519:P-256:P-384:P-521"); + tlsconf.ecdh_curves = "X25519:P-256:P-384:P-521"_sr; auto &httpconf = config->http; - httpconf.server_name = StringRef::from_lit("nghttpx"); + httpconf.server_name = "nghttpx"_sr; httpconf.no_host_rewrite = true; httpconf.request_header_field_buffer = 64_k; httpconf.max_request_header_fields = 100; httpconf.response_header_field_buffer = 64_k; httpconf.max_response_header_fields = 500; - httpconf.redirect_https_port = StringRef::from_lit("443"); + httpconf.redirect_https_port = "443"_sr; httpconf.max_requests = std::numeric_limits<size_t>::max(); httpconf.xfp.add = true; httpconf.xfp.strip_incoming = true; @@ -2099,7 +2093,7 @@ void fill_default_config(Config *config) { } auto &bpfconf = quicconf.bpf; - bpfconf.prog_file = StringRef::from_lit(PKGLIBDIR "/reuseport_kern.o"); + bpfconf.prog_file = PKGLIBDIR "/reuseport_kern.o"_sr; upstreamconf.congestion_controller = NGTCP2_CC_ALGO_CUBIC; @@ -2132,7 +2126,7 @@ void fill_default_config(Config *config) { parse_log_format(config->balloc, DEFAULT_ACCESSLOG_FORMAT); auto &errorconf = loggingconf.error; - errorconf.file = StringRef::from_lit("/dev/stderr"); + errorconf.file = "/dev/stderr"_sr; } loggingconf.syslog_facility = LOG_DAEMON; @@ -3659,10 +3653,10 @@ int process_options(Config *config, std::vector<std::pair<StringRef, StringRef>> &cmdcfgs) { std::array<char, STRERROR_BUFSIZE> errbuf; std::map<StringRef, size_t> pattern_addr_indexer; - if (conf_exists(config->conf_path.c_str())) { + if (conf_exists(config->conf_path.data())) { LOG(NOTICE) << "Loading configuration from " << config->conf_path; std::set<StringRef> include_set; - if (load_config(config, config->conf_path.c_str(), include_set, + if (load_config(config, config->conf_path.data(), include_set, pattern_addr_indexer) == -1) { LOG(FATAL) << "Failed to load configuration from " << config->conf_path; return -1; @@ -3728,7 +3722,7 @@ int process_options(Config *config, auto &dumpconf = http2conf.upstream.debug.dump; if (!dumpconf.request_header_file.empty()) { - auto path = dumpconf.request_header_file.c_str(); + auto path = dumpconf.request_header_file.data(); auto f = open_file_for_write(path); if (f == nullptr) { @@ -3750,7 +3744,7 @@ int process_options(Config *config, } if (!dumpconf.response_header_file.empty()) { - auto path = dumpconf.response_header_file.c_str(); + auto path = dumpconf.response_header_file.data(); auto f = open_file_for_write(path); if (f == nullptr) { @@ -3801,7 +3795,7 @@ int process_options(Config *config, if (listenerconf.addrs.empty()) { UpstreamAddr addr{}; - addr.host = StringRef::from_lit("*"); + addr.host = "*"_sr; addr.port = 3000; addr.tls = true; addr.family = AF_INET; @@ -3826,7 +3820,7 @@ int process_options(Config *config, if (tls::upstream_tls_enabled(config->conn) && !tlsconf.ocsp.disabled) { struct stat buf; - if (stat(tlsconf.ocsp.fetch_ocsp_response_file.c_str(), &buf) != 0) { + if (stat(tlsconf.ocsp.fetch_ocsp_response_file.data(), &buf) != 0) { tlsconf.ocsp.disabled = true; LOG(WARN) << "--fetch-ocsp-response-file: " << tlsconf.ocsp.fetch_ocsp_response_file @@ -3845,7 +3839,7 @@ int process_options(Config *config, if (!proxy.host.empty()) { auto hostport = util::make_hostport(std::begin(hostport_buf), StringRef{proxy.host}, proxy.port); - if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port, + if (resolve_hostname(&proxy.addr, proxy.host.data(), proxy.port, AF_UNSPEC) == -1) { LOG(FATAL) << "Resolving backend HTTP proxy address failed: " << hostport; return -1; @@ -3860,7 +3854,7 @@ int process_options(Config *config, auto hostport = util::make_hostport(std::begin(hostport_buf), StringRef{memcachedconf.host}, memcachedconf.port); - if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(), + if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.data(), memcachedconf.port, memcachedconf.family) == -1) { LOG(FATAL) << "Resolving memcached address for TLS session cache failed: " @@ -3882,7 +3876,7 @@ int process_options(Config *config, auto hostport = util::make_hostport(std::begin(hostport_buf), StringRef{memcachedconf.host}, memcachedconf.port); - if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(), + if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.data(), memcachedconf.port, memcachedconf.family) == -1) { LOG(FATAL) << "Resolving memcached address for TLS ticket key failed: " << hostport; @@ -3925,12 +3919,12 @@ int process_options(Config *config, fwdconf.by_obfuscated.empty()) { // 2 for '_' and terminal NULL auto iov = make_byte_ref(config->balloc, SHRPX_OBFUSCATED_NODE_LENGTH + 2); - auto p = iov.base; + auto p = std::begin(iov); *p++ = '_'; auto gen = util::make_mt19937(); p = util::random_alpha_digit(p, p + SHRPX_OBFUSCATED_NODE_LENGTH, gen); *p = '\0'; - fwdconf.by_obfuscated = StringRef{iov.base, p}; + fwdconf.by_obfuscated = StringRef{std::span{std::begin(iov), p}}; } if (config->http2.upstream.debug.frame_debug) { @@ -4124,292 +4118,285 @@ int main(int argc, char **argv) { while (1) { static int flag = 0; static constexpr option long_options[] = { - {SHRPX_OPT_DAEMON.c_str(), no_argument, nullptr, 'D'}, - {SHRPX_OPT_LOG_LEVEL.c_str(), required_argument, nullptr, 'L'}, - {SHRPX_OPT_BACKEND.c_str(), required_argument, nullptr, 'b'}, - {SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), required_argument, + {SHRPX_OPT_DAEMON.data(), no_argument, nullptr, 'D'}, + {SHRPX_OPT_LOG_LEVEL.data(), required_argument, nullptr, 'L'}, + {SHRPX_OPT_BACKEND.data(), required_argument, nullptr, 'b'}, + {SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS.data(), required_argument, nullptr, 'c'}, - {SHRPX_OPT_FRONTEND.c_str(), required_argument, nullptr, 'f'}, + {SHRPX_OPT_FRONTEND.data(), required_argument, nullptr, 'f'}, {"help", no_argument, nullptr, 'h'}, - {SHRPX_OPT_INSECURE.c_str(), no_argument, nullptr, 'k'}, - {SHRPX_OPT_WORKERS.c_str(), required_argument, nullptr, 'n'}, - {SHRPX_OPT_CLIENT_PROXY.c_str(), no_argument, nullptr, 'p'}, - {SHRPX_OPT_HTTP2_PROXY.c_str(), no_argument, nullptr, 's'}, + {SHRPX_OPT_INSECURE.data(), no_argument, nullptr, 'k'}, + {SHRPX_OPT_WORKERS.data(), required_argument, nullptr, 'n'}, + {SHRPX_OPT_CLIENT_PROXY.data(), no_argument, nullptr, 'p'}, + {SHRPX_OPT_HTTP2_PROXY.data(), no_argument, nullptr, 's'}, {"version", no_argument, nullptr, 'v'}, - {SHRPX_OPT_FRONTEND_FRAME_DEBUG.c_str(), no_argument, nullptr, 'o'}, - {SHRPX_OPT_ADD_X_FORWARDED_FOR.c_str(), no_argument, &flag, 1}, - {SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT.c_str(), required_argument, - &flag, 2}, - {SHRPX_OPT_FRONTEND_READ_TIMEOUT.c_str(), required_argument, &flag, 3}, - {SHRPX_OPT_FRONTEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 4}, - {SHRPX_OPT_BACKEND_READ_TIMEOUT.c_str(), required_argument, &flag, 5}, - {SHRPX_OPT_BACKEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 6}, - {SHRPX_OPT_ACCESSLOG_FILE.c_str(), required_argument, &flag, 7}, - {SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument, &flag, + {SHRPX_OPT_FRONTEND_FRAME_DEBUG.data(), no_argument, nullptr, 'o'}, + {SHRPX_OPT_ADD_X_FORWARDED_FOR.data(), no_argument, &flag, 1}, + {SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT.data(), required_argument, &flag, + 2}, + {SHRPX_OPT_FRONTEND_READ_TIMEOUT.data(), required_argument, &flag, 3}, + {SHRPX_OPT_FRONTEND_WRITE_TIMEOUT.data(), required_argument, &flag, 4}, + {SHRPX_OPT_BACKEND_READ_TIMEOUT.data(), required_argument, &flag, 5}, + {SHRPX_OPT_BACKEND_WRITE_TIMEOUT.data(), required_argument, &flag, 6}, + {SHRPX_OPT_ACCESSLOG_FILE.data(), required_argument, &flag, 7}, + {SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT.data(), required_argument, &flag, 8}, - {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag, + {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS.data(), required_argument, &flag, 9}, - {SHRPX_OPT_PID_FILE.c_str(), required_argument, &flag, 10}, - {SHRPX_OPT_USER.c_str(), required_argument, &flag, 11}, + {SHRPX_OPT_PID_FILE.data(), required_argument, &flag, 10}, + {SHRPX_OPT_USER.data(), required_argument, &flag, 11}, {"conf", required_argument, &flag, 12}, - {SHRPX_OPT_SYSLOG_FACILITY.c_str(), required_argument, &flag, 14}, - {SHRPX_OPT_BACKLOG.c_str(), required_argument, &flag, 15}, - {SHRPX_OPT_CIPHERS.c_str(), required_argument, &flag, 16}, - {SHRPX_OPT_CLIENT.c_str(), no_argument, &flag, 17}, - {SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag, + {SHRPX_OPT_SYSLOG_FACILITY.data(), required_argument, &flag, 14}, + {SHRPX_OPT_BACKLOG.data(), required_argument, &flag, 15}, + {SHRPX_OPT_CIPHERS.data(), required_argument, &flag, 16}, + {SHRPX_OPT_CLIENT.data(), no_argument, &flag, 17}, + {SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS.data(), required_argument, &flag, 18}, - {SHRPX_OPT_CACERT.c_str(), required_argument, &flag, 19}, - {SHRPX_OPT_BACKEND_IPV4.c_str(), no_argument, &flag, 20}, - {SHRPX_OPT_BACKEND_IPV6.c_str(), no_argument, &flag, 21}, - {SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE.c_str(), required_argument, &flag, + {SHRPX_OPT_CACERT.data(), required_argument, &flag, 19}, + {SHRPX_OPT_BACKEND_IPV4.data(), no_argument, &flag, 20}, + {SHRPX_OPT_BACKEND_IPV6.data(), no_argument, &flag, 21}, + {SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE.data(), required_argument, &flag, 22}, - {SHRPX_OPT_NO_VIA.c_str(), no_argument, &flag, 23}, - {SHRPX_OPT_SUBCERT.c_str(), required_argument, &flag, 24}, - {SHRPX_OPT_HTTP2_BRIDGE.c_str(), no_argument, &flag, 25}, - {SHRPX_OPT_BACKEND_HTTP_PROXY_URI.c_str(), required_argument, &flag, - 26}, - {SHRPX_OPT_BACKEND_NO_TLS.c_str(), no_argument, &flag, 27}, - {SHRPX_OPT_OCSP_STARTUP.c_str(), no_argument, &flag, 28}, - {SHRPX_OPT_FRONTEND_NO_TLS.c_str(), no_argument, &flag, 29}, - {SHRPX_OPT_NO_VERIFY_OCSP.c_str(), no_argument, &flag, 30}, - {SHRPX_OPT_BACKEND_TLS_SNI_FIELD.c_str(), required_argument, &flag, 31}, - {SHRPX_OPT_DH_PARAM_FILE.c_str(), required_argument, &flag, 33}, - {SHRPX_OPT_READ_RATE.c_str(), required_argument, &flag, 34}, - {SHRPX_OPT_READ_BURST.c_str(), required_argument, &flag, 35}, - {SHRPX_OPT_WRITE_RATE.c_str(), required_argument, &flag, 36}, - {SHRPX_OPT_WRITE_BURST.c_str(), required_argument, &flag, 37}, - {SHRPX_OPT_NPN_LIST.c_str(), required_argument, &flag, 38}, - {SHRPX_OPT_VERIFY_CLIENT.c_str(), no_argument, &flag, 39}, - {SHRPX_OPT_VERIFY_CLIENT_CACERT.c_str(), required_argument, &flag, 40}, - {SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE.c_str(), required_argument, &flag, + {SHRPX_OPT_NO_VIA.data(), no_argument, &flag, 23}, + {SHRPX_OPT_SUBCERT.data(), required_argument, &flag, 24}, + {SHRPX_OPT_HTTP2_BRIDGE.data(), no_argument, &flag, 25}, + {SHRPX_OPT_BACKEND_HTTP_PROXY_URI.data(), required_argument, &flag, 26}, + {SHRPX_OPT_BACKEND_NO_TLS.data(), no_argument, &flag, 27}, + {SHRPX_OPT_OCSP_STARTUP.data(), no_argument, &flag, 28}, + {SHRPX_OPT_FRONTEND_NO_TLS.data(), no_argument, &flag, 29}, + {SHRPX_OPT_NO_VERIFY_OCSP.data(), no_argument, &flag, 30}, + {SHRPX_OPT_BACKEND_TLS_SNI_FIELD.data(), required_argument, &flag, 31}, + {SHRPX_OPT_DH_PARAM_FILE.data(), required_argument, &flag, 33}, + {SHRPX_OPT_READ_RATE.data(), required_argument, &flag, 34}, + {SHRPX_OPT_READ_BURST.data(), required_argument, &flag, 35}, + {SHRPX_OPT_WRITE_RATE.data(), required_argument, &flag, 36}, + {SHRPX_OPT_WRITE_BURST.data(), required_argument, &flag, 37}, + {SHRPX_OPT_NPN_LIST.data(), required_argument, &flag, 38}, + {SHRPX_OPT_VERIFY_CLIENT.data(), no_argument, &flag, 39}, + {SHRPX_OPT_VERIFY_CLIENT_CACERT.data(), required_argument, &flag, 40}, + {SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE.data(), required_argument, &flag, 41}, - {SHRPX_OPT_CLIENT_CERT_FILE.c_str(), required_argument, &flag, 42}, - {SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER.c_str(), - required_argument, &flag, 43}, - {SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER.c_str(), + {SHRPX_OPT_CLIENT_CERT_FILE.data(), required_argument, &flag, 42}, + {SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER.data(), required_argument, + &flag, 43}, + {SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER.data(), required_argument, &flag, 44}, - {SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING.c_str(), no_argument, &flag, 45}, - {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(), + {SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING.data(), no_argument, &flag, 45}, + {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS.data(), required_argument, &flag, 46}, - {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(), + {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS.data(), required_argument, &flag, 47}, - {SHRPX_OPT_TLS_PROTO_LIST.c_str(), required_argument, &flag, 48}, - {SHRPX_OPT_PADDING.c_str(), required_argument, &flag, 49}, - {SHRPX_OPT_WORKER_READ_RATE.c_str(), required_argument, &flag, 50}, - {SHRPX_OPT_WORKER_READ_BURST.c_str(), required_argument, &flag, 51}, - {SHRPX_OPT_WORKER_WRITE_RATE.c_str(), required_argument, &flag, 52}, - {SHRPX_OPT_WORKER_WRITE_BURST.c_str(), required_argument, &flag, 53}, - {SHRPX_OPT_ALTSVC.c_str(), required_argument, &flag, 54}, - {SHRPX_OPT_ADD_RESPONSE_HEADER.c_str(), required_argument, &flag, 55}, - {SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS.c_str(), required_argument, - &flag, 56}, - {SHRPX_OPT_ACCESSLOG_SYSLOG.c_str(), no_argument, &flag, 57}, - {SHRPX_OPT_ERRORLOG_FILE.c_str(), required_argument, &flag, 58}, - {SHRPX_OPT_ERRORLOG_SYSLOG.c_str(), no_argument, &flag, 59}, - {SHRPX_OPT_STREAM_READ_TIMEOUT.c_str(), required_argument, &flag, 60}, - {SHRPX_OPT_STREAM_WRITE_TIMEOUT.c_str(), required_argument, &flag, 61}, - {SHRPX_OPT_NO_LOCATION_REWRITE.c_str(), no_argument, &flag, 62}, - {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST.c_str(), - required_argument, &flag, 63}, - {SHRPX_OPT_LISTENER_DISABLE_TIMEOUT.c_str(), required_argument, &flag, + {SHRPX_OPT_TLS_PROTO_LIST.data(), required_argument, &flag, 48}, + {SHRPX_OPT_PADDING.data(), required_argument, &flag, 49}, + {SHRPX_OPT_WORKER_READ_RATE.data(), required_argument, &flag, 50}, + {SHRPX_OPT_WORKER_READ_BURST.data(), required_argument, &flag, 51}, + {SHRPX_OPT_WORKER_WRITE_RATE.data(), required_argument, &flag, 52}, + {SHRPX_OPT_WORKER_WRITE_BURST.data(), required_argument, &flag, 53}, + {SHRPX_OPT_ALTSVC.data(), required_argument, &flag, 54}, + {SHRPX_OPT_ADD_RESPONSE_HEADER.data(), required_argument, &flag, 55}, + {SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS.data(), required_argument, &flag, + 56}, + {SHRPX_OPT_ACCESSLOG_SYSLOG.data(), no_argument, &flag, 57}, + {SHRPX_OPT_ERRORLOG_FILE.data(), required_argument, &flag, 58}, + {SHRPX_OPT_ERRORLOG_SYSLOG.data(), no_argument, &flag, 59}, + {SHRPX_OPT_STREAM_READ_TIMEOUT.data(), required_argument, &flag, 60}, + {SHRPX_OPT_STREAM_WRITE_TIMEOUT.data(), required_argument, &flag, 61}, + {SHRPX_OPT_NO_LOCATION_REWRITE.data(), no_argument, &flag, 62}, + {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST.data(), required_argument, + &flag, 63}, + {SHRPX_OPT_LISTENER_DISABLE_TIMEOUT.data(), required_argument, &flag, 64}, - {SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR.c_str(), no_argument, &flag, + {SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR.data(), no_argument, &flag, 65}, - {SHRPX_OPT_ACCESSLOG_FORMAT.c_str(), required_argument, &flag, 66}, - {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND.c_str(), + {SHRPX_OPT_ACCESSLOG_FORMAT.data(), required_argument, &flag, 66}, + {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND.data(), required_argument, &flag, 67}, - {SHRPX_OPT_TLS_TICKET_KEY_FILE.c_str(), required_argument, &flag, 68}, - {SHRPX_OPT_RLIMIT_NOFILE.c_str(), required_argument, &flag, 69}, - {SHRPX_OPT_BACKEND_RESPONSE_BUFFER.c_str(), required_argument, &flag, + {SHRPX_OPT_TLS_TICKET_KEY_FILE.data(), required_argument, &flag, 68}, + {SHRPX_OPT_RLIMIT_NOFILE.data(), required_argument, &flag, 69}, + {SHRPX_OPT_BACKEND_RESPONSE_BUFFER.data(), required_argument, &flag, 71}, - {SHRPX_OPT_BACKEND_REQUEST_BUFFER.c_str(), required_argument, &flag, - 72}, - {SHRPX_OPT_NO_HOST_REWRITE.c_str(), no_argument, &flag, 73}, - {SHRPX_OPT_NO_SERVER_PUSH.c_str(), no_argument, &flag, 74}, - {SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER.c_str(), + {SHRPX_OPT_BACKEND_REQUEST_BUFFER.data(), required_argument, &flag, 72}, + {SHRPX_OPT_NO_HOST_REWRITE.data(), no_argument, &flag, 73}, + {SHRPX_OPT_NO_SERVER_PUSH.data(), no_argument, &flag, 74}, + {SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER.data(), required_argument, &flag, 76}, - {SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE.c_str(), required_argument, &flag, + {SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE.data(), required_argument, &flag, 77}, - {SHRPX_OPT_OCSP_UPDATE_INTERVAL.c_str(), required_argument, &flag, 78}, - {SHRPX_OPT_NO_OCSP.c_str(), no_argument, &flag, 79}, - {SHRPX_OPT_HEADER_FIELD_BUFFER.c_str(), required_argument, &flag, 80}, - {SHRPX_OPT_MAX_HEADER_FIELDS.c_str(), required_argument, &flag, 81}, - {SHRPX_OPT_ADD_REQUEST_HEADER.c_str(), required_argument, &flag, 82}, - {SHRPX_OPT_INCLUDE.c_str(), required_argument, &flag, 83}, - {SHRPX_OPT_TLS_TICKET_KEY_CIPHER.c_str(), required_argument, &flag, 84}, - {SHRPX_OPT_HOST_REWRITE.c_str(), no_argument, &flag, 85}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED.c_str(), required_argument, - &flag, 86}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED.c_str(), required_argument, &flag, + {SHRPX_OPT_OCSP_UPDATE_INTERVAL.data(), required_argument, &flag, 78}, + {SHRPX_OPT_NO_OCSP.data(), no_argument, &flag, 79}, + {SHRPX_OPT_HEADER_FIELD_BUFFER.data(), required_argument, &flag, 80}, + {SHRPX_OPT_MAX_HEADER_FIELDS.data(), required_argument, &flag, 81}, + {SHRPX_OPT_ADD_REQUEST_HEADER.data(), required_argument, &flag, 82}, + {SHRPX_OPT_INCLUDE.data(), required_argument, &flag, 83}, + {SHRPX_OPT_TLS_TICKET_KEY_CIPHER.data(), required_argument, &flag, 84}, + {SHRPX_OPT_HOST_REWRITE.data(), no_argument, &flag, 85}, + {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED.data(), required_argument, &flag, + 86}, + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED.data(), required_argument, &flag, 87}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL.c_str(), required_argument, + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL.data(), required_argument, &flag, 88}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY.c_str(), - required_argument, &flag, 89}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL.c_str(), required_argument, + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY.data(), required_argument, + &flag, 89}, + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL.data(), required_argument, &flag, 90}, - {SHRPX_OPT_MRUBY_FILE.c_str(), required_argument, &flag, 91}, - {SHRPX_OPT_ACCEPT_PROXY_PROTOCOL.c_str(), no_argument, &flag, 93}, - {SHRPX_OPT_FASTOPEN.c_str(), required_argument, &flag, 94}, - {SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD.c_str(), required_argument, + {SHRPX_OPT_MRUBY_FILE.data(), required_argument, &flag, 91}, + {SHRPX_OPT_ACCEPT_PROXY_PROTOCOL.data(), no_argument, &flag, 93}, + {SHRPX_OPT_FASTOPEN.data(), required_argument, &flag, 94}, + {SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD.data(), required_argument, &flag, 95}, - {SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT.c_str(), required_argument, &flag, + {SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT.data(), required_argument, &flag, 96}, - {SHRPX_OPT_ADD_FORWARDED.c_str(), required_argument, &flag, 97}, - {SHRPX_OPT_STRIP_INCOMING_FORWARDED.c_str(), no_argument, &flag, 98}, - {SHRPX_OPT_FORWARDED_BY.c_str(), required_argument, &flag, 99}, - {SHRPX_OPT_FORWARDED_FOR.c_str(), required_argument, &flag, 100}, - {SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER.c_str(), required_argument, + {SHRPX_OPT_ADD_FORWARDED.data(), required_argument, &flag, 97}, + {SHRPX_OPT_STRIP_INCOMING_FORWARDED.data(), no_argument, &flag, 98}, + {SHRPX_OPT_FORWARDED_BY.data(), required_argument, &flag, 99}, + {SHRPX_OPT_FORWARDED_FOR.data(), required_argument, &flag, 100}, + {SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER.data(), required_argument, &flag, 101}, - {SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS.c_str(), required_argument, &flag, + {SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS.data(), required_argument, &flag, 102}, - {SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument, &flag, 103}, - {SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER.c_str(), required_argument, - &flag, 104}, - {SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS.c_str(), required_argument, &flag, + {SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST.data(), no_argument, &flag, 103}, + {SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER.data(), required_argument, &flag, + 104}, + {SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS.data(), required_argument, &flag, 105}, - {SHRPX_OPT_BACKEND_HTTP1_TLS.c_str(), no_argument, &flag, 106}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS.c_str(), no_argument, &flag, + {SHRPX_OPT_BACKEND_HTTP1_TLS.data(), no_argument, &flag, 106}, + {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS.data(), no_argument, &flag, 108}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE.c_str(), + {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE.data(), required_argument, &flag, 109}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE.c_str(), + {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE.data(), required_argument, &flag, 110}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS.c_str(), no_argument, &flag, + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS.data(), no_argument, &flag, 111}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE.c_str(), - required_argument, &flag, 112}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE.c_str(), + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE.data(), required_argument, + &flag, 112}, + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE.data(), required_argument, &flag, 113}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY.c_str(), + {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY.data(), required_argument, &flag, 114}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY.c_str(), + {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY.data(), required_argument, &flag, 115}, - {SHRPX_OPT_BACKEND_ADDRESS_FAMILY.c_str(), required_argument, &flag, + {SHRPX_OPT_BACKEND_ADDRESS_FAMILY.data(), required_argument, &flag, 116}, - {SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), + {SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS.data(), required_argument, &flag, 117}, - {SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), + {SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS.data(), required_argument, &flag, 118}, - {SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND.c_str(), required_argument, + {SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND.data(), required_argument, &flag, 119}, - {SHRPX_OPT_BACKEND_TLS.c_str(), no_argument, &flag, 120}, - {SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST.c_str(), required_argument, + {SHRPX_OPT_BACKEND_TLS.data(), no_argument, &flag, 120}, + {SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST.data(), required_argument, &flag, 121}, - {SHRPX_OPT_ERROR_PAGE.c_str(), required_argument, &flag, 122}, - {SHRPX_OPT_NO_KQUEUE.c_str(), no_argument, &flag, 123}, - {SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument, + {SHRPX_OPT_ERROR_PAGE.data(), required_argument, &flag, 122}, + {SHRPX_OPT_NO_KQUEUE.data(), no_argument, &flag, 123}, + {SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT.data(), required_argument, &flag, 124}, - {SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument, + {SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.data(), required_argument, &flag, 125}, - {SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126}, - {SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127}, - {SHRPX_OPT_SERVER_NAME.c_str(), required_argument, &flag, 128}, - {SHRPX_OPT_NO_SERVER_REWRITE.c_str(), no_argument, &flag, 129}, - {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE.c_str(), + {SHRPX_OPT_API_MAX_REQUEST_BODY.data(), required_argument, &flag, 126}, + {SHRPX_OPT_BACKEND_MAX_BACKOFF.data(), required_argument, &flag, 127}, + {SHRPX_OPT_SERVER_NAME.data(), required_argument, &flag, 128}, + {SHRPX_OPT_NO_SERVER_REWRITE.data(), no_argument, &flag, 129}, + {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE.data(), no_argument, &flag, 130}, - {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE.c_str(), no_argument, + {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE.data(), no_argument, &flag, 131}, - {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag, + {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE.data(), required_argument, &flag, 132}, - {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(), + {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE.data(), required_argument, &flag, 133}, - {SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag, + {SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE.data(), required_argument, &flag, 134}, - {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(), + {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.data(), required_argument, &flag, 135}, - {SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(), + {SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.data(), required_argument, &flag, 136}, - {SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(), + {SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.data(), required_argument, &flag, 137}, - {SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(), + {SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.data(), required_argument, &flag, 138}, - {SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(), + {SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.data(), required_argument, &flag, 139}, - {SHRPX_OPT_ECDH_CURVES.c_str(), required_argument, &flag, 140}, - {SHRPX_OPT_TLS_SCT_DIR.c_str(), required_argument, &flag, 141}, - {SHRPX_OPT_BACKEND_CONNECT_TIMEOUT.c_str(), required_argument, &flag, + {SHRPX_OPT_ECDH_CURVES.data(), required_argument, &flag, 140}, + {SHRPX_OPT_TLS_SCT_DIR.data(), required_argument, &flag, 141}, + {SHRPX_OPT_BACKEND_CONNECT_TIMEOUT.data(), required_argument, &flag, 142}, - {SHRPX_OPT_DNS_CACHE_TIMEOUT.c_str(), required_argument, &flag, 143}, - {SHRPX_OPT_DNS_LOOKUP_TIMEOUT.c_str(), required_argument, &flag, 144}, - {SHRPX_OPT_DNS_MAX_TRY.c_str(), required_argument, &flag, 145}, - {SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument, - &flag, 146}, - {SHRPX_OPT_PSK_SECRETS.c_str(), required_argument, &flag, 147}, - {SHRPX_OPT_CLIENT_PSK_SECRETS.c_str(), required_argument, &flag, 148}, - {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument, - &flag, 149}, - {SHRPX_OPT_CLIENT_CIPHERS.c_str(), required_argument, &flag, 150}, - {SHRPX_OPT_ACCESSLOG_WRITE_EARLY.c_str(), no_argument, &flag, 151}, - {SHRPX_OPT_TLS_MIN_PROTO_VERSION.c_str(), required_argument, &flag, - 152}, - {SHRPX_OPT_TLS_MAX_PROTO_VERSION.c_str(), required_argument, &flag, - 153}, - {SHRPX_OPT_REDIRECT_HTTPS_PORT.c_str(), required_argument, &flag, 154}, - {SHRPX_OPT_FRONTEND_MAX_REQUESTS.c_str(), required_argument, &flag, - 155}, - {SHRPX_OPT_SINGLE_THREAD.c_str(), no_argument, &flag, 156}, - {SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO.c_str(), no_argument, &flag, 157}, - {SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO.c_str(), no_argument, + {SHRPX_OPT_DNS_CACHE_TIMEOUT.data(), required_argument, &flag, 143}, + {SHRPX_OPT_DNS_LOOKUP_TIMEOUT.data(), required_argument, &flag, 144}, + {SHRPX_OPT_DNS_MAX_TRY.data(), required_argument, &flag, 145}, + {SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT.data(), required_argument, &flag, + 146}, + {SHRPX_OPT_PSK_SECRETS.data(), required_argument, &flag, 147}, + {SHRPX_OPT_CLIENT_PSK_SECRETS.data(), required_argument, &flag, 148}, + {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST.data(), no_argument, &flag, + 149}, + {SHRPX_OPT_CLIENT_CIPHERS.data(), required_argument, &flag, 150}, + {SHRPX_OPT_ACCESSLOG_WRITE_EARLY.data(), no_argument, &flag, 151}, + {SHRPX_OPT_TLS_MIN_PROTO_VERSION.data(), required_argument, &flag, 152}, + {SHRPX_OPT_TLS_MAX_PROTO_VERSION.data(), required_argument, &flag, 153}, + {SHRPX_OPT_REDIRECT_HTTPS_PORT.data(), required_argument, &flag, 154}, + {SHRPX_OPT_FRONTEND_MAX_REQUESTS.data(), required_argument, &flag, 155}, + {SHRPX_OPT_SINGLE_THREAD.data(), no_argument, &flag, 156}, + {SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO.data(), no_argument, &flag, 157}, + {SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO.data(), no_argument, &flag, 158}, - {SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159}, - {SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED.c_str(), no_argument, &flag, + {SHRPX_OPT_SINGLE_PROCESS.data(), no_argument, &flag, 159}, + {SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED.data(), no_argument, &flag, 160}, - {SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR.c_str(), no_argument, &flag, + {SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR.data(), no_argument, &flag, 161}, - {SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA.c_str(), no_argument, &flag, 162}, - {SHRPX_OPT_TLS_MAX_EARLY_DATA.c_str(), required_argument, &flag, 163}, - {SHRPX_OPT_TLS13_CIPHERS.c_str(), required_argument, &flag, 164}, - {SHRPX_OPT_TLS13_CLIENT_CIPHERS.c_str(), required_argument, &flag, 165}, - {SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA.c_str(), no_argument, &flag, + {SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA.data(), no_argument, &flag, 162}, + {SHRPX_OPT_TLS_MAX_EARLY_DATA.data(), required_argument, &flag, 163}, + {SHRPX_OPT_TLS13_CIPHERS.data(), required_argument, &flag, 164}, + {SHRPX_OPT_TLS13_CLIENT_CIPHERS.data(), required_argument, &flag, 165}, + {SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA.data(), no_argument, &flag, 166}, - {SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST.c_str(), no_argument, &flag, 167}, - {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST.c_str(), no_argument, - &flag, 168}, - {SHRPX_OPT_QUIC_BPF_PROGRAM_FILE.c_str(), required_argument, &flag, - 169}, - {SHRPX_OPT_NO_QUIC_BPF.c_str(), no_argument, &flag, 170}, - {SHRPX_OPT_HTTP2_ALTSVC.c_str(), required_argument, &flag, 171}, - {SHRPX_OPT_FRONTEND_HTTP3_READ_TIMEOUT.c_str(), required_argument, - &flag, 172}, - {SHRPX_OPT_FRONTEND_QUIC_IDLE_TIMEOUT.c_str(), required_argument, &flag, + {SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST.data(), no_argument, &flag, 167}, + {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST.data(), no_argument, &flag, + 168}, + {SHRPX_OPT_QUIC_BPF_PROGRAM_FILE.data(), required_argument, &flag, 169}, + {SHRPX_OPT_NO_QUIC_BPF.data(), no_argument, &flag, 170}, + {SHRPX_OPT_HTTP2_ALTSVC.data(), required_argument, &flag, 171}, + {SHRPX_OPT_FRONTEND_HTTP3_READ_TIMEOUT.data(), required_argument, &flag, + 172}, + {SHRPX_OPT_FRONTEND_QUIC_IDLE_TIMEOUT.data(), required_argument, &flag, 173}, - {SHRPX_OPT_FRONTEND_QUIC_DEBUG_LOG.c_str(), no_argument, &flag, 174}, - {SHRPX_OPT_FRONTEND_HTTP3_WINDOW_SIZE.c_str(), required_argument, &flag, + {SHRPX_OPT_FRONTEND_QUIC_DEBUG_LOG.data(), no_argument, &flag, 174}, + {SHRPX_OPT_FRONTEND_HTTP3_WINDOW_SIZE.data(), required_argument, &flag, 175}, - {SHRPX_OPT_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE.c_str(), + {SHRPX_OPT_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE.data(), required_argument, &flag, 176}, - {SHRPX_OPT_FRONTEND_HTTP3_MAX_WINDOW_SIZE.c_str(), required_argument, + {SHRPX_OPT_FRONTEND_HTTP3_MAX_WINDOW_SIZE.data(), required_argument, &flag, 177}, - {SHRPX_OPT_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE.c_str(), + {SHRPX_OPT_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE.data(), required_argument, &flag, 178}, - {SHRPX_OPT_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS.c_str(), + {SHRPX_OPT_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS.data(), required_argument, &flag, 179}, - {SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA.c_str(), no_argument, &flag, 180}, - {SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR.c_str(), required_argument, &flag, + {SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA.data(), no_argument, &flag, 180}, + {SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR.data(), required_argument, &flag, 181}, - {SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN.c_str(), no_argument, &flag, - 182}, - {SHRPX_OPT_FRONTEND_QUIC_CONGESTION_CONTROLLER.c_str(), + {SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN.data(), no_argument, &flag, 182}, + {SHRPX_OPT_FRONTEND_QUIC_CONGESTION_CONTROLLER.data(), required_argument, &flag, 183}, - {SHRPX_OPT_QUIC_SERVER_ID.c_str(), required_argument, &flag, 185}, - {SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE.c_str(), required_argument, &flag, + {SHRPX_OPT_QUIC_SERVER_ID.data(), required_argument, &flag, 185}, + {SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE.data(), required_argument, &flag, 186}, - {SHRPX_OPT_RLIMIT_MEMLOCK.c_str(), required_argument, &flag, 187}, - {SHRPX_OPT_MAX_WORKER_PROCESSES.c_str(), required_argument, &flag, 188}, - {SHRPX_OPT_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD.c_str(), + {SHRPX_OPT_RLIMIT_MEMLOCK.data(), required_argument, &flag, 187}, + {SHRPX_OPT_MAX_WORKER_PROCESSES.data(), required_argument, &flag, 188}, + {SHRPX_OPT_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD.data(), required_argument, &flag, 189}, - {SHRPX_OPT_FRONTEND_QUIC_INITIAL_RTT.c_str(), required_argument, &flag, + {SHRPX_OPT_FRONTEND_QUIC_INITIAL_RTT.data(), required_argument, &flag, 190}, - {SHRPX_OPT_REQUIRE_HTTP_SCHEME.c_str(), no_argument, &flag, 191}, - {SHRPX_OPT_TLS_KTLS.c_str(), no_argument, &flag, 192}, - {SHRPX_OPT_ALPN_LIST.c_str(), required_argument, &flag, 193}, - {SHRPX_OPT_FRONTEND_HEADER_TIMEOUT.c_str(), required_argument, &flag, + {SHRPX_OPT_REQUIRE_HTTP_SCHEME.data(), no_argument, &flag, 191}, + {SHRPX_OPT_TLS_KTLS.data(), no_argument, &flag, 192}, + {SHRPX_OPT_ALPN_LIST.data(), required_argument, &flag, 193}, + {SHRPX_OPT_FRONTEND_HEADER_TIMEOUT.data(), required_argument, &flag, 194}, - {SHRPX_OPT_FRONTEND_HTTP2_IDLE_TIMEOUT.c_str(), required_argument, - &flag, 195}, - {SHRPX_OPT_FRONTEND_HTTP3_IDLE_TIMEOUT.c_str(), required_argument, - &flag, 196}, + {SHRPX_OPT_FRONTEND_HTTP2_IDLE_TIMEOUT.data(), required_argument, &flag, + 195}, + {SHRPX_OPT_FRONTEND_HTTP3_IDLE_TIMEOUT.data(), required_argument, &flag, + 196}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -4420,7 +4407,7 @@ int main(int argc, char **argv) { } switch (c) { case 'D': - cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, "yes"_sr); break; case 'L': cmdcfgs.emplace_back(SHRPX_OPT_LOG_LEVEL, StringRef{optarg}); @@ -4439,20 +4426,19 @@ int main(int argc, char **argv) { print_help(std::cout); exit(EXIT_SUCCESS); case 'k': - cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, "yes"_sr); break; case 'n': cmdcfgs.emplace_back(SHRPX_OPT_WORKERS, StringRef{optarg}); break; case 'o': - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG, "yes"_sr); break; case 'p': - cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, "yes"_sr); break; case 's': - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, "yes"_sr); break; case 'v': print_version(std::cout); @@ -4464,8 +4450,7 @@ int main(int argc, char **argv) { switch (flag) { case 1: // --add-x-forwarded-for - cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR, "yes"_sr); break; case 2: // --frontend-http2-read-timeout @@ -4529,7 +4514,7 @@ int main(int argc, char **argv) { break; case 17: // --client - cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, "yes"_sr); break; case 18: // --backend-http2-window-bits @@ -4542,13 +4527,11 @@ int main(int argc, char **argv) { break; case 20: // --backend-ipv4 - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4, "yes"_sr); break; case 21: // --backend-ipv6 - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6, "yes"_sr); break; case 22: // --private-key-passwd-file @@ -4557,7 +4540,7 @@ int main(int argc, char **argv) { break; case 23: // --no-via - cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, "yes"_sr); break; case 24: // --subcert @@ -4565,8 +4548,7 @@ int main(int argc, char **argv) { break; case 25: // --http2-bridge - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE, "yes"_sr); break; case 26: // --backend-http-proxy-uri @@ -4575,23 +4557,19 @@ int main(int argc, char **argv) { break; case 27: // --backend-no-tls - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS, "yes"_sr); break; case 28: // --ocsp-startup - cmdcfgs.emplace_back(SHRPX_OPT_OCSP_STARTUP, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_OCSP_STARTUP, "yes"_sr); break; case 29: // --frontend-no-tls - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS, "yes"_sr); break; case 30: // --no-verify-ocsp - cmdcfgs.emplace_back(SHRPX_OPT_NO_VERIFY_OCSP, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_VERIFY_OCSP, "yes"_sr); break; case 31: // --backend-tls-sni-field @@ -4624,8 +4602,7 @@ int main(int argc, char **argv) { break; case 39: // --verify-client - cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT, "yes"_sr); break; case 40: // --verify-client-cacert @@ -4652,8 +4629,7 @@ int main(int argc, char **argv) { break; case 45: // --http2-no-cookie-crumbling - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING, "yes"_sr); break; case 46: // --frontend-http2-connection-window-bits @@ -4704,8 +4680,7 @@ int main(int argc, char **argv) { break; case 57: // --accesslog-syslog - cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG, "yes"_sr); break; case 58: // --errorlog-file @@ -4713,8 +4688,7 @@ int main(int argc, char **argv) { break; case 59: // --errorlog-syslog - cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG, "yes"_sr); break; case 60: // --stream-read-timeout @@ -4726,8 +4700,7 @@ int main(int argc, char **argv) { break; case 62: // --no-location-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE, "yes"_sr); break; case 63: // --backend-http1-connections-per-host @@ -4742,7 +4715,7 @@ int main(int argc, char **argv) { case 65: // --strip-incoming-x-forwarded-for cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR, - StringRef::from_lit("yes")); + "yes"_sr); break; case 66: // --accesslog-format @@ -4773,13 +4746,11 @@ int main(int argc, char **argv) { break; case 73: // --no-host-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_NO_HOST_REWRITE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_HOST_REWRITE, "yes"_sr); break; case 74: // --no-server-push - cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_PUSH, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_PUSH, "yes"_sr); break; case 76: // --backend-http2-connections-per-worker @@ -4797,7 +4768,7 @@ int main(int argc, char **argv) { break; case 79: // --no-ocsp - cmdcfgs.emplace_back(SHRPX_OPT_NO_OCSP, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_OCSP, "yes"_sr); break; case 80: // --header-field-buffer @@ -4822,8 +4793,7 @@ int main(int argc, char **argv) { break; case 85: // --host-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_HOST_REWRITE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HOST_REWRITE, "yes"_sr); break; case 86: // --tls-session-cache-memcached @@ -4856,8 +4826,7 @@ int main(int argc, char **argv) { break; case 93: // --accept-proxy-protocol - cmdcfgs.emplace_back(SHRPX_OPT_ACCEPT_PROXY_PROTOCOL, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ACCEPT_PROXY_PROTOCOL, "yes"_sr); break; case 94: // --fastopen @@ -4879,8 +4848,7 @@ int main(int argc, char **argv) { break; case 98: // --strip-incoming-forwarded - cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_FORWARDED, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_FORWARDED, "yes"_sr); break; case 99: // --forwarded-by @@ -4902,8 +4870,7 @@ int main(int argc, char **argv) { break; case 103: // --no-http2-cipher-black-list - cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, "yes"_sr); break; case 104: // --request-header-field-buffer @@ -4917,13 +4884,12 @@ int main(int argc, char **argv) { break; case 106: // --backend-http1-tls - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_TLS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_TLS, "yes"_sr); break; case 108: // --tls-session-cache-memcached-tls cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, - StringRef::from_lit("yes")); + "yes"_sr); break; case 109: // --tls-session-cache-memcached-cert-file @@ -4938,8 +4904,7 @@ int main(int argc, char **argv) { break; case 111: // --tls-ticket-key-memcached-tls - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS, "yes"_sr); break; case 112: // --tls-ticket-key-memcached-cert-file @@ -4985,7 +4950,7 @@ int main(int argc, char **argv) { break; case 120: // --backend-tls - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS, "yes"_sr); break; case 121: // --backend-connections-per-host @@ -4998,7 +4963,7 @@ int main(int argc, char **argv) { break; case 123: // --no-kqueue - cmdcfgs.emplace_back(SHRPX_OPT_NO_KQUEUE, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_KQUEUE, "yes"_sr); break; case 124: // --frontend-http2-settings-timeout @@ -5024,19 +4989,17 @@ int main(int argc, char **argv) { break; case 129: // --no-server-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_REWRITE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_REWRITE, "yes"_sr); break; case 130: // --frontend-http2-optimize-write-buffer-size cmdcfgs.emplace_back( - SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE, - StringRef::from_lit("yes")); + SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE, "yes"_sr); break; case 131: // --frontend-http2-optimize-window-size cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE, - StringRef::from_lit("yes")); + "yes"_sr); break; case 132: // --frontend-http2-window-size @@ -5121,7 +5084,7 @@ int main(int argc, char **argv) { case 149: // --client-no-http2-cipher-black-list cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST, - StringRef::from_lit("yes")); + "yes"_sr); break; case 150: // --client-ciphers @@ -5129,8 +5092,7 @@ int main(int argc, char **argv) { break; case 151: // --accesslog-write-early - cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_WRITE_EARLY, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_WRITE_EARLY, "yes"_sr); break; case 152: // --tls-min-proto-version @@ -5153,38 +5115,34 @@ int main(int argc, char **argv) { break; case 156: // --single-thread - cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_THREAD, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_THREAD, "yes"_sr); break; case 157: // --no-add-x-forwarded-proto - cmdcfgs.emplace_back(SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO, "yes"_sr); break; case 158: // --no-strip-incoming-x-forwarded-proto cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO, - StringRef::from_lit("yes")); + "yes"_sr); break; case 159: // --single-process - cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_PROCESS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_PROCESS, "yes"_sr); break; case 160: // --verify-client-tolerate-expired cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED, - StringRef::from_lit("yes")); + "yes"_sr); break; case 161: // --ignore-per-pattern-mruby-error cmdcfgs.emplace_back(SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR, - StringRef::from_lit("yes")); + "yes"_sr); break; case 162: // --tls-no-postpone-early-data - cmdcfgs.emplace_back(SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA, "yes"_sr); break; case 163: // --tls-max-early-data @@ -5200,18 +5158,16 @@ int main(int argc, char **argv) { break; case 166: // --no-strip-incoming-early-data - cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA, "yes"_sr); break; case 167: // --no-http2-cipher-block-list - cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST, "yes"_sr); break; case 168: // --client-no-http2-cipher-block-list cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST, - StringRef::from_lit("yes")); + "yes"_sr); break; case 169: // --quic-bpf-program-file @@ -5220,7 +5176,7 @@ int main(int argc, char **argv) { break; case 170: // --no-quic-bpf - cmdcfgs.emplace_back(SHRPX_OPT_NO_QUIC_BPF, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_QUIC_BPF, "yes"_sr); break; case 171: // --http2-altsvc @@ -5238,8 +5194,7 @@ int main(int argc, char **argv) { break; case 174: // --frontend-quic-debug-log - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_DEBUG_LOG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_DEBUG_LOG, "yes"_sr); break; case 175: // --frontend-http3-window-size @@ -5269,8 +5224,7 @@ int main(int argc, char **argv) { break; case 180: // --frontend-quic-early-data - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA, "yes"_sr); break; case 181: // --frontend-quic-qlog-dir @@ -5279,8 +5233,7 @@ int main(int argc, char **argv) { break; case 182: // --frontend-quic-require-token - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN, "yes"_sr); break; case 183: // --frontend-quic-congestion-controller @@ -5316,12 +5269,11 @@ int main(int argc, char **argv) { break; case 191: // --require-http-scheme - cmdcfgs.emplace_back(SHRPX_OPT_REQUIRE_HTTP_SCHEME, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_REQUIRE_HTTP_SCHEME, "yes"_sr); break; case 192: // --tls-ktls - cmdcfgs.emplace_back(SHRPX_OPT_TLS_KTLS, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_TLS_KTLS, "yes"_sr); break; case 193: // --alpn-list diff --git a/src/shrpx_api_downstream_connection.cc b/src/shrpx_api_downstream_connection.cc index 254ab59..13ebac6 100644 --- a/src/shrpx_api_downstream_connection.cc +++ b/src/shrpx_api_downstream_connection.cc @@ -39,33 +39,27 @@ namespace shrpx { namespace { -// List of API endpoints -const std::array<APIEndpoint, 2> &apis() { - static const auto apis = new std::array<APIEndpoint, 2>{ - APIEndpoint{ - StringRef::from_lit("/api/v1beta1/backendconfig"), - true, - (1 << API_METHOD_POST) | (1 << API_METHOD_PUT), - &APIDownstreamConnection::handle_backendconfig, - }, - APIEndpoint{ - StringRef::from_lit("/api/v1beta1/configrevision"), - true, - (1 << API_METHOD_GET), - &APIDownstreamConnection::handle_configrevision, - }, - }; - - return *apis; -} +const auto backendconfig_endpoint = APIEndpoint{ + "/api/v1beta1/backendconfig"_sr, + true, + (1 << API_METHOD_POST) | (1 << API_METHOD_PUT), + &APIDownstreamConnection::handle_backendconfig, +}; + +const auto configrevision_endpoint = APIEndpoint{ + "/api/v1beta1/configrevision"_sr, + true, + (1 << API_METHOD_GET), + &APIDownstreamConnection::handle_configrevision, +}; } // namespace namespace { // The method string. This must be same order of APIMethod. constexpr StringRef API_METHOD_STRING[] = { - StringRef::from_lit("GET"), - StringRef::from_lit("POST"), - StringRef::from_lit("PUT"), + "GET"_sr, + "POST"_sr, + "PUT"_sr, }; } // namespace @@ -112,18 +106,18 @@ int APIDownstreamConnection::send_reply(unsigned int http_status, switch (api_status) { case APIStatusCode::SUCCESS: - api_status_str = StringRef::from_lit("Success"); + api_status_str = "Success"_sr; break; case APIStatusCode::FAILURE: - api_status_str = StringRef::from_lit("Failure"); + api_status_str = "Failure"_sr; break; default: assert(0); } - constexpr auto M1 = StringRef::from_lit("{\"status\":\""); - constexpr auto M2 = StringRef::from_lit("\",\"code\":"); - constexpr auto M3 = StringRef::from_lit("}"); + constexpr auto M1 = "{\"status\":\""_sr; + constexpr auto M2 = "\",\"code\":"_sr; + constexpr auto M3 = "}"_sr; // 3 is the number of digits in http_status, assuming it is 3 digits // number. @@ -131,7 +125,7 @@ int APIDownstreamConnection::send_reply(unsigned int http_status, api_status_str.size() + 3; auto buf = make_byte_ref(balloc, buflen); - auto p = buf.base; + auto p = std::begin(buf); p = std::copy(std::begin(M1), std::end(M1), p); p = std::copy(std::begin(api_status_str), std::end(api_status_str), p); @@ -140,24 +134,23 @@ int APIDownstreamConnection::send_reply(unsigned int http_status, p = std::copy(std::begin(data), std::end(data), p); p = std::copy(std::begin(M3), std::end(M3), p); - buf.len = p - buf.base; + buf = buf.subspan(0, p - std::begin(buf)); - auto content_length = util::make_string_ref_uint(balloc, buf.len); + auto content_length = util::make_string_ref_uint(balloc, buf.size()); - resp.fs.add_header_token(StringRef::from_lit("content-length"), - content_length, false, http2::HD_CONTENT_LENGTH); + resp.fs.add_header_token("content-length"_sr, content_length, false, + http2::HD_CONTENT_LENGTH); switch (http_status) { case 400: case 405: case 413: - resp.fs.add_header_token(StringRef::from_lit("connection"), - StringRef::from_lit("close"), false, + resp.fs.add_header_token("connection"_sr, "close"_sr, false, http2::HD_CONNECTION); break; } - if (upstream->send_reply(downstream_, buf.base, buf.len) != 0) { + if (upstream->send_reply(downstream_, buf.data(), buf.size()) != 0) { return -1; } @@ -170,8 +163,8 @@ const APIEndpoint *lookup_api(const StringRef &path) { case 26: switch (path[25]) { case 'g': - if (util::streq_l("/api/v1beta1/backendconfi", std::begin(path), 25)) { - return &apis()[0]; + if (util::streq("/api/v1beta1/backendconfi"_sr, path, 25)) { + return &backendconfig_endpoint; } break; } @@ -179,8 +172,8 @@ const APIEndpoint *lookup_api(const StringRef &path) { case 27: switch (path[26]) { case 'n': - if (util::streq_l("/api/v1beta1/configrevisio", std::begin(path), 26)) { - return &apis()[1]; + if (util::streq("/api/v1beta1/configrevisio"_sr, path, 26)) { + return &configrevision_endpoint; } break; } @@ -283,7 +276,7 @@ int APIDownstreamConnection::error_method_not_allowed() { auto &balloc = downstream_->get_block_allocator(); auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); for (uint8_t i = 0; i < API_METHOD_MAX; ++i) { if (api_->allowed_methods & (1 << i)) { auto &s = API_METHOD_STRING[i]; @@ -295,7 +288,7 @@ int APIDownstreamConnection::error_method_not_allowed() { p -= 2; *p = '\0'; - resp.fs.add_header_token(StringRef::from_lit("allow"), StringRef{iov.base, p}, + resp.fs.add_header_token("allow"_sr, StringRef{std::span{std::begin(iov), p}}, false, -1); return send_reply(405, APIStatusCode::FAILURE); } @@ -394,10 +387,10 @@ int APIDownstreamConnection::handle_backendconfig() { return 0; } - auto opt = StringRef{first, eq}; - auto optval = StringRef{eq + 1, eol}; + auto opt = StringRef{std::span{first, eq}}; + auto optval = StringRef{std::span{eq + 1, eol}}; - auto optid = option_lookup_token(opt.c_str(), opt.size()); + auto optid = option_lookup_token(opt); switch (optid) { case SHRPX_OPTID_BACKEND: @@ -442,9 +435,8 @@ int APIDownstreamConnection::handle_configrevision() { // "configRevision": N // } auto data = concat_string_ref( - balloc, StringRef::from_lit(R"(,"data":{"configRevision":)"), - util::make_string_ref_uint(balloc, config->config_revision), - StringRef::from_lit("}")); + balloc, R"(,"data":{"configRevision":)"_sr, + util::make_string_ref_uint(balloc, config->config_revision), "}"_sr); send_reply(200, APIStatusCode::SUCCESS, data); diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index a78b00a..70f0d95 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -322,11 +322,11 @@ int ClientHandler::write_tls() { int ClientHandler::read_quic(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, - const ngtcp2_pkt_info &pi, const uint8_t *data, - size_t datalen) { + const ngtcp2_pkt_info &pi, + std::span<const uint8_t> data) { auto upstream = static_cast<Http3Upstream *>(upstream_.get()); - return upstream->on_read(faddr, remote_addr, local_addr, pi, data, datalen); + return upstream->on_read(faddr, remote_addr, local_addr, pi, data); } int ClientHandler::write_quic() { return upstream_->on_write(); } @@ -492,13 +492,13 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, auto len = SHRPX_OBFUSCATED_NODE_LENGTH + 1; // 1 for terminating NUL. auto buf = make_byte_ref(balloc_, len + 1); - auto p = buf.base; + auto p = std::begin(buf); *p++ = '_'; p = util::random_alpha_digit(p, p + SHRPX_OBFUSCATED_NODE_LENGTH, worker_->get_randgen()); *p = '\0'; - forwarded_for_ = StringRef{buf.base, p}; + forwarded_for_ = StringRef{std::span{std::begin(buf), p}}; } else { init_forwarded_for(family, ipaddr_); } @@ -511,13 +511,13 @@ void ClientHandler::init_forwarded_for(int family, const StringRef &ipaddr) { auto len = 2 + ipaddr.size(); // 1 for terminating NUL. auto buf = make_byte_ref(balloc_, len + 1); - auto p = buf.base; + auto p = std::begin(buf); *p++ = '['; p = std::copy(std::begin(ipaddr), std::end(ipaddr), p); *p++ = ']'; *p = '\0'; - forwarded_for_ = StringRef{buf.base, p}; + forwarded_for_ = StringRef{std::span{std::begin(buf), p}}; } else { // family == AF_INET or family == AF_UNIX forwarded_for_ = ipaddr; @@ -535,7 +535,7 @@ void ClientHandler::setup_upstream_io_callback() { // upgraded to HTTP/2 through HTTP Upgrade or direct HTTP/2 // connection. upstream_ = std::make_unique<HttpsUpstream>(this); - alpn_ = StringRef::from_lit("http/1.1"); + alpn_ = "http/1.1"_sr; read_ = &ClientHandler::read_clear; write_ = &ClientHandler::write_clear; on_read_ = &ClientHandler::upstream_http1_connhd_read; @@ -629,7 +629,7 @@ int ClientHandler::validate_next_proto() { CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1"; } - proto = StringRef::from_lit("http/1.1"); + proto = "http/1.1"_sr; } if (!tls::in_proto_list(get_config()->tls.alpn_list, proto)) { @@ -657,9 +657,9 @@ int ClientHandler::validate_next_proto() { return 0; } - if (proto == StringRef::from_lit("http/1.1")) { + if (proto == "http/1.1"_sr) { upstream_ = std::make_unique<HttpsUpstream>(this); - alpn_ = StringRef::from_lit("http/1.1"); + alpn_ = "http/1.1"_sr; // At this point, input buffer is already filled with some bytes. // The read callback is not called until new data come. So consume @@ -802,8 +802,7 @@ uint32_t ClientHandler::get_affinity_cookie(Downstream *downstream, auto d = std::uniform_int_distribution<uint32_t>(1); auto rh = d(worker_->get_randgen()); - h = util::hash32(StringRef{reinterpret_cast<uint8_t *>(&rh), - reinterpret_cast<uint8_t *>(&rh) + sizeof(rh)}); + h = util::hash32(StringRef{reinterpret_cast<char *>(&rh), sizeof(rh)}); downstream->renew_affinity_cookie(h); @@ -963,8 +962,7 @@ DownstreamAddr *ClientHandler::get_downstream_addr_strict_affinity( } else { auto d = std::uniform_int_distribution<uint32_t>(1); auto rh = d(worker_->get_randgen()); - h = util::hash32(StringRef{reinterpret_cast<uint8_t *>(&rh), - reinterpret_cast<uint8_t *>(&rh) + sizeof(rh)}); + h = util::hash32(StringRef{reinterpret_cast<char *>(&rh), sizeof(rh)}); } // Client is not bound to a particular backend, or the bound backend @@ -1148,7 +1146,7 @@ SSL *ClientHandler::get_ssl() const { return conn_.tls.ssl; } void ClientHandler::direct_http2_upgrade() { upstream_ = std::make_unique<Http2Upstream>(this); - alpn_ = StringRef::from_lit(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID); + alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID ""_sr; on_read_ = &ClientHandler::upstream_read; write_ = &ClientHandler::write_clear; } @@ -1173,17 +1171,16 @@ int ClientHandler::perform_http2_upgrade(HttpsUpstream *http) { upstream_.release(); // TODO We might get other version id in HTTP2-settings, if we // support aliasing for h2, but we just use library default for now. - alpn_ = StringRef::from_lit(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID); + alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID ""_sr; on_read_ = &ClientHandler::upstream_http2_connhd_read; write_ = &ClientHandler::write_clear; input->remove(*output, input->rleft()); - constexpr auto res = - StringRef::from_lit("HTTP/1.1 101 Switching Protocols\r\n" - "Connection: Upgrade\r\n" - "Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n" - "\r\n"); + constexpr auto res = "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n" + "\r\n"_sr; output->append(res); upstream_ = std::move(upstream); @@ -1196,9 +1193,9 @@ bool ClientHandler::get_http2_upgrade_allowed() const { return !conn_.tls.ssl; } StringRef ClientHandler::get_upstream_scheme() const { if (conn_.tls.ssl) { - return StringRef::from_lit("https"); + return "https"_sr; } else { - return StringRef::from_lit("http"); + return "http"_sr; } } @@ -1324,7 +1321,7 @@ int ClientHandler::proxy_protocol_read() { // NULL character really destroys functions which expects NULL // terminated string. We won't expect it in PROXY protocol line, so // find it here. - auto chrs = std::array<char, 2>{'\n', '\0'}; + auto chrs = std::to_array({'\n', '\0'}); constexpr size_t MAX_PROXY_LINELEN = 107; @@ -1342,7 +1339,7 @@ int ClientHandler::proxy_protocol_read() { --end; - constexpr auto HEADER = StringRef::from_lit("PROXY "); + constexpr auto HEADER = "PROXY "_sr; if (static_cast<size_t>(end - rb_.pos()) < HEADER.size()) { if (LOG_ENABLED(INFO)) { @@ -1351,7 +1348,7 @@ int ClientHandler::proxy_protocol_read() { return -1; } - if (!util::streq(HEADER, StringRef{rb_.pos(), HEADER.size()})) { + if (HEADER != StringRef{rb_.pos(), HEADER.size()}) { if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "PROXY-protocol-v1: Bad PROXY protocol version 1 ID"; } @@ -1399,7 +1396,7 @@ int ClientHandler::proxy_protocol_read() { } return -1; } - if (!util::streq_l("UNKNOWN", rb_.pos(), 7)) { + if ("UNKNOWN"_sr != StringRef{rb_.pos(), 7}) { if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "PROXY-protocol-v1: Unknown INET protocol family"; } @@ -1482,9 +1479,10 @@ int ClientHandler::proxy_protocol_read() { rb_.drain(end + 2 - rb_.pos()); - ipaddr_ = - make_string_ref(balloc_, StringRef{src_addr, src_addr + src_addrlen}); - port_ = make_string_ref(balloc_, StringRef{src_port, src_port + src_portlen}); + ipaddr_ = make_string_ref( + balloc_, StringRef{src_addr, static_cast<size_t>(src_addrlen)}); + port_ = make_string_ref( + balloc_, StringRef{src_port, static_cast<size_t>(src_portlen)}); if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "PROXY-protocol-v1: Finished, " << (rb_.pos() - first) diff --git a/src/shrpx_client_handler.h b/src/shrpx_client_handler.h index 511dd91..1bb3552 100644 --- a/src/shrpx_client_handler.h +++ b/src/shrpx_client_handler.h @@ -153,7 +153,7 @@ public: void setup_http3_upstream(std::unique_ptr<Http3Upstream> &&upstream); int read_quic(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen); + std::span<const uint8_t> data); int write_quic(); #endif // ENABLE_HTTP3 diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index d856c95..a74b79e 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -76,7 +76,7 @@ namespace { Config *config; } // namespace -constexpr auto SHRPX_UNIX_PATH_PREFIX = StringRef::from_lit("unix:"); +constexpr auto SHRPX_UNIX_PATH_PREFIX = "unix:"_sr; const Config *get_config() { return config; } @@ -139,8 +139,8 @@ int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr, auto portstr = StringRef{sep + 1, std::end(hostport)}; auto d = util::parse_uint(portstr); - if (1 <= d && d <= std::numeric_limits<uint16_t>::max()) { - *port_ptr = d; + if (d && 1 <= d && d <= std::numeric_limits<uint16_t>::max()) { + *port_ptr = *d; return 0; } @@ -152,7 +152,7 @@ int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr, namespace { bool is_secure(const StringRef &filename) { struct stat buf; - int rv = stat(filename.c_str(), &buf); + int rv = stat(filename.data(), &buf); if (rv == 0) { if ((buf.st_mode & S_IRWXU) && !(buf.st_mode & S_IRWXG) && !(buf.st_mode & S_IRWXO)) { @@ -185,7 +185,7 @@ read_tls_ticket_key_file(const std::vector<StringRef> &files, for (auto &file : files) { struct stat fst {}; - if (stat(file.c_str(), &fst) == -1) { + if (stat(file.data(), &fst) == -1) { auto error = errno; LOG(ERROR) << "tls-ticket-key-file: could not stat file " << file << ", errno=" << error; @@ -198,7 +198,7 @@ read_tls_ticket_key_file(const std::vector<StringRef> &files, return nullptr; } - std::ifstream f(file.c_str()); + std::ifstream f(file.data()); if (!f) { LOG(ERROR) << "tls-ticket-key-file: could not open file " << file; return nullptr; @@ -245,7 +245,7 @@ read_quic_secret_file(const StringRef &path) { auto qkms = std::make_shared<QUICKeyingMaterials>(); auto &kms = qkms->keying_materials; - std::ifstream f(path.c_str()); + std::ifstream f(path.data()); if (!f) { LOG(ERROR) << "frontend-quic-secret-file: could not open file " << path; return nullptr; @@ -350,7 +350,7 @@ std::string read_passwd_from_file(const StringRef &opt, return line; } - std::ifstream in(filename.c_str(), std::ios::binary); + std::ifstream in(filename.data(), std::ios::binary); if (!in) { LOG(ERROR) << opt << ": Could not open key passwd file " << filename; return line; @@ -375,13 +375,12 @@ HeaderRefs::value_type parse_header(BlockAllocator &balloc, auto name_iov = make_byte_ref(balloc, std::distance(std::begin(optarg), colon) + 1); - auto p = name_iov.base; - p = std::copy(std::begin(optarg), colon, p); - util::inp_strlower(name_iov.base, p); + auto p = std::copy(std::begin(optarg), colon, std::begin(name_iov)); + util::inp_strlower(std::begin(name_iov), p); *p = '\0'; auto nv = - HeaderRef(StringRef{name_iov.base, p}, + HeaderRef(StringRef{std::span{std::begin(name_iov), p}}, make_string_ref(balloc, StringRef{value, std::end(optarg)})); if (!nghttp2_check_header_name(nv.name.byte(), nv.name.size()) || @@ -395,12 +394,12 @@ HeaderRefs::value_type parse_header(BlockAllocator &balloc, template <typename T> int parse_uint(T *dest, const StringRef &opt, const StringRef &optarg) { auto val = util::parse_uint(optarg); - if (val == -1) { + if (!val) { LOG(ERROR) << opt << ": bad value. Specify an integer >= 0."; return -1; } - *dest = val; + *dest = *val; return 0; } @@ -410,20 +409,20 @@ template <typename T> int parse_uint_with_unit(T *dest, const StringRef &opt, const StringRef &optarg) { auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { + if (!n) { LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; return -1; } if (static_cast<uint64_t>(std::numeric_limits<T>::max()) < - static_cast<uint64_t>(n)) { + static_cast<uint64_t>(*n)) { LOG(ERROR) << opt << ": too large. The value should be less than or equal to " << std::numeric_limits<T>::max(); return -1; } - *dest = n; + *dest = *n; return 0; } @@ -482,12 +481,12 @@ int parse_altsvc(AltSvc &altsvc, const StringRef &opt, namespace { // generated by gennghttpxfun.py -LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { - switch (namelen) { +LogFragmentType log_var_lookup_token(const StringRef &name) { + switch (name.size()) { case 3: switch (name[2]) { case 'd': - if (util::strieq_l("pi", name, 2)) { + if (util::strieq("pi"_sr, name, 2)) { return LogFragmentType::PID; } break; @@ -496,12 +495,12 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 4: switch (name[3]) { case 'h': - if (util::strieq_l("pat", name, 3)) { + if (util::strieq("pat"_sr, name, 3)) { return LogFragmentType::PATH; } break; case 'n': - if (util::strieq_l("alp", name, 3)) { + if (util::strieq("alp"_sr, name, 3)) { return LogFragmentType::ALPN; } break; @@ -510,12 +509,12 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 6: switch (name[5]) { case 'd': - if (util::strieq_l("metho", name, 5)) { + if (util::strieq("metho"_sr, name, 5)) { return LogFragmentType::METHOD; } break; case 's': - if (util::strieq_l("statu", name, 5)) { + if (util::strieq("statu"_sr, name, 5)) { return LogFragmentType::STATUS; } break; @@ -524,12 +523,12 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 7: switch (name[6]) { case 'i': - if (util::strieq_l("tls_sn", name, 6)) { + if (util::strieq("tls_sn"_sr, name, 6)) { return LogFragmentType::TLS_SNI; } break; case 't': - if (util::strieq_l("reques", name, 6)) { + if (util::strieq("reques"_sr, name, 6)) { return LogFragmentType::REQUEST; } break; @@ -538,15 +537,15 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 10: switch (name[9]) { case 'l': - if (util::strieq_l("time_loca", name, 9)) { + if (util::strieq("time_loca"_sr, name, 9)) { return LogFragmentType::TIME_LOCAL; } break; case 'r': - if (util::strieq_l("ssl_ciphe", name, 9)) { + if (util::strieq("ssl_ciphe"_sr, name, 9)) { return LogFragmentType::SSL_CIPHER; } - if (util::strieq_l("tls_ciphe", name, 9)) { + if (util::strieq("tls_ciphe"_sr, name, 9)) { return LogFragmentType::TLS_CIPHER; } break; @@ -555,15 +554,15 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 11: switch (name[10]) { case 'r': - if (util::strieq_l("remote_add", name, 10)) { + if (util::strieq("remote_add"_sr, name, 10)) { return LogFragmentType::REMOTE_ADDR; } break; case 't': - if (util::strieq_l("remote_por", name, 10)) { + if (util::strieq("remote_por"_sr, name, 10)) { return LogFragmentType::REMOTE_PORT; } - if (util::strieq_l("server_por", name, 10)) { + if (util::strieq("server_por"_sr, name, 10)) { return LogFragmentType::SERVER_PORT; } break; @@ -572,28 +571,28 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 12: switch (name[11]) { case '1': - if (util::strieq_l("time_iso860", name, 11)) { + if (util::strieq("time_iso860"_sr, name, 11)) { return LogFragmentType::TIME_ISO8601; } break; case 'e': - if (util::strieq_l("request_tim", name, 11)) { + if (util::strieq("request_tim"_sr, name, 11)) { return LogFragmentType::REQUEST_TIME; } break; case 'l': - if (util::strieq_l("ssl_protoco", name, 11)) { + if (util::strieq("ssl_protoco"_sr, name, 11)) { return LogFragmentType::SSL_PROTOCOL; } - if (util::strieq_l("tls_protoco", name, 11)) { + if (util::strieq("tls_protoco"_sr, name, 11)) { return LogFragmentType::TLS_PROTOCOL; } break; case 't': - if (util::strieq_l("backend_hos", name, 11)) { + if (util::strieq("backend_hos"_sr, name, 11)) { return LogFragmentType::BACKEND_HOST; } - if (util::strieq_l("backend_por", name, 11)) { + if (util::strieq("backend_por"_sr, name, 11)) { return LogFragmentType::BACKEND_PORT; } break; @@ -602,10 +601,10 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 14: switch (name[13]) { case 'd': - if (util::strieq_l("ssl_session_i", name, 13)) { + if (util::strieq("ssl_session_i"_sr, name, 13)) { return LogFragmentType::SSL_SESSION_ID; } - if (util::strieq_l("tls_session_i", name, 13)) { + if (util::strieq("tls_session_i"_sr, name, 13)) { return LogFragmentType::TLS_SESSION_ID; } break; @@ -614,7 +613,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 15: switch (name[14]) { case 't': - if (util::strieq_l("body_bytes_sen", name, 14)) { + if (util::strieq("body_bytes_sen"_sr, name, 14)) { return LogFragmentType::BODY_BYTES_SENT; } break; @@ -623,7 +622,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 16: switch (name[15]) { case 'n': - if (util::strieq_l("protocol_versio", name, 15)) { + if (util::strieq("protocol_versio"_sr, name, 15)) { return LogFragmentType::PROTOCOL_VERSION; } break; @@ -632,7 +631,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 17: switch (name[16]) { case 'l': - if (util::strieq_l("tls_client_seria", name, 16)) { + if (util::strieq("tls_client_seria"_sr, name, 16)) { return LogFragmentType::TLS_CLIENT_SERIAL; } break; @@ -641,15 +640,15 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 18: switch (name[17]) { case 'd': - if (util::strieq_l("ssl_session_reuse", name, 17)) { + if (util::strieq("ssl_session_reuse"_sr, name, 17)) { return LogFragmentType::SSL_SESSION_REUSED; } - if (util::strieq_l("tls_session_reuse", name, 17)) { + if (util::strieq("tls_session_reuse"_sr, name, 17)) { return LogFragmentType::TLS_SESSION_REUSED; } break; case 'y': - if (util::strieq_l("path_without_quer", name, 17)) { + if (util::strieq("path_without_quer"_sr, name, 17)) { return LogFragmentType::PATH_WITHOUT_QUERY; } break; @@ -658,7 +657,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 22: switch (name[21]) { case 'e': - if (util::strieq_l("tls_client_issuer_nam", name, 21)) { + if (util::strieq("tls_client_issuer_nam"_sr, name, 21)) { return LogFragmentType::TLS_CLIENT_ISSUER_NAME; } break; @@ -667,7 +666,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 23: switch (name[22]) { case 'e': - if (util::strieq_l("tls_client_subject_nam", name, 22)) { + if (util::strieq("tls_client_subject_nam"_sr, name, 22)) { return LogFragmentType::TLS_CLIENT_SUBJECT_NAME; } break; @@ -676,7 +675,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 27: switch (name[26]) { case '1': - if (util::strieq_l("tls_client_fingerprint_sha", name, 26)) { + if (util::strieq("tls_client_fingerprint_sha"_sr, name, 26)) { return LogFragmentType::TLS_CLIENT_FINGERPRINT_SHA1; } break; @@ -685,7 +684,7 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { case 29: switch (name[28]) { case '6': - if (util::strieq_l("tls_client_fingerprint_sha25", name, 28)) { + if (util::strieq("tls_client_fingerprint_sha25"_sr, name, 28)) { return LogFragmentType::TLS_CLIENT_FINGERPRINT_SHA256; } break; @@ -720,10 +719,9 @@ std::vector<LogFragment> parse_log_format(BlockAllocator &balloc, ++p; - const char *var_name; - size_t var_namelen; + StringRef var_name; if (p != eop && *p == '{') { - var_name = ++p; + auto var_name_start = ++p; for (; p != eop && var_token(*p); ++p) ; @@ -732,35 +730,33 @@ std::vector<LogFragment> parse_log_format(BlockAllocator &balloc, continue; } - var_namelen = p - var_name; + var_name = StringRef{var_name_start, p}; ++p; } else { - var_name = p; + auto var_name_start = p; for (; p != eop && var_token(*p); ++p) ; - var_namelen = p - var_name; + var_name = StringRef{var_name_start, p}; } - const char *value = nullptr; + auto value = std::begin(var_name); - auto type = log_var_lookup_token(var_name, var_namelen); + auto type = log_var_lookup_token(var_name); if (type == LogFragmentType::NONE) { - if (util::istarts_with_l(StringRef{var_name, var_namelen}, "http_")) { - if (util::streq_l("host", StringRef{var_name + str_size("http_"), - var_namelen - str_size("http_")})) { + if (util::istarts_with(var_name, "http_"_sr)) { + if ("host"_sr == var_name.substr(str_size("http_"))) { // Special handling of host header field. We will use // :authority header field if host header is missing. This // is a typical case in HTTP/2. type = LogFragmentType::AUTHORITY; } else { type = LogFragmentType::HTTP; - value = var_name + str_size("http_"); + value += str_size("http_"); } } else { - LOG(WARN) << "Unrecognized log format variable: " - << StringRef{var_name, var_namelen}; + LOG(WARN) << "Unrecognized log format variable: " << var_name; continue; } } @@ -773,23 +769,19 @@ std::vector<LogFragment> parse_log_format(BlockAllocator &balloc, literal_start = p; - if (value == nullptr) { + if (value == std::begin(var_name)) { res.emplace_back(type); continue; } { - auto iov = make_byte_ref( - balloc, std::distance(value, var_name + var_namelen) + 1); - auto p = iov.base; - p = std::copy(value, var_name + var_namelen, p); - for (auto cp = iov.base; cp != p; ++cp) { - if (*cp == '_') { - *cp = '-'; - } - } + auto iov = + make_byte_ref(balloc, std::distance(value, std::end(var_name)) + 1); + auto p = std::copy(value, std::end(var_name), std::begin(iov)); + std::transform(std::begin(iov), p, std::begin(iov), + [](auto c) { return c == '_' ? '-' : c; }); *p = '\0'; - res.emplace_back(type, StringRef{iov.base, p}); + res.emplace_back(type, StringRef{std::span{std::begin(iov), p}}); } } @@ -804,15 +796,15 @@ std::vector<LogFragment> parse_log_format(BlockAllocator &balloc, namespace { int parse_address_family(int *dest, const StringRef &opt, const StringRef &optarg) { - if (util::strieq_l("auto", optarg)) { + if (util::strieq("auto"_sr, optarg)) { *dest = AF_UNSPEC; return 0; } - if (util::strieq_l("IPv4", optarg)) { + if (util::strieq("IPv4"_sr, optarg)) { *dest = AF_INET; return 0; } - if (util::strieq_l("IPv6", optarg)) { + if (util::strieq("IPv6"_sr, optarg)) { *dest = AF_INET6; return 0; } @@ -826,12 +818,12 @@ namespace { int parse_duration(ev_tstamp *dest, const StringRef &opt, const StringRef &optarg) { auto t = util::parse_duration_with_unit(optarg); - if (t == std::numeric_limits<double>::infinity()) { + if (!t) { LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; return -1; } - *dest = t; + *dest = *t; return 0; } @@ -868,9 +860,9 @@ int parse_memcached_connection_params(MemcachedConnectionParams &out, auto end = std::find(first, last, ';'); auto param = StringRef{first, end}; - if (util::strieq_l("tls", param)) { + if (util::strieq("tls"_sr, param)) { out.tls = true; - } else if (util::strieq_l("no-tls", param)) { + } else if (util::strieq("no-tls"_sr, param)) { out.tls = false; } else if (!param.empty()) { LOG(ERROR) << opt << ": " << param << ": unknown keyword"; @@ -906,29 +898,29 @@ int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) { auto end = std::find(first, last, ';'); auto param = StringRef{first, end}; - if (util::strieq_l("tls", param)) { + if (util::strieq("tls"_sr, param)) { out.tls = true; - } else if (util::strieq_l("sni-fwd", param)) { + } else if (util::strieq("sni-fwd"_sr, param)) { out.sni_fwd = true; - } else if (util::strieq_l("no-tls", param)) { + } else if (util::strieq("no-tls"_sr, param)) { out.tls = false; - } else if (util::strieq_l("api", param)) { + } else if (util::strieq("api"_sr, param)) { if (out.alt_mode != UpstreamAltMode::NONE && out.alt_mode != UpstreamAltMode::API) { LOG(ERROR) << "frontend: api and healthmon are mutually exclusive"; return -1; } out.alt_mode = UpstreamAltMode::API; - } else if (util::strieq_l("healthmon", param)) { + } else if (util::strieq("healthmon"_sr, param)) { if (out.alt_mode != UpstreamAltMode::NONE && out.alt_mode != UpstreamAltMode::HEALTHMON) { LOG(ERROR) << "frontend: api and healthmon are mutually exclusive"; return -1; } out.alt_mode = UpstreamAltMode::HEALTHMON; - } else if (util::strieq_l("proxyproto", param)) { + } else if (util::strieq("proxyproto"_sr, param)) { out.proxyproto = true; - } else if (util::strieq_l("quic", param)) { + } else if (util::strieq("quic"_sr, param)) { #ifdef ENABLE_HTTP3 out.quic = true; #else // !ENABLE_HTTP3 @@ -977,11 +969,11 @@ namespace { int parse_downstream_param_duration(ev_tstamp &dest, const StringRef &name, const StringRef &value) { auto t = util::parse_duration_with_unit(value); - if (t == std::numeric_limits<double>::infinity()) { + if (!t) { LOG(ERROR) << "backend: " << name << ": bad value: '" << value << "'"; return -1; } - dest = t; + dest = *t; return 0; } } // namespace @@ -997,23 +989,22 @@ int parse_downstream_params(DownstreamParams &out, auto end = std::find(first, last, ';'); auto param = StringRef{first, end}; - if (util::istarts_with_l(param, "proto=")) { + if (util::istarts_with(param, "proto="_sr)) { auto protostr = StringRef{first + str_size("proto="), end}; if (protostr.empty()) { LOG(ERROR) << "backend: proto: protocol is empty"; return -1; } - if (util::streq_l("h2", std::begin(protostr), protostr.size())) { + if ("h2"_sr == protostr) { out.proto = Proto::HTTP2; - } else if (util::streq_l("http/1.1", std::begin(protostr), - protostr.size())) { + } else if ("http/1.1"_sr == protostr) { out.proto = Proto::HTTP1; } else { LOG(ERROR) << "backend: proto: unknown protocol " << protostr; return -1; } - } else if (util::istarts_with_l(param, "fall=")) { + } else if (util::istarts_with(param, "fall="_sr)) { auto valstr = StringRef{first + str_size("fall="), end}; if (valstr.empty()) { LOG(ERROR) << "backend: fall: non-negative integer is expected"; @@ -1021,13 +1012,13 @@ int parse_downstream_params(DownstreamParams &out, } auto n = util::parse_uint(valstr); - if (n == -1) { + if (!n) { LOG(ERROR) << "backend: fall: non-negative integer is expected"; return -1; } - out.fall = n; - } else if (util::istarts_with_l(param, "rise=")) { + out.fall = *n; + } else if (util::istarts_with(param, "rise="_sr)) { auto valstr = StringRef{first + str_size("rise="), end}; if (valstr.empty()) { LOG(ERROR) << "backend: rise: non-negative integer is expected"; @@ -1035,32 +1026,32 @@ int parse_downstream_params(DownstreamParams &out, } auto n = util::parse_uint(valstr); - if (n == -1) { + if (!n) { LOG(ERROR) << "backend: rise: non-negative integer is expected"; return -1; } - out.rise = n; - } else if (util::strieq_l("tls", param)) { + out.rise = *n; + } else if (util::strieq("tls"_sr, param)) { out.tls = true; - } else if (util::strieq_l("no-tls", param)) { + } else if (util::strieq("no-tls"_sr, param)) { out.tls = false; - } else if (util::istarts_with_l(param, "sni=")) { + } else if (util::istarts_with(param, "sni="_sr)) { out.sni = StringRef{first + str_size("sni="), end}; - } else if (util::istarts_with_l(param, "affinity=")) { + } else if (util::istarts_with(param, "affinity="_sr)) { auto valstr = StringRef{first + str_size("affinity="), end}; - if (util::strieq_l("none", valstr)) { + if (util::strieq("none"_sr, valstr)) { out.affinity.type = SessionAffinity::NONE; - } else if (util::strieq_l("ip", valstr)) { + } else if (util::strieq("ip"_sr, valstr)) { out.affinity.type = SessionAffinity::IP; - } else if (util::strieq_l("cookie", valstr)) { + } else if (util::strieq("cookie"_sr, valstr)) { out.affinity.type = SessionAffinity::COOKIE; } else { LOG(ERROR) << "backend: affinity: value must be one of none, ip, and cookie"; return -1; } - } else if (util::istarts_with_l(param, "affinity-cookie-name=")) { + } else if (util::istarts_with(param, "affinity-cookie-name="_sr)) { auto val = StringRef{first + str_size("affinity-cookie-name="), end}; if (val.empty()) { LOG(ERROR) @@ -1068,28 +1059,28 @@ int parse_downstream_params(DownstreamParams &out, return -1; } out.affinity.cookie.name = val; - } else if (util::istarts_with_l(param, "affinity-cookie-path=")) { + } else if (util::istarts_with(param, "affinity-cookie-path="_sr)) { out.affinity.cookie.path = StringRef{first + str_size("affinity-cookie-path="), end}; - } else if (util::istarts_with_l(param, "affinity-cookie-secure=")) { + } else if (util::istarts_with(param, "affinity-cookie-secure="_sr)) { auto valstr = StringRef{first + str_size("affinity-cookie-secure="), end}; - if (util::strieq_l("auto", valstr)) { + if (util::strieq("auto"_sr, valstr)) { out.affinity.cookie.secure = SessionAffinityCookieSecure::AUTO; - } else if (util::strieq_l("yes", valstr)) { + } else if (util::strieq("yes"_sr, valstr)) { out.affinity.cookie.secure = SessionAffinityCookieSecure::YES; - } else if (util::strieq_l("no", valstr)) { + } else if (util::strieq("no"_sr, valstr)) { out.affinity.cookie.secure = SessionAffinityCookieSecure::NO; } else { LOG(ERROR) << "backend: affinity-cookie-secure: value must be one of " "auto, yes, and no"; return -1; } - } else if (util::istarts_with_l(param, "affinity-cookie-stickiness=")) { + } else if (util::istarts_with(param, "affinity-cookie-stickiness="_sr)) { auto valstr = StringRef{first + str_size("affinity-cookie-stickiness="), end}; - if (util::strieq_l("loose", valstr)) { + if (util::strieq("loose"_sr, valstr)) { out.affinity.cookie.stickiness = SessionAffinityCookieStickiness::LOOSE; - } else if (util::strieq_l("strict", valstr)) { + } else if (util::strieq("strict"_sr, valstr)) { out.affinity.cookie.stickiness = SessionAffinityCookieStickiness::STRICT; } else { @@ -1097,28 +1088,28 @@ int parse_downstream_params(DownstreamParams &out, "either loose or strict"; return -1; } - } else if (util::strieq_l("dns", param)) { + } else if (util::strieq("dns"_sr, param)) { out.dns = true; - } else if (util::strieq_l("redirect-if-not-tls", param)) { + } else if (util::strieq("redirect-if-not-tls"_sr, param)) { out.redirect_if_not_tls = true; - } else if (util::strieq_l("upgrade-scheme", param)) { + } else if (util::strieq("upgrade-scheme"_sr, param)) { out.upgrade_scheme = true; - } else if (util::istarts_with_l(param, "mruby=")) { + } else if (util::istarts_with(param, "mruby="_sr)) { auto valstr = StringRef{first + str_size("mruby="), end}; out.mruby = valstr; - } else if (util::istarts_with_l(param, "read-timeout=")) { + } else if (util::istarts_with(param, "read-timeout="_sr)) { if (parse_downstream_param_duration( - out.read_timeout, StringRef::from_lit("read-timeout"), + out.read_timeout, "read-timeout"_sr, StringRef{first + str_size("read-timeout="), end}) == -1) { return -1; } - } else if (util::istarts_with_l(param, "write-timeout=")) { + } else if (util::istarts_with(param, "write-timeout="_sr)) { if (parse_downstream_param_duration( - out.write_timeout, StringRef::from_lit("write-timeout"), + out.write_timeout, "write-timeout"_sr, StringRef{first + str_size("write-timeout="), end}) == -1) { return -1; } - } else if (util::istarts_with_l(param, "weight=")) { + } else if (util::istarts_with(param, "weight="_sr)) { auto valstr = StringRef{first + str_size("weight="), end}; if (valstr.empty()) { LOG(ERROR) @@ -1127,20 +1118,20 @@ int parse_downstream_params(DownstreamParams &out, } auto n = util::parse_uint(valstr); - if (n < 1 || n > 256) { + if (!n || (n < 1 || n > 256)) { LOG(ERROR) << "backend: weight: non-negative integer [1, 256] is expected"; return -1; } - out.weight = n; - } else if (util::istarts_with_l(param, "group=")) { + out.weight = *n; + } else if (util::istarts_with(param, "group="_sr)) { auto valstr = StringRef{first + str_size("group="), end}; if (valstr.empty()) { LOG(ERROR) << "backend: group: empty string is not allowed"; return -1; } out.group = valstr; - } else if (util::istarts_with_l(param, "group-weight=")) { + } else if (util::istarts_with(param, "group-weight="_sr)) { auto valstr = StringRef{first + str_size("group-weight="), end}; if (valstr.empty()) { LOG(ERROR) << "backend: group-weight: non-negative integer [1, 256] is " @@ -1149,13 +1140,13 @@ int parse_downstream_params(DownstreamParams &out, } auto n = util::parse_uint(valstr); - if (n < 1 || n > 256) { + if (!n || (n < 1 || n > 256)) { LOG(ERROR) << "backend: group-weight: non-negative integer [1, 256] is " "expected"; return -1; } - out.group_weight = n; - } else if (util::strieq_l("dnf", param)) { + out.group_weight = *n; + } else if (util::strieq("dnf"_sr, param)) { out.dnf = true; } else if (!param.empty()) { LOG(ERROR) << "backend: " << param << ": unknown keyword"; @@ -1235,12 +1226,12 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, // This effectively makes empty pattern to "/". 2 for '/' and // terminal NULL character. auto iov = make_byte_ref(downstreamconf.balloc, raw_pattern.size() + 2); - auto p = iov.base; - p = std::copy(std::begin(raw_pattern), std::end(raw_pattern), p); - util::inp_strlower(iov.base, p); + auto p = std::copy(std::begin(raw_pattern), std::end(raw_pattern), + std::begin(iov)); + util::inp_strlower(std::begin(iov), p); *p++ = '/'; *p = '\0'; - pattern = StringRef{iov.base, p}; + pattern = StringRef{std::span{std::begin(iov), p}}; } else { auto path = http2::normalize_path_colon( downstreamconf.balloc, StringRef{slash, std::end(raw_pattern)}, @@ -1248,12 +1239,11 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, auto iov = make_byte_ref(downstreamconf.balloc, std::distance(std::begin(raw_pattern), slash) + path.size() + 1); - auto p = iov.base; - p = std::copy(std::begin(raw_pattern), slash, p); - util::inp_strlower(iov.base, p); + auto p = std::copy(std::begin(raw_pattern), slash, std::begin(iov)); + util::inp_strlower(std::begin(iov), p); p = std::copy(std::begin(path), std::end(path), p); *p = '\0'; - pattern = StringRef{iov.base, p}; + pattern = StringRef{std::span{std::begin(iov), p}}; } auto it = pattern_addr_indexer.find(pattern); if (it != std::end(pattern_addr_indexer)) { @@ -1385,10 +1375,10 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, router.add_route(path, idx, path_is_wildcard); auto iov = make_byte_ref(downstreamconf.balloc, host.size() + 1); - auto p = iov.base; - p = std::reverse_copy(std::begin(host), std::end(host), p); + auto p = std::reverse_copy(std::begin(host), std::end(host), + std::begin(iov)); *p = '\0'; - auto rev_host = StringRef{iov.base, p}; + auto rev_host = StringRef{std::span{std::begin(iov), p}}; rw_router.add_route(rev_host, wildcard_patterns.size() - 1); } else { @@ -1413,11 +1403,11 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, namespace { ForwardedNode parse_forwarded_node_type(const StringRef &optarg) { - if (util::strieq_l("obfuscated", optarg)) { + if (util::strieq("obfuscated"_sr, optarg)) { return ForwardedNode::OBFUSCATED; } - if (util::strieq_l("ip", optarg)) { + if (util::strieq("ip"_sr, optarg)) { return ForwardedNode::IP; } @@ -1450,23 +1440,23 @@ int parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt, auto codestr = StringRef{std::begin(optarg), eq}; unsigned int code; - if (codestr == StringRef::from_lit("*")) { + if (codestr == "*"_sr) { code = 0; } else { auto n = util::parse_uint(codestr); - if (n == -1 || n < 400 || n > 599) { + if (!n || n < 400 || n > 599) { LOG(ERROR) << opt << ": bad code: '" << codestr << "'"; return -1; } - code = static_cast<unsigned int>(n); + code = static_cast<unsigned int>(*n); } auto path = StringRef{eq + 1, std::end(optarg)}; std::vector<uint8_t> content; - auto fd = open(path.c_str(), O_RDONLY); + auto fd = open(path.data(), O_RDONLY); if (fd == -1) { auto error = errno; LOG(ERROR) << opt << ": " << optarg << ": " @@ -1515,7 +1505,7 @@ int parse_subcert_params(SubcertParams &out, const StringRef &src_params) { auto end = std::find(first, last, ';'); auto param = StringRef{first, end}; - if (util::istarts_with_l(param, "sct-dir=")) { + if (util::istarts_with(param, "sct-dir="_sr)) { #if defined(NGHTTP2_GENUINE_OPENSSL) || defined(NGHTTP2_OPENSSL_IS_BORINGSSL) auto sct_dir = StringRef{std::begin(param) + str_size("sct-dir="), std::end(param)}; @@ -1551,7 +1541,7 @@ int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt, const StringRef &dir_path) { std::array<char, STRERROR_BUFSIZE> errbuf; - auto dir = opendir(dir_path.c_str()); + auto dir = opendir(dir_path.data()); if (dir == nullptr) { auto error = errno; LOG(ERROR) << opt << ": " << dir_path << ": " @@ -1580,7 +1570,7 @@ int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt, auto name = StringRef{ent->d_name}; - if (name[0] == '.' || !util::iends_with_l(name, ".sct")) { + if (name[0] == '.' || !util::iends_with(name, ".sct"_sr)) { continue; } @@ -1667,7 +1657,7 @@ namespace { int parse_psk_secrets(Config *config, const StringRef &path) { auto &tlsconf = config->tls; - std::ifstream f(path.c_str(), std::ios::binary); + std::ifstream f(path.data(), std::ios::binary); if (!f) { LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": could not open file " << path; return -1; @@ -1733,7 +1723,7 @@ namespace { int parse_client_psk_secrets(Config *config, const StringRef &path) { auto &tlsconf = config->tls; - std::ifstream f(path.c_str(), std::ios::binary); + std::ifstream f(path.data(), std::ios::binary); if (!f) { LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": could not open file " << path; @@ -1776,8 +1766,8 @@ int parse_client_psk_secrets(Config *config, const StringRef &path) { tlsconf.client.psk.identity = make_string_ref(config->balloc, StringRef{std::begin(line), sep_it}); - tlsconf.client.psk.secret = - util::decode_hex(config->balloc, StringRef{sep_it + 1, std::end(line)}); + tlsconf.client.psk.secret = StringRef{util::decode_hex( + config->balloc, StringRef{sep_it + 1, std::end(line)})}; return 0; } @@ -1788,17 +1778,17 @@ int parse_client_psk_secrets(Config *config, const StringRef &path) { #endif // !OPENSSL_NO_PSK // generated by gennghttpxfun.py -int option_lookup_token(const char *name, size_t namelen) { - switch (namelen) { +int option_lookup_token(const StringRef &name) { + switch (name.size()) { case 4: switch (name[3]) { case 'f': - if (util::strieq_l("con", name, 3)) { + if (util::strieq("con"_sr, name, 3)) { return SHRPX_OPTID_CONF; } break; case 'r': - if (util::strieq_l("use", name, 3)) { + if (util::strieq("use"_sr, name, 3)) { return SHRPX_OPTID_USER; } break; @@ -1807,25 +1797,25 @@ int option_lookup_token(const char *name, size_t namelen) { case 6: switch (name[5]) { case 'a': - if (util::strieq_l("no-vi", name, 5)) { + if (util::strieq("no-vi"_sr, name, 5)) { return SHRPX_OPTID_NO_VIA; } break; case 'c': - if (util::strieq_l("altsv", name, 5)) { + if (util::strieq("altsv"_sr, name, 5)) { return SHRPX_OPTID_ALTSVC; } break; case 'n': - if (util::strieq_l("daemo", name, 5)) { + if (util::strieq("daemo"_sr, name, 5)) { return SHRPX_OPTID_DAEMON; } break; case 't': - if (util::strieq_l("cacer", name, 5)) { + if (util::strieq("cacer"_sr, name, 5)) { return SHRPX_OPTID_CACERT; } - if (util::strieq_l("clien", name, 5)) { + if (util::strieq("clien"_sr, name, 5)) { return SHRPX_OPTID_CLIENT; } break; @@ -1834,38 +1824,38 @@ int option_lookup_token(const char *name, size_t namelen) { case 7: switch (name[6]) { case 'd': - if (util::strieq_l("backen", name, 6)) { + if (util::strieq("backen"_sr, name, 6)) { return SHRPX_OPTID_BACKEND; } break; case 'e': - if (util::strieq_l("includ", name, 6)) { + if (util::strieq("includ"_sr, name, 6)) { return SHRPX_OPTID_INCLUDE; } break; case 'g': - if (util::strieq_l("backlo", name, 6)) { + if (util::strieq("backlo"_sr, name, 6)) { return SHRPX_OPTID_BACKLOG; } - if (util::strieq_l("paddin", name, 6)) { + if (util::strieq("paddin"_sr, name, 6)) { return SHRPX_OPTID_PADDING; } break; case 'p': - if (util::strieq_l("no-ocs", name, 6)) { + if (util::strieq("no-ocs"_sr, name, 6)) { return SHRPX_OPTID_NO_OCSP; } break; case 's': - if (util::strieq_l("cipher", name, 6)) { + if (util::strieq("cipher"_sr, name, 6)) { return SHRPX_OPTID_CIPHERS; } - if (util::strieq_l("worker", name, 6)) { + if (util::strieq("worker"_sr, name, 6)) { return SHRPX_OPTID_WORKERS; } break; case 't': - if (util::strieq_l("subcer", name, 6)) { + if (util::strieq("subcer"_sr, name, 6)) { return SHRPX_OPTID_SUBCERT; } break; @@ -1874,30 +1864,30 @@ int option_lookup_token(const char *name, size_t namelen) { case 8: switch (name[7]) { case 'd': - if (util::strieq_l("fronten", name, 7)) { + if (util::strieq("fronten"_sr, name, 7)) { return SHRPX_OPTID_FRONTEND; } break; case 'e': - if (util::strieq_l("insecur", name, 7)) { + if (util::strieq("insecur"_sr, name, 7)) { return SHRPX_OPTID_INSECURE; } - if (util::strieq_l("pid-fil", name, 7)) { + if (util::strieq("pid-fil"_sr, name, 7)) { return SHRPX_OPTID_PID_FILE; } break; case 'n': - if (util::strieq_l("fastope", name, 7)) { + if (util::strieq("fastope"_sr, name, 7)) { return SHRPX_OPTID_FASTOPEN; } break; case 's': - if (util::strieq_l("tls-ktl", name, 7)) { + if (util::strieq("tls-ktl"_sr, name, 7)) { return SHRPX_OPTID_TLS_KTLS; } break; case 't': - if (util::strieq_l("npn-lis", name, 7)) { + if (util::strieq("npn-lis"_sr, name, 7)) { return SHRPX_OPTID_NPN_LIST; } break; @@ -1906,20 +1896,20 @@ int option_lookup_token(const char *name, size_t namelen) { case 9: switch (name[8]) { case 'e': - if (util::strieq_l("no-kqueu", name, 8)) { + if (util::strieq("no-kqueu"_sr, name, 8)) { return SHRPX_OPTID_NO_KQUEUE; } - if (util::strieq_l("read-rat", name, 8)) { + if (util::strieq("read-rat"_sr, name, 8)) { return SHRPX_OPTID_READ_RATE; } break; case 'l': - if (util::strieq_l("log-leve", name, 8)) { + if (util::strieq("log-leve"_sr, name, 8)) { return SHRPX_OPTID_LOG_LEVEL; } break; case 't': - if (util::strieq_l("alpn-lis", name, 8)) { + if (util::strieq("alpn-lis"_sr, name, 8)) { return SHRPX_OPTID_ALPN_LIST; } break; @@ -1928,18 +1918,18 @@ int option_lookup_token(const char *name, size_t namelen) { case 10: switch (name[9]) { case 'e': - if (util::strieq_l("error-pag", name, 9)) { + if (util::strieq("error-pag"_sr, name, 9)) { return SHRPX_OPTID_ERROR_PAGE; } - if (util::strieq_l("mruby-fil", name, 9)) { + if (util::strieq("mruby-fil"_sr, name, 9)) { return SHRPX_OPTID_MRUBY_FILE; } - if (util::strieq_l("write-rat", name, 9)) { + if (util::strieq("write-rat"_sr, name, 9)) { return SHRPX_OPTID_WRITE_RATE; } break; case 't': - if (util::strieq_l("read-burs", name, 9)) { + if (util::strieq("read-burs"_sr, name, 9)) { return SHRPX_OPTID_READ_BURST; } break; @@ -1948,41 +1938,41 @@ int option_lookup_token(const char *name, size_t namelen) { case 11: switch (name[10]) { case 'e': - if (util::strieq_l("server-nam", name, 10)) { + if (util::strieq("server-nam"_sr, name, 10)) { return SHRPX_OPTID_SERVER_NAME; } break; case 'f': - if (util::strieq_l("no-quic-bp", name, 10)) { + if (util::strieq("no-quic-bp"_sr, name, 10)) { return SHRPX_OPTID_NO_QUIC_BPF; } break; case 'r': - if (util::strieq_l("tls-sct-di", name, 10)) { + if (util::strieq("tls-sct-di"_sr, name, 10)) { return SHRPX_OPTID_TLS_SCT_DIR; } break; case 's': - if (util::strieq_l("backend-tl", name, 10)) { + if (util::strieq("backend-tl"_sr, name, 10)) { return SHRPX_OPTID_BACKEND_TLS; } - if (util::strieq_l("ecdh-curve", name, 10)) { + if (util::strieq("ecdh-curve"_sr, name, 10)) { return SHRPX_OPTID_ECDH_CURVES; } - if (util::strieq_l("psk-secret", name, 10)) { + if (util::strieq("psk-secret"_sr, name, 10)) { return SHRPX_OPTID_PSK_SECRETS; } break; case 't': - if (util::strieq_l("write-burs", name, 10)) { + if (util::strieq("write-burs"_sr, name, 10)) { return SHRPX_OPTID_WRITE_BURST; } break; case 'y': - if (util::strieq_l("dns-max-tr", name, 10)) { + if (util::strieq("dns-max-tr"_sr, name, 10)) { return SHRPX_OPTID_DNS_MAX_TRY; } - if (util::strieq_l("http2-prox", name, 10)) { + if (util::strieq("http2-prox"_sr, name, 10)) { return SHRPX_OPTID_HTTP2_PROXY; } break; @@ -1991,38 +1981,38 @@ int option_lookup_token(const char *name, size_t namelen) { case 12: switch (name[11]) { case '4': - if (util::strieq_l("backend-ipv", name, 11)) { + if (util::strieq("backend-ipv"_sr, name, 11)) { return SHRPX_OPTID_BACKEND_IPV4; } break; case '6': - if (util::strieq_l("backend-ipv", name, 11)) { + if (util::strieq("backend-ipv"_sr, name, 11)) { return SHRPX_OPTID_BACKEND_IPV6; } break; case 'c': - if (util::strieq_l("http2-altsv", name, 11)) { + if (util::strieq("http2-altsv"_sr, name, 11)) { return SHRPX_OPTID_HTTP2_ALTSVC; } break; case 'e': - if (util::strieq_l("host-rewrit", name, 11)) { + if (util::strieq("host-rewrit"_sr, name, 11)) { return SHRPX_OPTID_HOST_REWRITE; } - if (util::strieq_l("http2-bridg", name, 11)) { + if (util::strieq("http2-bridg"_sr, name, 11)) { return SHRPX_OPTID_HTTP2_BRIDGE; } break; case 'p': - if (util::strieq_l("ocsp-startu", name, 11)) { + if (util::strieq("ocsp-startu"_sr, name, 11)) { return SHRPX_OPTID_OCSP_STARTUP; } break; case 'y': - if (util::strieq_l("client-prox", name, 11)) { + if (util::strieq("client-prox"_sr, name, 11)) { return SHRPX_OPTID_CLIENT_PROXY; } - if (util::strieq_l("forwarded-b", name, 11)) { + if (util::strieq("forwarded-b"_sr, name, 11)) { return SHRPX_OPTID_FORWARDED_BY; } break; @@ -2031,36 +2021,36 @@ int option_lookup_token(const char *name, size_t namelen) { case 13: switch (name[12]) { case 'd': - if (util::strieq_l("add-forwarde", name, 12)) { + if (util::strieq("add-forwarde"_sr, name, 12)) { return SHRPX_OPTID_ADD_FORWARDED; } - if (util::strieq_l("single-threa", name, 12)) { + if (util::strieq("single-threa"_sr, name, 12)) { return SHRPX_OPTID_SINGLE_THREAD; } break; case 'e': - if (util::strieq_l("dh-param-fil", name, 12)) { + if (util::strieq("dh-param-fil"_sr, name, 12)) { return SHRPX_OPTID_DH_PARAM_FILE; } - if (util::strieq_l("errorlog-fil", name, 12)) { + if (util::strieq("errorlog-fil"_sr, name, 12)) { return SHRPX_OPTID_ERRORLOG_FILE; } - if (util::strieq_l("rlimit-nofil", name, 12)) { + if (util::strieq("rlimit-nofil"_sr, name, 12)) { return SHRPX_OPTID_RLIMIT_NOFILE; } break; case 'r': - if (util::strieq_l("forwarded-fo", name, 12)) { + if (util::strieq("forwarded-fo"_sr, name, 12)) { return SHRPX_OPTID_FORWARDED_FOR; } break; case 's': - if (util::strieq_l("tls13-cipher", name, 12)) { + if (util::strieq("tls13-cipher"_sr, name, 12)) { return SHRPX_OPTID_TLS13_CIPHERS; } break; case 't': - if (util::strieq_l("verify-clien", name, 12)) { + if (util::strieq("verify-clien"_sr, name, 12)) { return SHRPX_OPTID_VERIFY_CLIENT; } break; @@ -2069,43 +2059,43 @@ int option_lookup_token(const char *name, size_t namelen) { case 14: switch (name[13]) { case 'd': - if (util::strieq_l("quic-server-i", name, 13)) { + if (util::strieq("quic-server-i"_sr, name, 13)) { return SHRPX_OPTID_QUIC_SERVER_ID; } break; case 'e': - if (util::strieq_l("accesslog-fil", name, 13)) { + if (util::strieq("accesslog-fil"_sr, name, 13)) { return SHRPX_OPTID_ACCESSLOG_FILE; } break; case 'h': - if (util::strieq_l("no-server-pus", name, 13)) { + if (util::strieq("no-server-pus"_sr, name, 13)) { return SHRPX_OPTID_NO_SERVER_PUSH; } break; case 'k': - if (util::strieq_l("rlimit-memloc", name, 13)) { + if (util::strieq("rlimit-memloc"_sr, name, 13)) { return SHRPX_OPTID_RLIMIT_MEMLOCK; } break; case 'p': - if (util::strieq_l("no-verify-ocs", name, 13)) { + if (util::strieq("no-verify-ocs"_sr, name, 13)) { return SHRPX_OPTID_NO_VERIFY_OCSP; } break; case 's': - if (util::strieq_l("backend-no-tl", name, 13)) { + if (util::strieq("backend-no-tl"_sr, name, 13)) { return SHRPX_OPTID_BACKEND_NO_TLS; } - if (util::strieq_l("client-cipher", name, 13)) { + if (util::strieq("client-cipher"_sr, name, 13)) { return SHRPX_OPTID_CLIENT_CIPHERS; } - if (util::strieq_l("single-proces", name, 13)) { + if (util::strieq("single-proces"_sr, name, 13)) { return SHRPX_OPTID_SINGLE_PROCESS; } break; case 't': - if (util::strieq_l("tls-proto-lis", name, 13)) { + if (util::strieq("tls-proto-lis"_sr, name, 13)) { return SHRPX_OPTID_TLS_PROTO_LIST; } break; @@ -2114,22 +2104,22 @@ int option_lookup_token(const char *name, size_t namelen) { case 15: switch (name[14]) { case 'e': - if (util::strieq_l("no-host-rewrit", name, 14)) { + if (util::strieq("no-host-rewrit"_sr, name, 14)) { return SHRPX_OPTID_NO_HOST_REWRITE; } break; case 'g': - if (util::strieq_l("errorlog-syslo", name, 14)) { + if (util::strieq("errorlog-syslo"_sr, name, 14)) { return SHRPX_OPTID_ERRORLOG_SYSLOG; } break; case 's': - if (util::strieq_l("frontend-no-tl", name, 14)) { + if (util::strieq("frontend-no-tl"_sr, name, 14)) { return SHRPX_OPTID_FRONTEND_NO_TLS; } break; case 'y': - if (util::strieq_l("syslog-facilit", name, 14)) { + if (util::strieq("syslog-facilit"_sr, name, 14)) { return SHRPX_OPTID_SYSLOG_FACILITY; } break; @@ -2138,26 +2128,26 @@ int option_lookup_token(const char *name, size_t namelen) { case 16: switch (name[15]) { case 'e': - if (util::strieq_l("certificate-fil", name, 15)) { + if (util::strieq("certificate-fil"_sr, name, 15)) { return SHRPX_OPTID_CERTIFICATE_FILE; } - if (util::strieq_l("client-cert-fil", name, 15)) { + if (util::strieq("client-cert-fil"_sr, name, 15)) { return SHRPX_OPTID_CLIENT_CERT_FILE; } - if (util::strieq_l("private-key-fil", name, 15)) { + if (util::strieq("private-key-fil"_sr, name, 15)) { return SHRPX_OPTID_PRIVATE_KEY_FILE; } - if (util::strieq_l("worker-read-rat", name, 15)) { + if (util::strieq("worker-read-rat"_sr, name, 15)) { return SHRPX_OPTID_WORKER_READ_RATE; } break; case 'g': - if (util::strieq_l("accesslog-syslo", name, 15)) { + if (util::strieq("accesslog-syslo"_sr, name, 15)) { return SHRPX_OPTID_ACCESSLOG_SYSLOG; } break; case 't': - if (util::strieq_l("accesslog-forma", name, 15)) { + if (util::strieq("accesslog-forma"_sr, name, 15)) { return SHRPX_OPTID_ACCESSLOG_FORMAT; } break; @@ -2166,26 +2156,26 @@ int option_lookup_token(const char *name, size_t namelen) { case 17: switch (name[16]) { case 'e': - if (util::strieq_l("no-server-rewrit", name, 16)) { + if (util::strieq("no-server-rewrit"_sr, name, 16)) { return SHRPX_OPTID_NO_SERVER_REWRITE; } - if (util::strieq_l("worker-write-rat", name, 16)) { + if (util::strieq("worker-write-rat"_sr, name, 16)) { return SHRPX_OPTID_WORKER_WRITE_RATE; } break; case 's': - if (util::strieq_l("backend-http1-tl", name, 16)) { + if (util::strieq("backend-http1-tl"_sr, name, 16)) { return SHRPX_OPTID_BACKEND_HTTP1_TLS; } - if (util::strieq_l("max-header-field", name, 16)) { + if (util::strieq("max-header-field"_sr, name, 16)) { return SHRPX_OPTID_MAX_HEADER_FIELDS; } break; case 't': - if (util::strieq_l("dns-cache-timeou", name, 16)) { + if (util::strieq("dns-cache-timeou"_sr, name, 16)) { return SHRPX_OPTID_DNS_CACHE_TIMEOUT; } - if (util::strieq_l("worker-read-burs", name, 16)) { + if (util::strieq("worker-read-burs"_sr, name, 16)) { return SHRPX_OPTID_WORKER_READ_BURST; } break; @@ -2194,25 +2184,25 @@ int option_lookup_token(const char *name, size_t namelen) { case 18: switch (name[17]) { case 'a': - if (util::strieq_l("tls-max-early-dat", name, 17)) { + if (util::strieq("tls-max-early-dat"_sr, name, 17)) { return SHRPX_OPTID_TLS_MAX_EARLY_DATA; } break; case 'r': - if (util::strieq_l("add-request-heade", name, 17)) { + if (util::strieq("add-request-heade"_sr, name, 17)) { return SHRPX_OPTID_ADD_REQUEST_HEADER; } break; case 's': - if (util::strieq_l("client-psk-secret", name, 17)) { + if (util::strieq("client-psk-secret"_sr, name, 17)) { return SHRPX_OPTID_CLIENT_PSK_SECRETS; } break; case 't': - if (util::strieq_l("dns-lookup-timeou", name, 17)) { + if (util::strieq("dns-lookup-timeou"_sr, name, 17)) { return SHRPX_OPTID_DNS_LOOKUP_TIMEOUT; } - if (util::strieq_l("worker-write-burs", name, 17)) { + if (util::strieq("worker-write-burs"_sr, name, 17)) { return SHRPX_OPTID_WORKER_WRITE_BURST; } break; @@ -2221,37 +2211,37 @@ int option_lookup_token(const char *name, size_t namelen) { case 19: switch (name[18]) { case 'e': - if (util::strieq_l("no-location-rewrit", name, 18)) { + if (util::strieq("no-location-rewrit"_sr, name, 18)) { return SHRPX_OPTID_NO_LOCATION_REWRITE; } - if (util::strieq_l("require-http-schem", name, 18)) { + if (util::strieq("require-http-schem"_sr, name, 18)) { return SHRPX_OPTID_REQUIRE_HTTP_SCHEME; } - if (util::strieq_l("tls-ticket-key-fil", name, 18)) { + if (util::strieq("tls-ticket-key-fil"_sr, name, 18)) { return SHRPX_OPTID_TLS_TICKET_KEY_FILE; } break; case 'f': - if (util::strieq_l("backend-max-backof", name, 18)) { + if (util::strieq("backend-max-backof"_sr, name, 18)) { return SHRPX_OPTID_BACKEND_MAX_BACKOFF; } break; case 'r': - if (util::strieq_l("add-response-heade", name, 18)) { + if (util::strieq("add-response-heade"_sr, name, 18)) { return SHRPX_OPTID_ADD_RESPONSE_HEADER; } - if (util::strieq_l("add-x-forwarded-fo", name, 18)) { + if (util::strieq("add-x-forwarded-fo"_sr, name, 18)) { return SHRPX_OPTID_ADD_X_FORWARDED_FOR; } - if (util::strieq_l("header-field-buffe", name, 18)) { + if (util::strieq("header-field-buffe"_sr, name, 18)) { return SHRPX_OPTID_HEADER_FIELD_BUFFER; } break; case 't': - if (util::strieq_l("redirect-https-por", name, 18)) { + if (util::strieq("redirect-https-por"_sr, name, 18)) { return SHRPX_OPTID_REDIRECT_HTTPS_PORT; } - if (util::strieq_l("stream-read-timeou", name, 18)) { + if (util::strieq("stream-read-timeou"_sr, name, 18)) { return SHRPX_OPTID_STREAM_READ_TIMEOUT; } break; @@ -2260,36 +2250,36 @@ int option_lookup_token(const char *name, size_t namelen) { case 20: switch (name[19]) { case 'g': - if (util::strieq_l("frontend-frame-debu", name, 19)) { + if (util::strieq("frontend-frame-debu"_sr, name, 19)) { return SHRPX_OPTID_FRONTEND_FRAME_DEBUG; } break; case 'l': - if (util::strieq_l("ocsp-update-interva", name, 19)) { + if (util::strieq("ocsp-update-interva"_sr, name, 19)) { return SHRPX_OPTID_OCSP_UPDATE_INTERVAL; } break; case 's': - if (util::strieq_l("max-worker-processe", name, 19)) { + if (util::strieq("max-worker-processe"_sr, name, 19)) { return SHRPX_OPTID_MAX_WORKER_PROCESSES; } - if (util::strieq_l("tls13-client-cipher", name, 19)) { + if (util::strieq("tls13-client-cipher"_sr, name, 19)) { return SHRPX_OPTID_TLS13_CLIENT_CIPHERS; } break; case 't': - if (util::strieq_l("backend-read-timeou", name, 19)) { + if (util::strieq("backend-read-timeou"_sr, name, 19)) { return SHRPX_OPTID_BACKEND_READ_TIMEOUT; } - if (util::strieq_l("stream-write-timeou", name, 19)) { + if (util::strieq("stream-write-timeou"_sr, name, 19)) { return SHRPX_OPTID_STREAM_WRITE_TIMEOUT; } - if (util::strieq_l("verify-client-cacer", name, 19)) { + if (util::strieq("verify-client-cacer"_sr, name, 19)) { return SHRPX_OPTID_VERIFY_CLIENT_CACERT; } break; case 'y': - if (util::strieq_l("api-max-request-bod", name, 19)) { + if (util::strieq("api-max-request-bod"_sr, name, 19)) { return SHRPX_OPTID_API_MAX_REQUEST_BODY; } break; @@ -2298,48 +2288,48 @@ int option_lookup_token(const char *name, size_t namelen) { case 21: switch (name[20]) { case 'd': - if (util::strieq_l("backend-tls-sni-fiel", name, 20)) { + if (util::strieq("backend-tls-sni-fiel"_sr, name, 20)) { return SHRPX_OPTID_BACKEND_TLS_SNI_FIELD; } break; case 'e': - if (util::strieq_l("quic-bpf-program-fil", name, 20)) { + if (util::strieq("quic-bpf-program-fil"_sr, name, 20)) { return SHRPX_OPTID_QUIC_BPF_PROGRAM_FILE; } break; case 'l': - if (util::strieq_l("accept-proxy-protoco", name, 20)) { + if (util::strieq("accept-proxy-protoco"_sr, name, 20)) { return SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL; } break; case 'n': - if (util::strieq_l("tls-max-proto-versio", name, 20)) { + if (util::strieq("tls-max-proto-versio"_sr, name, 20)) { return SHRPX_OPTID_TLS_MAX_PROTO_VERSION; } - if (util::strieq_l("tls-min-proto-versio", name, 20)) { + if (util::strieq("tls-min-proto-versio"_sr, name, 20)) { return SHRPX_OPTID_TLS_MIN_PROTO_VERSION; } break; case 'r': - if (util::strieq_l("tls-ticket-key-ciphe", name, 20)) { + if (util::strieq("tls-ticket-key-ciphe"_sr, name, 20)) { return SHRPX_OPTID_TLS_TICKET_KEY_CIPHER; } break; case 's': - if (util::strieq_l("frontend-max-request", name, 20)) { + if (util::strieq("frontend-max-request"_sr, name, 20)) { return SHRPX_OPTID_FRONTEND_MAX_REQUESTS; } break; case 't': - if (util::strieq_l("backend-write-timeou", name, 20)) { + if (util::strieq("backend-write-timeou"_sr, name, 20)) { return SHRPX_OPTID_BACKEND_WRITE_TIMEOUT; } - if (util::strieq_l("frontend-read-timeou", name, 20)) { + if (util::strieq("frontend-read-timeou"_sr, name, 20)) { return SHRPX_OPTID_FRONTEND_READ_TIMEOUT; } break; case 'y': - if (util::strieq_l("accesslog-write-earl", name, 20)) { + if (util::strieq("accesslog-write-earl"_sr, name, 20)) { return SHRPX_OPTID_ACCESSLOG_WRITE_EARLY; } break; @@ -2348,25 +2338,25 @@ int option_lookup_token(const char *name, size_t namelen) { case 22: switch (name[21]) { case 'i': - if (util::strieq_l("backend-http-proxy-ur", name, 21)) { + if (util::strieq("backend-http-proxy-ur"_sr, name, 21)) { return SHRPX_OPTID_BACKEND_HTTP_PROXY_URI; } break; case 'r': - if (util::strieq_l("backend-request-buffe", name, 21)) { + if (util::strieq("backend-request-buffe"_sr, name, 21)) { return SHRPX_OPTID_BACKEND_REQUEST_BUFFER; } - if (util::strieq_l("frontend-quic-qlog-di", name, 21)) { + if (util::strieq("frontend-quic-qlog-di"_sr, name, 21)) { return SHRPX_OPTID_FRONTEND_QUIC_QLOG_DIR; } break; case 't': - if (util::strieq_l("frontend-write-timeou", name, 21)) { + if (util::strieq("frontend-write-timeou"_sr, name, 21)) { return SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT; } break; case 'y': - if (util::strieq_l("backend-address-famil", name, 21)) { + if (util::strieq("backend-address-famil"_sr, name, 21)) { return SHRPX_OPTID_BACKEND_ADDRESS_FAMILY; } break; @@ -2375,28 +2365,28 @@ int option_lookup_token(const char *name, size_t namelen) { case 23: switch (name[22]) { case 'e': - if (util::strieq_l("client-private-key-fil", name, 22)) { + if (util::strieq("client-private-key-fil"_sr, name, 22)) { return SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE; } - if (util::strieq_l("private-key-passwd-fil", name, 22)) { + if (util::strieq("private-key-passwd-fil"_sr, name, 22)) { return SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE; } break; case 'g': - if (util::strieq_l("frontend-quic-debug-lo", name, 22)) { + if (util::strieq("frontend-quic-debug-lo"_sr, name, 22)) { return SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG; } break; case 'r': - if (util::strieq_l("backend-response-buffe", name, 22)) { + if (util::strieq("backend-response-buffe"_sr, name, 22)) { return SHRPX_OPTID_BACKEND_RESPONSE_BUFFER; } break; case 't': - if (util::strieq_l("backend-connect-timeou", name, 22)) { + if (util::strieq("backend-connect-timeou"_sr, name, 22)) { return SHRPX_OPTID_BACKEND_CONNECT_TIMEOUT; } - if (util::strieq_l("frontend-header-timeou", name, 22)) { + if (util::strieq("frontend-header-timeou"_sr, name, 22)) { return SHRPX_OPTID_FRONTEND_HEADER_TIMEOUT; } break; @@ -2405,33 +2395,33 @@ int option_lookup_token(const char *name, size_t namelen) { case 24: switch (name[23]) { case 'a': - if (util::strieq_l("frontend-quic-early-dat", name, 23)) { + if (util::strieq("frontend-quic-early-dat"_sr, name, 23)) { return SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA; } break; case 'd': - if (util::strieq_l("strip-incoming-forwarde", name, 23)) { + if (util::strieq("strip-incoming-forwarde"_sr, name, 23)) { return SHRPX_OPTID_STRIP_INCOMING_FORWARDED; } - if (util::strieq_l("tls-ticket-key-memcache", name, 23)) { + if (util::strieq("tls-ticket-key-memcache"_sr, name, 23)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED; } break; case 'e': - if (util::strieq_l("fetch-ocsp-response-fil", name, 23)) { + if (util::strieq("fetch-ocsp-response-fil"_sr, name, 23)) { return SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE; } break; case 'o': - if (util::strieq_l("no-add-x-forwarded-prot", name, 23)) { + if (util::strieq("no-add-x-forwarded-prot"_sr, name, 23)) { return SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO; } break; case 't': - if (util::strieq_l("listener-disable-timeou", name, 23)) { + if (util::strieq("listener-disable-timeou"_sr, name, 23)) { return SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT; } - if (util::strieq_l("tls-dyn-rec-idle-timeou", name, 23)) { + if (util::strieq("tls-dyn-rec-idle-timeou"_sr, name, 23)) { return SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT; } break; @@ -2440,28 +2430,28 @@ int option_lookup_token(const char *name, size_t namelen) { case 25: switch (name[24]) { case 'e': - if (util::strieq_l("backend-http2-window-siz", name, 24)) { + if (util::strieq("backend-http2-window-siz"_sr, name, 24)) { return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE; } - if (util::strieq_l("frontend-quic-secret-fil", name, 24)) { + if (util::strieq("frontend-quic-secret-fil"_sr, name, 24)) { return SHRPX_OPTID_FRONTEND_QUIC_SECRET_FILE; } break; case 'g': - if (util::strieq_l("http2-no-cookie-crumblin", name, 24)) { + if (util::strieq("http2-no-cookie-crumblin"_sr, name, 24)) { return SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING; } break; case 's': - if (util::strieq_l("backend-http2-window-bit", name, 24)) { + if (util::strieq("backend-http2-window-bit"_sr, name, 24)) { return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS; } - if (util::strieq_l("max-request-header-field", name, 24)) { + if (util::strieq("max-request-header-field"_sr, name, 24)) { return SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS; } break; case 't': - if (util::strieq_l("frontend-quic-initial-rt", name, 24)) { + if (util::strieq("frontend-quic-initial-rt"_sr, name, 24)) { return SHRPX_OPTID_FRONTEND_QUIC_INITIAL_RTT; } break; @@ -2470,37 +2460,37 @@ int option_lookup_token(const char *name, size_t namelen) { case 26: switch (name[25]) { case 'a': - if (util::strieq_l("tls-no-postpone-early-dat", name, 25)) { + if (util::strieq("tls-no-postpone-early-dat"_sr, name, 25)) { return SHRPX_OPTID_TLS_NO_POSTPONE_EARLY_DATA; } break; case 'e': - if (util::strieq_l("frontend-http2-window-siz", name, 25)) { + if (util::strieq("frontend-http2-window-siz"_sr, name, 25)) { return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE; } - if (util::strieq_l("frontend-http3-window-siz", name, 25)) { + if (util::strieq("frontend-http3-window-siz"_sr, name, 25)) { return SHRPX_OPTID_FRONTEND_HTTP3_WINDOW_SIZE; } break; case 's': - if (util::strieq_l("frontend-http2-window-bit", name, 25)) { + if (util::strieq("frontend-http2-window-bit"_sr, name, 25)) { return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS; } - if (util::strieq_l("max-response-header-field", name, 25)) { + if (util::strieq("max-response-header-field"_sr, name, 25)) { return SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS; } break; case 't': - if (util::strieq_l("backend-keep-alive-timeou", name, 25)) { + if (util::strieq("backend-keep-alive-timeou"_sr, name, 25)) { return SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT; } - if (util::strieq_l("frontend-quic-idle-timeou", name, 25)) { + if (util::strieq("frontend-quic-idle-timeou"_sr, name, 25)) { return SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT; } - if (util::strieq_l("no-http2-cipher-black-lis", name, 25)) { + if (util::strieq("no-http2-cipher-black-lis"_sr, name, 25)) { return SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST; } - if (util::strieq_l("no-http2-cipher-block-lis", name, 25)) { + if (util::strieq("no-http2-cipher-block-lis"_sr, name, 25)) { return SHRPX_OPTID_NO_HTTP2_CIPHER_BLOCK_LIST; } break; @@ -2509,39 +2499,39 @@ int option_lookup_token(const char *name, size_t namelen) { case 27: switch (name[26]) { case 'd': - if (util::strieq_l("tls-session-cache-memcache", name, 26)) { + if (util::strieq("tls-session-cache-memcache"_sr, name, 26)) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED; } break; case 'n': - if (util::strieq_l("frontend-quic-require-toke", name, 26)) { + if (util::strieq("frontend-quic-require-toke"_sr, name, 26)) { return SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN; } break; case 'r': - if (util::strieq_l("request-header-field-buffe", name, 26)) { + if (util::strieq("request-header-field-buffe"_sr, name, 26)) { return SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER; } break; case 's': - if (util::strieq_l("worker-frontend-connection", name, 26)) { + if (util::strieq("worker-frontend-connection"_sr, name, 26)) { return SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS; } break; case 't': - if (util::strieq_l("frontend-http2-idle-timeou", name, 26)) { + if (util::strieq("frontend-http2-idle-timeou"_sr, name, 26)) { return SHRPX_OPTID_FRONTEND_HTTP2_IDLE_TIMEOUT; } - if (util::strieq_l("frontend-http2-read-timeou", name, 26)) { + if (util::strieq("frontend-http2-read-timeou"_sr, name, 26)) { return SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT; } - if (util::strieq_l("frontend-http3-idle-timeou", name, 26)) { + if (util::strieq("frontend-http3-idle-timeou"_sr, name, 26)) { return SHRPX_OPTID_FRONTEND_HTTP3_IDLE_TIMEOUT; } - if (util::strieq_l("frontend-http3-read-timeou", name, 26)) { + if (util::strieq("frontend-http3-read-timeou"_sr, name, 26)) { return SHRPX_OPTID_FRONTEND_HTTP3_READ_TIMEOUT; } - if (util::strieq_l("frontend-keep-alive-timeou", name, 26)) { + if (util::strieq("frontend-keep-alive-timeou"_sr, name, 26)) { return SHRPX_OPTID_FRONTEND_KEEP_ALIVE_TIMEOUT; } break; @@ -2550,30 +2540,30 @@ int option_lookup_token(const char *name, size_t namelen) { case 28: switch (name[27]) { case 'a': - if (util::strieq_l("no-strip-incoming-early-dat", name, 27)) { + if (util::strieq("no-strip-incoming-early-dat"_sr, name, 27)) { return SHRPX_OPTID_NO_STRIP_INCOMING_EARLY_DATA; } break; case 'd': - if (util::strieq_l("tls-dyn-rec-warmup-threshol", name, 27)) { + if (util::strieq("tls-dyn-rec-warmup-threshol"_sr, name, 27)) { return SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD; } break; case 'r': - if (util::strieq_l("response-header-field-buffe", name, 27)) { + if (util::strieq("response-header-field-buffe"_sr, name, 27)) { return SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER; } break; case 's': - if (util::strieq_l("http2-max-concurrent-stream", name, 27)) { + if (util::strieq("http2-max-concurrent-stream"_sr, name, 27)) { return SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS; } - if (util::strieq_l("tls-ticket-key-memcached-tl", name, 27)) { + if (util::strieq("tls-ticket-key-memcached-tl"_sr, name, 27)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS; } break; case 't': - if (util::strieq_l("backend-connections-per-hos", name, 27)) { + if (util::strieq("backend-connections-per-hos"_sr, name, 27)) { return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST; } break; @@ -2582,25 +2572,25 @@ int option_lookup_token(const char *name, size_t namelen) { case 30: switch (name[29]) { case 'd': - if (util::strieq_l("verify-client-tolerate-expire", name, 29)) { + if (util::strieq("verify-client-tolerate-expire"_sr, name, 29)) { return SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED; } break; case 'e': - if (util::strieq_l("frontend-http3-max-window-siz", name, 29)) { + if (util::strieq("frontend-http3-max-window-siz"_sr, name, 29)) { return SHRPX_OPTID_FRONTEND_HTTP3_MAX_WINDOW_SIZE; } break; case 'r': - if (util::strieq_l("ignore-per-pattern-mruby-erro", name, 29)) { + if (util::strieq("ignore-per-pattern-mruby-erro"_sr, name, 29)) { return SHRPX_OPTID_IGNORE_PER_PATTERN_MRUBY_ERROR; } - if (util::strieq_l("strip-incoming-x-forwarded-fo", name, 29)) { + if (util::strieq("strip-incoming-x-forwarded-fo"_sr, name, 29)) { return SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR; } break; case 't': - if (util::strieq_l("backend-http2-settings-timeou", name, 29)) { + if (util::strieq("backend-http2-settings-timeou"_sr, name, 29)) { return SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT; } break; @@ -2609,12 +2599,12 @@ int option_lookup_token(const char *name, size_t namelen) { case 31: switch (name[30]) { case 's': - if (util::strieq_l("tls-session-cache-memcached-tl", name, 30)) { + if (util::strieq("tls-session-cache-memcached-tl"_sr, name, 30)) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS; } break; case 't': - if (util::strieq_l("frontend-http2-settings-timeou", name, 30)) { + if (util::strieq("frontend-http2-settings-timeou"_sr, name, 30)) { return SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT; } break; @@ -2623,7 +2613,7 @@ int option_lookup_token(const char *name, size_t namelen) { case 32: switch (name[31]) { case 'd': - if (util::strieq_l("backend-connections-per-fronten", name, 31)) { + if (util::strieq("backend-connections-per-fronten"_sr, name, 31)) { return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND; } break; @@ -2632,18 +2622,18 @@ int option_lookup_token(const char *name, size_t namelen) { case 33: switch (name[32]) { case 'l': - if (util::strieq_l("tls-ticket-key-memcached-interva", name, 32)) { + if (util::strieq("tls-ticket-key-memcached-interva"_sr, name, 32)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL; } - if (util::strieq_l("tls-ticket-key-memcached-max-fai", name, 32)) { + if (util::strieq("tls-ticket-key-memcached-max-fai"_sr, name, 32)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL; } break; case 't': - if (util::strieq_l("client-no-http2-cipher-black-lis", name, 32)) { + if (util::strieq("client-no-http2-cipher-black-lis"_sr, name, 32)) { return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST; } - if (util::strieq_l("client-no-http2-cipher-block-lis", name, 32)) { + if (util::strieq("client-no-http2-cipher-block-lis"_sr, name, 32)) { return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST; } break; @@ -2652,22 +2642,22 @@ int option_lookup_token(const char *name, size_t namelen) { case 34: switch (name[33]) { case 'e': - if (util::strieq_l("tls-ticket-key-memcached-cert-fil", name, 33)) { + if (util::strieq("tls-ticket-key-memcached-cert-fil"_sr, name, 33)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE; } break; case 'r': - if (util::strieq_l("frontend-http2-dump-request-heade", name, 33)) { + if (util::strieq("frontend-http2-dump-request-heade"_sr, name, 33)) { return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER; } break; case 't': - if (util::strieq_l("backend-http1-connections-per-hos", name, 33)) { + if (util::strieq("backend-http1-connections-per-hos"_sr, name, 33)) { return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST; } break; case 'y': - if (util::strieq_l("tls-ticket-key-memcached-max-retr", name, 33)) { + if (util::strieq("tls-ticket-key-memcached-max-retr"_sr, name, 33)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY; } break; @@ -2676,20 +2666,20 @@ int option_lookup_token(const char *name, size_t namelen) { case 35: switch (name[34]) { case 'e': - if (util::strieq_l("frontend-http2-optimize-window-siz", name, 34)) { + if (util::strieq("frontend-http2-optimize-window-siz"_sr, name, 34)) { return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE; } break; case 'o': - if (util::strieq_l("no-strip-incoming-x-forwarded-prot", name, 34)) { + if (util::strieq("no-strip-incoming-x-forwarded-prot"_sr, name, 34)) { return SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO; } break; case 'r': - if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) { + if (util::strieq("frontend-http2-dump-response-heade"_sr, name, 34)) { return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER; } - if (util::strieq_l("frontend-quic-congestion-controlle", name, 34)) { + if (util::strieq("frontend-quic-congestion-controlle"_sr, name, 34)) { return SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER; } break; @@ -2698,25 +2688,25 @@ int option_lookup_token(const char *name, size_t namelen) { case 36: switch (name[35]) { case 'd': - if (util::strieq_l("worker-process-grace-shutdown-perio", name, 35)) { + if (util::strieq("worker-process-grace-shutdown-perio"_sr, name, 35)) { return SHRPX_OPTID_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD; } break; case 'e': - if (util::strieq_l("backend-http2-connection-window-siz", name, 35)) { + if (util::strieq("backend-http2-connection-window-siz"_sr, name, 35)) { return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE; } break; case 'r': - if (util::strieq_l("backend-http2-connections-per-worke", name, 35)) { + if (util::strieq("backend-http2-connections-per-worke"_sr, name, 35)) { return SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER; } break; case 's': - if (util::strieq_l("backend-http2-connection-window-bit", name, 35)) { + if (util::strieq("backend-http2-connection-window-bit"_sr, name, 35)) { return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS; } - if (util::strieq_l("backend-http2-max-concurrent-stream", name, 35)) { + if (util::strieq("backend-http2-max-concurrent-stream"_sr, name, 35)) { return SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS; } break; @@ -2725,24 +2715,24 @@ int option_lookup_token(const char *name, size_t namelen) { case 37: switch (name[36]) { case 'e': - if (util::strieq_l("frontend-http2-connection-window-siz", name, 36)) { + if (util::strieq("frontend-http2-connection-window-siz"_sr, name, 36)) { return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE; } - if (util::strieq_l("frontend-http3-connection-window-siz", name, 36)) { + if (util::strieq("frontend-http3-connection-window-siz"_sr, name, 36)) { return SHRPX_OPTID_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE; } - if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) { + if (util::strieq("tls-session-cache-memcached-cert-fil"_sr, name, 36)) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE; } break; case 's': - if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) { + if (util::strieq("frontend-http2-connection-window-bit"_sr, name, 36)) { return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS; } - if (util::strieq_l("frontend-http2-max-concurrent-stream", name, 36)) { + if (util::strieq("frontend-http2-max-concurrent-stream"_sr, name, 36)) { return SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS; } - if (util::strieq_l("frontend-http3-max-concurrent-stream", name, 36)) { + if (util::strieq("frontend-http3-max-concurrent-stream"_sr, name, 36)) { return SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS; } break; @@ -2751,7 +2741,7 @@ int option_lookup_token(const char *name, size_t namelen) { case 38: switch (name[37]) { case 'd': - if (util::strieq_l("backend-http1-connections-per-fronten", name, 37)) { + if (util::strieq("backend-http1-connections-per-fronten"_sr, name, 37)) { return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND; } break; @@ -2760,7 +2750,7 @@ int option_lookup_token(const char *name, size_t namelen) { case 39: switch (name[38]) { case 'y': - if (util::strieq_l("tls-ticket-key-memcached-address-famil", name, 38)) { + if (util::strieq("tls-ticket-key-memcached-address-famil"_sr, name, 38)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY; } break; @@ -2769,10 +2759,12 @@ int option_lookup_token(const char *name, size_t namelen) { case 40: switch (name[39]) { case 'e': - if (util::strieq_l("backend-http2-decoder-dynamic-table-siz", name, 39)) { + if (util::strieq("backend-http2-decoder-dynamic-table-siz"_sr, name, + 39)) { return SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE; } - if (util::strieq_l("backend-http2-encoder-dynamic-table-siz", name, 39)) { + if (util::strieq("backend-http2-encoder-dynamic-table-siz"_sr, name, + 39)) { return SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE; } break; @@ -2781,24 +2773,24 @@ int option_lookup_token(const char *name, size_t namelen) { case 41: switch (name[40]) { case 'e': - if (util::strieq_l("frontend-http2-decoder-dynamic-table-siz", name, - 40)) { + if (util::strieq("frontend-http2-decoder-dynamic-table-siz"_sr, name, + 40)) { return SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE; } - if (util::strieq_l("frontend-http2-encoder-dynamic-table-siz", name, - 40)) { + if (util::strieq("frontend-http2-encoder-dynamic-table-siz"_sr, name, + 40)) { return SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE; } - if (util::strieq_l("frontend-http2-optimize-write-buffer-siz", name, - 40)) { + if (util::strieq("frontend-http2-optimize-write-buffer-siz"_sr, name, + 40)) { return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE; } - if (util::strieq_l("frontend-http3-max-connection-window-siz", name, - 40)) { + if (util::strieq("frontend-http3-max-connection-window-siz"_sr, name, + 40)) { return SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE; } - if (util::strieq_l("tls-ticket-key-memcached-private-key-fil", name, - 40)) { + if (util::strieq("tls-ticket-key-memcached-private-key-fil"_sr, name, + 40)) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE; } break; @@ -2807,8 +2799,8 @@ int option_lookup_token(const char *name, size_t namelen) { case 42: switch (name[41]) { case 'y': - if (util::strieq_l("tls-session-cache-memcached-address-famil", name, - 41)) { + if (util::strieq("tls-session-cache-memcached-address-famil"_sr, name, + 41)) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY; } break; @@ -2817,8 +2809,8 @@ int option_lookup_token(const char *name, size_t namelen) { case 44: switch (name[43]) { case 'e': - if (util::strieq_l("tls-session-cache-memcached-private-key-fil", name, - 43)) { + if (util::strieq("tls-session-cache-memcached-private-key-fil"_sr, name, + 43)) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE; } break; @@ -2831,7 +2823,7 @@ int option_lookup_token(const char *name, size_t namelen) { int parse_config(Config *config, const StringRef &opt, const StringRef &optarg, std::set<StringRef> &included_set, std::map<StringRef, size_t> &pattern_addr_indexer) { - auto optid = option_lookup_token(opt.c_str(), opt.size()); + auto optid = option_lookup_token(opt); return parse_config(config, optid, opt, optarg, included_set, pattern_addr_indexer); } @@ -3022,11 +3014,11 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; } case SHRPX_OPTID_DAEMON: - config->daemon = util::strieq_l("yes", optarg); + config->daemon = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_HTTP2_PROXY: - config->http2_proxy = util::strieq_l("yes", optarg); + config->http2_proxy = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_HTTP2_BRIDGE: @@ -3040,15 +3032,15 @@ int parse_config(Config *config, int optid, const StringRef &opt, "and backend=<addr>,<port>;;proto=h2;tls"; return -1; case SHRPX_OPTID_ADD_X_FORWARDED_FOR: - config->http.xff.add = util::strieq_l("yes", optarg); + config->http.xff.add = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR: - config->http.xff.strip_incoming = util::strieq_l("yes", optarg); + config->http.xff.strip_incoming = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_NO_VIA: - config->http.no_via = util::strieq_l("yes", optarg); + config->http.no_via = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: @@ -3081,7 +3073,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_ACCESSLOG_SYSLOG: - config->logging.access.syslog = util::strieq_l("yes", optarg); + config->logging.access.syslog = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_ACCESSLOG_FORMAT: @@ -3093,7 +3085,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_ERRORLOG_SYSLOG: - config->logging.error.syslog = util::strieq_l("yes", optarg); + config->logging.error.syslog = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FASTOPEN: @@ -3191,7 +3183,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_USER: { - auto pwd = getpwnam(optarg.c_str()); + auto pwd = getpwnam(optarg.data()); if (!pwd) { LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": " << xsi_strerror(errno, errbuf.data(), errbuf.size()); @@ -3240,7 +3232,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, if (!params.sct_dir.empty()) { // Make sure that dir_path is NULL terminated string. if (read_tls_sct_from_dir(sct_data, opt, - StringRef{params.sct_dir.str()}) != 0) { + StringRef{std::string{params.sct_dir}}) != 0) { return -1; } } @@ -3301,7 +3293,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, "backend=<addr>,<port>;;proto=h2;tls"; return -1; case SHRPX_OPTID_INSECURE: - config->tls.insecure = util::strieq_l("yes", optarg); + config->tls.insecure = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_CACERT: @@ -3329,10 +3321,10 @@ int parse_config(Config *config, int optid, const StringRef &opt, proxy = {}; // parse URI and get hostname, port and optionally userinfo. http_parser_url u{}; - int rv = http_parser_parse_url(optarg.c_str(), optarg.size(), 0, &u); + int rv = http_parser_parse_url(optarg.data(), optarg.size(), 0, &u); if (rv == 0) { if (u.field_set & UF_USERINFO) { - auto uf = util::get_uri_field(optarg.c_str(), u, UF_USERINFO); + auto uf = util::get_uri_field(optarg.data(), u, UF_USERINFO); // Surprisingly, u.field_set & UF_USERINFO is nonzero even if // userinfo component is empty string. if (!uf.empty()) { @@ -3341,7 +3333,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, } if (u.field_set & UF_HOST) { proxy.host = make_string_ref( - config->balloc, util::get_uri_field(optarg.c_str(), u, UF_HOST)); + config->balloc, util::get_uri_field(optarg.data(), u, UF_HOST)); } else { LOG(ERROR) << opt << ": no hostname specified"; return -1; @@ -3396,7 +3388,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; } case SHRPX_OPTID_VERIFY_CLIENT: - config->tls.client_verify.enabled = util::strieq_l("yes", optarg); + config->tls.client_verify.enabled = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_VERIFY_CLIENT_CACERT: @@ -3423,11 +3415,11 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING: - config->http2.no_cookie_crumbling = util::strieq_l("yes", optarg); + config->http2.no_cookie_crumbling = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FRONTEND_FRAME_DEBUG: - config->http2.upstream.debug.frame_debug = util::strieq_l("yes", optarg); + config->http2.upstream.debug.frame_debug = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_PADDING: @@ -3460,7 +3452,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS: return parse_uint(&config->conn.upstream.worker_connections, opt, optarg); case SHRPX_OPTID_NO_LOCATION_REWRITE: - config->http.no_location_rewrite = util::strieq_l("yes", optarg); + config->http.no_location_rewrite = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_NO_HOST_REWRITE: @@ -3544,7 +3536,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, } case SHRPX_OPTID_NO_SERVER_PUSH: - config->http2.no_server_push = util::strieq_l("yes", optarg); + config->http2.no_server_push = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER: @@ -3558,7 +3550,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_OCSP_UPDATE_INTERVAL: return parse_duration(&config->tls.ocsp.update_interval, opt, optarg); case SHRPX_OPTID_NO_OCSP: - config->tls.ocsp.disabled = util::strieq_l("yes", optarg); + config->tls.ocsp.disabled = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_HEADER_FIELD_BUFFER: @@ -3586,7 +3578,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, included_set.insert(optarg); auto rv = - load_config(config, optarg.c_str(), included_set, pattern_addr_indexer); + load_config(config, optarg.data(), included_set, pattern_addr_indexer); included_set.erase(optarg); if (rv != 0) { @@ -3596,9 +3588,9 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; } case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER: - if (util::strieq_l("aes-128-cbc", optarg)) { + if (util::strieq("aes-128-cbc"_sr, optarg)) { config->tls.ticket.cipher = EVP_aes_128_cbc(); - } else if (util::strieq_l("aes-256-cbc", optarg)) { + } else if (util::strieq("aes-256-cbc"_sr, optarg)) { config->tls.ticket.cipher = EVP_aes_256_cbc(); } else { LOG(ERROR) << opt @@ -3609,7 +3601,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_HOST_REWRITE: - config->http.no_host_rewrite = !util::strieq_l("yes", optarg); + config->http.no_host_rewrite = !util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: @@ -3690,26 +3682,27 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL: LOG(WARN) << opt << ": deprecated. Use proxyproto keyword in " << SHRPX_OPT_FRONTEND << " instead."; - config->conn.upstream.accept_proxy_protocol = util::strieq_l("yes", optarg); + config->conn.upstream.accept_proxy_protocol = + util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_ADD_FORWARDED: { auto &fwdconf = config->http.forwarded; fwdconf.params = FORWARDED_NONE; for (const auto ¶m : util::split_str(optarg, ',')) { - if (util::strieq_l("by", param)) { + if (util::strieq("by"_sr, param)) { fwdconf.params |= FORWARDED_BY; continue; } - if (util::strieq_l("for", param)) { + if (util::strieq("for"_sr, param)) { fwdconf.params |= FORWARDED_FOR; continue; } - if (util::strieq_l("host", param)) { + if (util::strieq("host"_sr, param)) { fwdconf.params |= FORWARDED_HOST; continue; } - if (util::strieq_l("proto", param)) { + if (util::strieq("proto"_sr, param)) { fwdconf.params |= FORWARDED_PROTO; continue; } @@ -3722,7 +3715,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; } case SHRPX_OPTID_STRIP_INCOMING_FORWARDED: - config->http.forwarded.strip_incoming = util::strieq_l("yes", optarg); + config->http.forwarded.strip_incoming = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FORWARDED_BY: @@ -3744,7 +3737,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, if (optarg[0] == '_') { fwdconf.by_obfuscated = make_string_ref(config->balloc, optarg); } else { - fwdconf.by_obfuscated = StringRef::from_lit(""); + fwdconf.by_obfuscated = ""_sr; } break; case SHRPX_OPTID_FORWARDED_FOR: @@ -3759,7 +3752,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, << SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST << " instead."; // fall through case SHRPX_OPTID_NO_HTTP2_CIPHER_BLOCK_LIST: - config->tls.no_http2_cipher_block_list = util::strieq_l("yes", optarg); + config->tls.no_http2_cipher_block_list = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_BACKEND_HTTP1_TLS: case SHRPX_OPTID_BACKEND_TLS: @@ -3835,16 +3828,17 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_NO_SERVER_REWRITE: - config->http.no_server_rewrite = util::strieq_l("yes", optarg); + config->http.no_server_rewrite = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE: config->http2.upstream.optimize_write_buffer_size = - util::strieq_l("yes", optarg); + util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE: - config->http2.upstream.optimize_window_size = util::strieq_l("yes", optarg); + config->http2.upstream.optimize_window_size = + util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE: @@ -3963,7 +3957,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, // fall through case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST: config->tls.client.no_http2_cipher_block_list = - util::strieq_l("yes", optarg); + util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_CLIENT_CIPHERS: @@ -3975,7 +3969,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_ACCESSLOG_WRITE_EARLY: - config->logging.access.write_early = util::strieq_l("yes", optarg); + config->logging.access.write_early = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_TLS_MIN_PROTO_VERSION: @@ -3984,7 +3978,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return parse_tls_proto_version(config->tls.max_proto_version, opt, optarg); case SHRPX_OPTID_REDIRECT_HTTPS_PORT: { auto n = util::parse_uint(optarg); - if (n == -1 || n < 0 || n > 65535) { + if (!n || n < 0 || n > 65535) { LOG(ERROR) << opt << ": bad value. Specify an integer in the range [0, " "65535], inclusive"; @@ -3996,46 +3990,46 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_FRONTEND_MAX_REQUESTS: return parse_uint(&config->http.max_requests, opt, optarg); case SHRPX_OPTID_SINGLE_THREAD: - config->single_thread = util::strieq_l("yes", optarg); + config->single_thread = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_SINGLE_PROCESS: - config->single_process = util::strieq_l("yes", optarg); + config->single_process = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO: - config->http.xfp.add = !util::strieq_l("yes", optarg); + config->http.xfp.add = !util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO: - config->http.xfp.strip_incoming = !util::strieq_l("yes", optarg); + config->http.xfp.strip_incoming = !util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_OCSP_STARTUP: - config->tls.ocsp.startup = util::strieq_l("yes", optarg); + config->tls.ocsp.startup = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_NO_VERIFY_OCSP: - config->tls.ocsp.no_verify = util::strieq_l("yes", optarg); + config->tls.ocsp.no_verify = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED: - config->tls.client_verify.tolerate_expired = util::strieq_l("yes", optarg); + config->tls.client_verify.tolerate_expired = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_IGNORE_PER_PATTERN_MRUBY_ERROR: - config->ignore_per_pattern_mruby_error = util::strieq_l("yes", optarg); + config->ignore_per_pattern_mruby_error = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_TLS_NO_POSTPONE_EARLY_DATA: - config->tls.no_postpone_early_data = util::strieq_l("yes", optarg); + config->tls.no_postpone_early_data = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_TLS_MAX_EARLY_DATA: { return parse_uint_with_unit(&config->tls.max_early_data, opt, optarg); } case SHRPX_OPTID_NO_STRIP_INCOMING_EARLY_DATA: - config->http.early_data.strip_incoming = !util::strieq_l("yes", optarg); + config->http.early_data.strip_incoming = !util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_QUIC_BPF_PROGRAM_FILE: @@ -4046,7 +4040,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_NO_QUIC_BPF: #ifdef ENABLE_HTTP3 - config->quic.bpf.disabled = util::strieq_l("yes", optarg); + config->quic.bpf.disabled = util::strieq("yes"_sr, optarg); #endif // ENABLE_HTTP3 return 0; @@ -4079,7 +4073,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, #endif // !ENABLE_HTTP3 case SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG: #ifdef ENABLE_HTTP3 - config->quic.upstream.debug.log = util::strieq_l("yes", optarg); + config->quic.upstream.debug.log = util::strieq("yes"_sr, optarg); #endif // ENABLE_HTTP3 return 0; @@ -4128,7 +4122,7 @@ int parse_config(Config *config, int optid, const StringRef &opt, #endif // !ENABLE_HTTP3 case SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA: #ifdef ENABLE_HTTP3 - config->quic.upstream.early_data = util::strieq_l("yes", optarg); + config->quic.upstream.early_data = util::strieq("yes"_sr, optarg); #endif // ENABLE_HTTP3 return 0; @@ -4140,15 +4134,15 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; case SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN: #ifdef ENABLE_HTTP3 - config->quic.upstream.require_token = util::strieq_l("yes", optarg); + config->quic.upstream.require_token = util::strieq("yes"_sr, optarg); #endif // ENABLE_HTTP3 return 0; case SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER: #ifdef ENABLE_HTTP3 - if (util::strieq_l("cubic", optarg)) { + if (util::strieq("cubic"_sr, optarg)) { config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_CUBIC; - } else if (util::strieq_l("bbr", optarg)) { + } else if (util::strieq("bbr"_sr, optarg)) { config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_BBR; } else { LOG(ERROR) << opt << ": must be either cubic or bbr"; @@ -4205,10 +4199,10 @@ int parse_config(Config *config, int optid, const StringRef &opt, return 0; } case SHRPX_OPTID_REQUIRE_HTTP_SCHEME: - config->http.require_http_scheme = util::strieq_l("yes", optarg); + config->http.require_http_scheme = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_TLS_KTLS: - config->tls.ktls = util::strieq_l("yes", optarg); + config->tls.ktls = util::strieq("yes"_sr, optarg); return 0; case SHRPX_OPTID_NPN_LIST: LOG(WARN) << opt << ": deprecated. Use alpn-list instead."; @@ -4268,134 +4262,134 @@ int load_config(Config *config, const char *filename, StringRef str_syslog_facility(int facility) { switch (facility) { case (LOG_AUTH): - return StringRef::from_lit("auth"); + return "auth"_sr; #ifdef LOG_AUTHPRIV case (LOG_AUTHPRIV): - return StringRef::from_lit("authpriv"); + return "authpriv"_sr; #endif // LOG_AUTHPRIV case (LOG_CRON): - return StringRef::from_lit("cron"); + return "cron"_sr; case (LOG_DAEMON): - return StringRef::from_lit("daemon"); + return "daemon"_sr; #ifdef LOG_FTP case (LOG_FTP): - return StringRef::from_lit("ftp"); + return "ftp"_sr; #endif // LOG_FTP case (LOG_KERN): - return StringRef::from_lit("kern"); + return "kern"_sr; case (LOG_LOCAL0): - return StringRef::from_lit("local0"); + return "local0"_sr; case (LOG_LOCAL1): - return StringRef::from_lit("local1"); + return "local1"_sr; case (LOG_LOCAL2): - return StringRef::from_lit("local2"); + return "local2"_sr; case (LOG_LOCAL3): - return StringRef::from_lit("local3"); + return "local3"_sr; case (LOG_LOCAL4): - return StringRef::from_lit("local4"); + return "local4"_sr; case (LOG_LOCAL5): - return StringRef::from_lit("local5"); + return "local5"_sr; case (LOG_LOCAL6): - return StringRef::from_lit("local6"); + return "local6"_sr; case (LOG_LOCAL7): - return StringRef::from_lit("local7"); + return "local7"_sr; case (LOG_LPR): - return StringRef::from_lit("lpr"); + return "lpr"_sr; case (LOG_MAIL): - return StringRef::from_lit("mail"); + return "mail"_sr; case (LOG_SYSLOG): - return StringRef::from_lit("syslog"); + return "syslog"_sr; case (LOG_USER): - return StringRef::from_lit("user"); + return "user"_sr; case (LOG_UUCP): - return StringRef::from_lit("uucp"); + return "uucp"_sr; default: - return StringRef::from_lit("(unknown)"); + return "(unknown)"_sr; } } int int_syslog_facility(const StringRef &strfacility) { - if (util::strieq_l("auth", strfacility)) { + if (util::strieq("auth"_sr, strfacility)) { return LOG_AUTH; } #ifdef LOG_AUTHPRIV - if (util::strieq_l("authpriv", strfacility)) { + if (util::strieq("authpriv"_sr, strfacility)) { return LOG_AUTHPRIV; } #endif // LOG_AUTHPRIV - if (util::strieq_l("cron", strfacility)) { + if (util::strieq("cron"_sr, strfacility)) { return LOG_CRON; } - if (util::strieq_l("daemon", strfacility)) { + if (util::strieq("daemon"_sr, strfacility)) { return LOG_DAEMON; } #ifdef LOG_FTP - if (util::strieq_l("ftp", strfacility)) { + if (util::strieq("ftp"_sr, strfacility)) { return LOG_FTP; } #endif // LOG_FTP - if (util::strieq_l("kern", strfacility)) { + if (util::strieq("kern"_sr, strfacility)) { return LOG_KERN; } - if (util::strieq_l("local0", strfacility)) { + if (util::strieq("local0"_sr, strfacility)) { return LOG_LOCAL0; } - if (util::strieq_l("local1", strfacility)) { + if (util::strieq("local1"_sr, strfacility)) { return LOG_LOCAL1; } - if (util::strieq_l("local2", strfacility)) { + if (util::strieq("local2"_sr, strfacility)) { return LOG_LOCAL2; } - if (util::strieq_l("local3", strfacility)) { + if (util::strieq("local3"_sr, strfacility)) { return LOG_LOCAL3; } - if (util::strieq_l("local4", strfacility)) { + if (util::strieq("local4"_sr, strfacility)) { return LOG_LOCAL4; } - if (util::strieq_l("local5", strfacility)) { + if (util::strieq("local5"_sr, strfacility)) { return LOG_LOCAL5; } - if (util::strieq_l("local6", strfacility)) { + if (util::strieq("local6"_sr, strfacility)) { return LOG_LOCAL6; } - if (util::strieq_l("local7", strfacility)) { + if (util::strieq("local7"_sr, strfacility)) { return LOG_LOCAL7; } - if (util::strieq_l("lpr", strfacility)) { + if (util::strieq("lpr"_sr, strfacility)) { return LOG_LPR; } - if (util::strieq_l("mail", strfacility)) { + if (util::strieq("mail"_sr, strfacility)) { return LOG_MAIL; } - if (util::strieq_l("news", strfacility)) { + if (util::strieq("news"_sr, strfacility)) { return LOG_NEWS; } - if (util::strieq_l("syslog", strfacility)) { + if (util::strieq("syslog"_sr, strfacility)) { return LOG_SYSLOG; } - if (util::strieq_l("user", strfacility)) { + if (util::strieq("user"_sr, strfacility)) { return LOG_USER; } - if (util::strieq_l("uucp", strfacility)) { + if (util::strieq("uucp"_sr, strfacility)) { return LOG_UUCP; } @@ -4405,15 +4399,15 @@ int int_syslog_facility(const StringRef &strfacility) { StringRef strproto(Proto proto) { switch (proto) { case Proto::NONE: - return StringRef::from_lit("none"); + return "none"_sr; case Proto::HTTP1: - return StringRef::from_lit("http/1.1"); + return "http/1.1"_sr; case Proto::HTTP2: - return StringRef::from_lit("h2"); + return "h2"_sr; case Proto::HTTP3: - return StringRef::from_lit("h3"); + return "h3"_sr; case Proto::MEMCACHED: - return StringRef::from_lit("memcached"); + return "memcached"_sr; } // gcc needs this. @@ -4436,7 +4430,7 @@ int compute_affinity_hash(std::vector<AffinityHash> &res, size_t idx, std::array<uint8_t, 32> buf; for (auto i = 0; i < 20; ++i) { - auto t = s.str(); + auto t = std::string{s}; t += i; rv = util::sha256(buf.data(), StringRef{t}); @@ -4473,13 +4467,13 @@ int configure_downstream_group(Config *config, bool http2_proxy, if (addr_groups.empty()) { DownstreamAddrConfig addr{}; - addr.host = StringRef::from_lit(DEFAULT_DOWNSTREAM_HOST); + addr.host = DEFAULT_DOWNSTREAM_HOST; addr.port = DEFAULT_DOWNSTREAM_PORT; addr.proto = Proto::HTTP1; addr.weight = 1; addr.group_weight = 1; - DownstreamAddrGroupConfig g(StringRef::from_lit("/")); + DownstreamAddrGroupConfig g("/"_sr); g.addrs.push_back(std::move(addr)); router.add_route(g.pattern, addr_groups.size()); addr_groups.push_back(std::move(g)); @@ -4503,14 +4497,14 @@ int configure_downstream_group(Config *config, bool http2_proxy, ssize_t catch_all_group = -1; for (size_t i = 0; i < addr_groups.size(); ++i) { auto &g = addr_groups[i]; - if (g.pattern == StringRef::from_lit("/")) { + if (g.pattern == "/"_sr) { catch_all_group = i; } if (LOG_ENABLED(INFO)) { LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern << "'"; for (auto &addr : g.addrs) { - LOG(INFO) << "group " << i << " -> " << addr.host.c_str() + LOG(INFO) << "group " << i << " -> " << addr.host.data() << (addr.host_unix ? "" : ":" + util::utos(addr.port)) << ", proto=" << strproto(addr.proto) << (addr.tls ? ", tls" : ""); @@ -4575,9 +4569,9 @@ int configure_downstream_group(Config *config, bool http2_proxy, // for AF_UNIX socket, we use "localhost" as host for backend // hostport. This is used as Host header field to backend and // not going to be passed to any syscalls. - addr.hostport = StringRef::from_lit("localhost"); + addr.hostport = "localhost"_sr; - auto path = addr.host.c_str(); + auto path = addr.host.data(); auto pathlen = addr.host.size(); if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) { @@ -4606,7 +4600,7 @@ int configure_downstream_group(Config *config, bool http2_proxy, util::make_hostport(std::begin(hostport_buf), addr.host, addr.port); if (!addr.dns) { - if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port, + if (resolve_hostname(&addr.addr, addr.host.data(), addr.port, downstreamconf.family, resolve_flags) == -1) { LOG(FATAL) << "Resolving backend address failed: " << hostport; return -1; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index f264b6a..b0225d1 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -51,6 +51,7 @@ #include <nghttp2/nghttp2.h> +#include "shrpx_log.h" #include "shrpx_router.h" #if ENABLE_HTTP3 # include "shrpx_quic.h" @@ -74,348 +75,289 @@ class CertLookupTree; } // namespace tls -constexpr auto SHRPX_OPT_PRIVATE_KEY_FILE = - StringRef::from_lit("private-key-file"); -constexpr auto SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE = - StringRef::from_lit("private-key-passwd-file"); -constexpr auto SHRPX_OPT_CERTIFICATE_FILE = - StringRef::from_lit("certificate-file"); -constexpr auto SHRPX_OPT_DH_PARAM_FILE = StringRef::from_lit("dh-param-file"); -constexpr auto SHRPX_OPT_SUBCERT = StringRef::from_lit("subcert"); -constexpr auto SHRPX_OPT_BACKEND = StringRef::from_lit("backend"); -constexpr auto SHRPX_OPT_FRONTEND = StringRef::from_lit("frontend"); -constexpr auto SHRPX_OPT_WORKERS = StringRef::from_lit("workers"); +constexpr auto SHRPX_OPT_PRIVATE_KEY_FILE = "private-key-file"_sr; +constexpr auto SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE = "private-key-passwd-file"_sr; +constexpr auto SHRPX_OPT_CERTIFICATE_FILE = "certificate-file"_sr; +constexpr auto SHRPX_OPT_DH_PARAM_FILE = "dh-param-file"_sr; +constexpr auto SHRPX_OPT_SUBCERT = "subcert"_sr; +constexpr auto SHRPX_OPT_BACKEND = "backend"_sr; +constexpr auto SHRPX_OPT_FRONTEND = "frontend"_sr; +constexpr auto SHRPX_OPT_WORKERS = "workers"_sr; constexpr auto SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("http2-max-concurrent-streams"); -constexpr auto SHRPX_OPT_LOG_LEVEL = StringRef::from_lit("log-level"); -constexpr auto SHRPX_OPT_DAEMON = StringRef::from_lit("daemon"); -constexpr auto SHRPX_OPT_HTTP2_PROXY = StringRef::from_lit("http2-proxy"); -constexpr auto SHRPX_OPT_HTTP2_BRIDGE = StringRef::from_lit("http2-bridge"); -constexpr auto SHRPX_OPT_CLIENT_PROXY = StringRef::from_lit("client-proxy"); -constexpr auto SHRPX_OPT_ADD_X_FORWARDED_FOR = - StringRef::from_lit("add-x-forwarded-for"); + "http2-max-concurrent-streams"_sr; +constexpr auto SHRPX_OPT_LOG_LEVEL = "log-level"_sr; +constexpr auto SHRPX_OPT_DAEMON = "daemon"_sr; +constexpr auto SHRPX_OPT_HTTP2_PROXY = "http2-proxy"_sr; +constexpr auto SHRPX_OPT_HTTP2_BRIDGE = "http2-bridge"_sr; +constexpr auto SHRPX_OPT_CLIENT_PROXY = "client-proxy"_sr; +constexpr auto SHRPX_OPT_ADD_X_FORWARDED_FOR = "add-x-forwarded-for"_sr; constexpr auto SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR = - StringRef::from_lit("strip-incoming-x-forwarded-for"); -constexpr auto SHRPX_OPT_NO_VIA = StringRef::from_lit("no-via"); + "strip-incoming-x-forwarded-for"_sr; +constexpr auto SHRPX_OPT_NO_VIA = "no-via"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT = - StringRef::from_lit("frontend-http2-read-timeout"); -constexpr auto SHRPX_OPT_FRONTEND_READ_TIMEOUT = - StringRef::from_lit("frontend-read-timeout"); -constexpr auto SHRPX_OPT_FRONTEND_WRITE_TIMEOUT = - StringRef::from_lit("frontend-write-timeout"); -constexpr auto SHRPX_OPT_BACKEND_READ_TIMEOUT = - StringRef::from_lit("backend-read-timeout"); -constexpr auto SHRPX_OPT_BACKEND_WRITE_TIMEOUT = - StringRef::from_lit("backend-write-timeout"); -constexpr auto SHRPX_OPT_STREAM_READ_TIMEOUT = - StringRef::from_lit("stream-read-timeout"); -constexpr auto SHRPX_OPT_STREAM_WRITE_TIMEOUT = - StringRef::from_lit("stream-write-timeout"); -constexpr auto SHRPX_OPT_ACCESSLOG_FILE = StringRef::from_lit("accesslog-file"); -constexpr auto SHRPX_OPT_ACCESSLOG_SYSLOG = - StringRef::from_lit("accesslog-syslog"); -constexpr auto SHRPX_OPT_ACCESSLOG_FORMAT = - StringRef::from_lit("accesslog-format"); -constexpr auto SHRPX_OPT_ERRORLOG_FILE = StringRef::from_lit("errorlog-file"); -constexpr auto SHRPX_OPT_ERRORLOG_SYSLOG = - StringRef::from_lit("errorlog-syslog"); + "frontend-http2-read-timeout"_sr; +constexpr auto SHRPX_OPT_FRONTEND_READ_TIMEOUT = "frontend-read-timeout"_sr; +constexpr auto SHRPX_OPT_FRONTEND_WRITE_TIMEOUT = "frontend-write-timeout"_sr; +constexpr auto SHRPX_OPT_BACKEND_READ_TIMEOUT = "backend-read-timeout"_sr; +constexpr auto SHRPX_OPT_BACKEND_WRITE_TIMEOUT = "backend-write-timeout"_sr; +constexpr auto SHRPX_OPT_STREAM_READ_TIMEOUT = "stream-read-timeout"_sr; +constexpr auto SHRPX_OPT_STREAM_WRITE_TIMEOUT = "stream-write-timeout"_sr; +constexpr auto SHRPX_OPT_ACCESSLOG_FILE = "accesslog-file"_sr; +constexpr auto SHRPX_OPT_ACCESSLOG_SYSLOG = "accesslog-syslog"_sr; +constexpr auto SHRPX_OPT_ACCESSLOG_FORMAT = "accesslog-format"_sr; +constexpr auto SHRPX_OPT_ERRORLOG_FILE = "errorlog-file"_sr; +constexpr auto SHRPX_OPT_ERRORLOG_SYSLOG = "errorlog-syslog"_sr; constexpr auto SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT = - StringRef::from_lit("backend-keep-alive-timeout"); + "backend-keep-alive-timeout"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS = - StringRef::from_lit("frontend-http2-window-bits"); + "frontend-http2-window-bits"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS = - StringRef::from_lit("backend-http2-window-bits"); + "backend-http2-window-bits"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS = - StringRef::from_lit("frontend-http2-connection-window-bits"); + "frontend-http2-connection-window-bits"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS = - StringRef::from_lit("backend-http2-connection-window-bits"); -constexpr auto SHRPX_OPT_FRONTEND_NO_TLS = - StringRef::from_lit("frontend-no-tls"); -constexpr auto SHRPX_OPT_BACKEND_NO_TLS = StringRef::from_lit("backend-no-tls"); -constexpr auto SHRPX_OPT_BACKEND_TLS_SNI_FIELD = - StringRef::from_lit("backend-tls-sni-field"); -constexpr auto SHRPX_OPT_PID_FILE = StringRef::from_lit("pid-file"); -constexpr auto SHRPX_OPT_USER = StringRef::from_lit("user"); -constexpr auto SHRPX_OPT_SYSLOG_FACILITY = - StringRef::from_lit("syslog-facility"); -constexpr auto SHRPX_OPT_BACKLOG = StringRef::from_lit("backlog"); -constexpr auto SHRPX_OPT_CIPHERS = StringRef::from_lit("ciphers"); -constexpr auto SHRPX_OPT_CLIENT = StringRef::from_lit("client"); -constexpr auto SHRPX_OPT_INSECURE = StringRef::from_lit("insecure"); -constexpr auto SHRPX_OPT_CACERT = StringRef::from_lit("cacert"); -constexpr auto SHRPX_OPT_BACKEND_IPV4 = StringRef::from_lit("backend-ipv4"); -constexpr auto SHRPX_OPT_BACKEND_IPV6 = StringRef::from_lit("backend-ipv6"); -constexpr auto SHRPX_OPT_BACKEND_HTTP_PROXY_URI = - StringRef::from_lit("backend-http-proxy-uri"); -constexpr auto SHRPX_OPT_READ_RATE = StringRef::from_lit("read-rate"); -constexpr auto SHRPX_OPT_READ_BURST = StringRef::from_lit("read-burst"); -constexpr auto SHRPX_OPT_WRITE_RATE = StringRef::from_lit("write-rate"); -constexpr auto SHRPX_OPT_WRITE_BURST = StringRef::from_lit("write-burst"); -constexpr auto SHRPX_OPT_WORKER_READ_RATE = - StringRef::from_lit("worker-read-rate"); -constexpr auto SHRPX_OPT_WORKER_READ_BURST = - StringRef::from_lit("worker-read-burst"); -constexpr auto SHRPX_OPT_WORKER_WRITE_RATE = - StringRef::from_lit("worker-write-rate"); -constexpr auto SHRPX_OPT_WORKER_WRITE_BURST = - StringRef::from_lit("worker-write-burst"); -constexpr auto SHRPX_OPT_NPN_LIST = StringRef::from_lit("npn-list"); -constexpr auto SHRPX_OPT_TLS_PROTO_LIST = StringRef::from_lit("tls-proto-list"); -constexpr auto SHRPX_OPT_VERIFY_CLIENT = StringRef::from_lit("verify-client"); -constexpr auto SHRPX_OPT_VERIFY_CLIENT_CACERT = - StringRef::from_lit("verify-client-cacert"); -constexpr auto SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE = - StringRef::from_lit("client-private-key-file"); -constexpr auto SHRPX_OPT_CLIENT_CERT_FILE = - StringRef::from_lit("client-cert-file"); + "backend-http2-connection-window-bits"_sr; +constexpr auto SHRPX_OPT_FRONTEND_NO_TLS = "frontend-no-tls"_sr; +constexpr auto SHRPX_OPT_BACKEND_NO_TLS = "backend-no-tls"_sr; +constexpr auto SHRPX_OPT_BACKEND_TLS_SNI_FIELD = "backend-tls-sni-field"_sr; +constexpr auto SHRPX_OPT_PID_FILE = "pid-file"_sr; +constexpr auto SHRPX_OPT_USER = "user"_sr; +constexpr auto SHRPX_OPT_SYSLOG_FACILITY = "syslog-facility"_sr; +constexpr auto SHRPX_OPT_BACKLOG = "backlog"_sr; +constexpr auto SHRPX_OPT_CIPHERS = "ciphers"_sr; +constexpr auto SHRPX_OPT_CLIENT = "client"_sr; +constexpr auto SHRPX_OPT_INSECURE = "insecure"_sr; +constexpr auto SHRPX_OPT_CACERT = "cacert"_sr; +constexpr auto SHRPX_OPT_BACKEND_IPV4 = "backend-ipv4"_sr; +constexpr auto SHRPX_OPT_BACKEND_IPV6 = "backend-ipv6"_sr; +constexpr auto SHRPX_OPT_BACKEND_HTTP_PROXY_URI = "backend-http-proxy-uri"_sr; +constexpr auto SHRPX_OPT_READ_RATE = "read-rate"_sr; +constexpr auto SHRPX_OPT_READ_BURST = "read-burst"_sr; +constexpr auto SHRPX_OPT_WRITE_RATE = "write-rate"_sr; +constexpr auto SHRPX_OPT_WRITE_BURST = "write-burst"_sr; +constexpr auto SHRPX_OPT_WORKER_READ_RATE = "worker-read-rate"_sr; +constexpr auto SHRPX_OPT_WORKER_READ_BURST = "worker-read-burst"_sr; +constexpr auto SHRPX_OPT_WORKER_WRITE_RATE = "worker-write-rate"_sr; +constexpr auto SHRPX_OPT_WORKER_WRITE_BURST = "worker-write-burst"_sr; +constexpr auto SHRPX_OPT_NPN_LIST = "npn-list"_sr; +constexpr auto SHRPX_OPT_TLS_PROTO_LIST = "tls-proto-list"_sr; +constexpr auto SHRPX_OPT_VERIFY_CLIENT = "verify-client"_sr; +constexpr auto SHRPX_OPT_VERIFY_CLIENT_CACERT = "verify-client-cacert"_sr; +constexpr auto SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE = "client-private-key-file"_sr; +constexpr auto SHRPX_OPT_CLIENT_CERT_FILE = "client-cert-file"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER = - StringRef::from_lit("frontend-http2-dump-request-header"); + "frontend-http2-dump-request-header"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER = - StringRef::from_lit("frontend-http2-dump-response-header"); + "frontend-http2-dump-response-header"_sr; constexpr auto SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING = - StringRef::from_lit("http2-no-cookie-crumbling"); -constexpr auto SHRPX_OPT_FRONTEND_FRAME_DEBUG = - StringRef::from_lit("frontend-frame-debug"); -constexpr auto SHRPX_OPT_PADDING = StringRef::from_lit("padding"); -constexpr auto SHRPX_OPT_ALTSVC = StringRef::from_lit("altsvc"); -constexpr auto SHRPX_OPT_ADD_REQUEST_HEADER = - StringRef::from_lit("add-request-header"); -constexpr auto SHRPX_OPT_ADD_RESPONSE_HEADER = - StringRef::from_lit("add-response-header"); + "http2-no-cookie-crumbling"_sr; +constexpr auto SHRPX_OPT_FRONTEND_FRAME_DEBUG = "frontend-frame-debug"_sr; +constexpr auto SHRPX_OPT_PADDING = "padding"_sr; +constexpr auto SHRPX_OPT_ALTSVC = "altsvc"_sr; +constexpr auto SHRPX_OPT_ADD_REQUEST_HEADER = "add-request-header"_sr; +constexpr auto SHRPX_OPT_ADD_RESPONSE_HEADER = "add-response-header"_sr; constexpr auto SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS = - StringRef::from_lit("worker-frontend-connections"); -constexpr auto SHRPX_OPT_NO_LOCATION_REWRITE = - StringRef::from_lit("no-location-rewrite"); -constexpr auto SHRPX_OPT_NO_HOST_REWRITE = - StringRef::from_lit("no-host-rewrite"); + "worker-frontend-connections"_sr; +constexpr auto SHRPX_OPT_NO_LOCATION_REWRITE = "no-location-rewrite"_sr; +constexpr auto SHRPX_OPT_NO_HOST_REWRITE = "no-host-rewrite"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST = - StringRef::from_lit("backend-http1-connections-per-host"); + "backend-http1-connections-per-host"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND = - StringRef::from_lit("backend-http1-connections-per-frontend"); + "backend-http1-connections-per-frontend"_sr; constexpr auto SHRPX_OPT_LISTENER_DISABLE_TIMEOUT = - StringRef::from_lit("listener-disable-timeout"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_FILE = - StringRef::from_lit("tls-ticket-key-file"); -constexpr auto SHRPX_OPT_RLIMIT_NOFILE = StringRef::from_lit("rlimit-nofile"); -constexpr auto SHRPX_OPT_BACKEND_REQUEST_BUFFER = - StringRef::from_lit("backend-request-buffer"); -constexpr auto SHRPX_OPT_BACKEND_RESPONSE_BUFFER = - StringRef::from_lit("backend-response-buffer"); -constexpr auto SHRPX_OPT_NO_SERVER_PUSH = StringRef::from_lit("no-server-push"); + "listener-disable-timeout"_sr; +constexpr auto SHRPX_OPT_TLS_TICKET_KEY_FILE = "tls-ticket-key-file"_sr; +constexpr auto SHRPX_OPT_RLIMIT_NOFILE = "rlimit-nofile"_sr; +constexpr auto SHRPX_OPT_BACKEND_REQUEST_BUFFER = "backend-request-buffer"_sr; +constexpr auto SHRPX_OPT_BACKEND_RESPONSE_BUFFER = "backend-response-buffer"_sr; +constexpr auto SHRPX_OPT_NO_SERVER_PUSH = "no-server-push"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER = - StringRef::from_lit("backend-http2-connections-per-worker"); + "backend-http2-connections-per-worker"_sr; constexpr auto SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE = - StringRef::from_lit("fetch-ocsp-response-file"); -constexpr auto SHRPX_OPT_OCSP_UPDATE_INTERVAL = - StringRef::from_lit("ocsp-update-interval"); -constexpr auto SHRPX_OPT_NO_OCSP = StringRef::from_lit("no-ocsp"); -constexpr auto SHRPX_OPT_HEADER_FIELD_BUFFER = - StringRef::from_lit("header-field-buffer"); -constexpr auto SHRPX_OPT_MAX_HEADER_FIELDS = - StringRef::from_lit("max-header-fields"); -constexpr auto SHRPX_OPT_INCLUDE = StringRef::from_lit("include"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_CIPHER = - StringRef::from_lit("tls-ticket-key-cipher"); -constexpr auto SHRPX_OPT_HOST_REWRITE = StringRef::from_lit("host-rewrite"); + "fetch-ocsp-response-file"_sr; +constexpr auto SHRPX_OPT_OCSP_UPDATE_INTERVAL = "ocsp-update-interval"_sr; +constexpr auto SHRPX_OPT_NO_OCSP = "no-ocsp"_sr; +constexpr auto SHRPX_OPT_HEADER_FIELD_BUFFER = "header-field-buffer"_sr; +constexpr auto SHRPX_OPT_MAX_HEADER_FIELDS = "max-header-fields"_sr; +constexpr auto SHRPX_OPT_INCLUDE = "include"_sr; +constexpr auto SHRPX_OPT_TLS_TICKET_KEY_CIPHER = "tls-ticket-key-cipher"_sr; +constexpr auto SHRPX_OPT_HOST_REWRITE = "host-rewrite"_sr; constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED = - StringRef::from_lit("tls-session-cache-memcached"); + "tls-session-cache-memcached"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED = - StringRef::from_lit("tls-ticket-key-memcached"); + "tls-ticket-key-memcached"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL = - StringRef::from_lit("tls-ticket-key-memcached-interval"); + "tls-ticket-key-memcached-interval"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY = - StringRef::from_lit("tls-ticket-key-memcached-max-retry"); + "tls-ticket-key-memcached-max-retry"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL = - StringRef::from_lit("tls-ticket-key-memcached-max-fail"); -constexpr auto SHRPX_OPT_MRUBY_FILE = StringRef::from_lit("mruby-file"); -constexpr auto SHRPX_OPT_ACCEPT_PROXY_PROTOCOL = - StringRef::from_lit("accept-proxy-protocol"); -constexpr auto SHRPX_OPT_FASTOPEN = StringRef::from_lit("fastopen"); + "tls-ticket-key-memcached-max-fail"_sr; +constexpr auto SHRPX_OPT_MRUBY_FILE = "mruby-file"_sr; +constexpr auto SHRPX_OPT_ACCEPT_PROXY_PROTOCOL = "accept-proxy-protocol"_sr; +constexpr auto SHRPX_OPT_FASTOPEN = "fastopen"_sr; constexpr auto SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD = - StringRef::from_lit("tls-dyn-rec-warmup-threshold"); + "tls-dyn-rec-warmup-threshold"_sr; constexpr auto SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT = - StringRef::from_lit("tls-dyn-rec-idle-timeout"); -constexpr auto SHRPX_OPT_ADD_FORWARDED = StringRef::from_lit("add-forwarded"); + "tls-dyn-rec-idle-timeout"_sr; +constexpr auto SHRPX_OPT_ADD_FORWARDED = "add-forwarded"_sr; constexpr auto SHRPX_OPT_STRIP_INCOMING_FORWARDED = - StringRef::from_lit("strip-incoming-forwarded"); -constexpr auto SHRPX_OPT_FORWARDED_BY = StringRef::from_lit("forwarded-by"); -constexpr auto SHRPX_OPT_FORWARDED_FOR = StringRef::from_lit("forwarded-for"); + "strip-incoming-forwarded"_sr; +constexpr auto SHRPX_OPT_FORWARDED_BY = "forwarded-by"_sr; +constexpr auto SHRPX_OPT_FORWARDED_FOR = "forwarded-for"_sr; constexpr auto SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER = - StringRef::from_lit("request-header-field-buffer"); + "request-header-field-buffer"_sr; constexpr auto SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS = - StringRef::from_lit("max-request-header-fields"); + "max-request-header-fields"_sr; constexpr auto SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER = - StringRef::from_lit("response-header-field-buffer"); + "response-header-field-buffer"_sr; constexpr auto SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS = - StringRef::from_lit("max-response-header-fields"); + "max-response-header-fields"_sr; constexpr auto SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST = - StringRef::from_lit("no-http2-cipher-block-list"); + "no-http2-cipher-block-list"_sr; constexpr auto SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST = - StringRef::from_lit("no-http2-cipher-black-list"); -constexpr auto SHRPX_OPT_BACKEND_HTTP1_TLS = - StringRef::from_lit("backend-http1-tls"); + "no-http2-cipher-black-list"_sr; +constexpr auto SHRPX_OPT_BACKEND_HTTP1_TLS = "backend-http1-tls"_sr; constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS = - StringRef::from_lit("tls-session-cache-memcached-tls"); + "tls-session-cache-memcached-tls"_sr; constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE = - StringRef::from_lit("tls-session-cache-memcached-cert-file"); + "tls-session-cache-memcached-cert-file"_sr; constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE = - StringRef::from_lit("tls-session-cache-memcached-private-key-file"); + "tls-session-cache-memcached-private-key-file"_sr; constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY = - StringRef::from_lit("tls-session-cache-memcached-address-family"); + "tls-session-cache-memcached-address-family"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS = - StringRef::from_lit("tls-ticket-key-memcached-tls"); + "tls-ticket-key-memcached-tls"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE = - StringRef::from_lit("tls-ticket-key-memcached-cert-file"); + "tls-ticket-key-memcached-cert-file"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE = - StringRef::from_lit("tls-ticket-key-memcached-private-key-file"); + "tls-ticket-key-memcached-private-key-file"_sr; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY = - StringRef::from_lit("tls-ticket-key-memcached-address-family"); -constexpr auto SHRPX_OPT_BACKEND_ADDRESS_FAMILY = - StringRef::from_lit("backend-address-family"); + "tls-ticket-key-memcached-address-family"_sr; +constexpr auto SHRPX_OPT_BACKEND_ADDRESS_FAMILY = "backend-address-family"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("frontend-http2-max-concurrent-streams"); + "frontend-http2-max-concurrent-streams"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("backend-http2-max-concurrent-streams"); + "backend-http2-max-concurrent-streams"_sr; constexpr auto SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND = - StringRef::from_lit("backend-connections-per-frontend"); -constexpr auto SHRPX_OPT_BACKEND_TLS = StringRef::from_lit("backend-tls"); + "backend-connections-per-frontend"_sr; +constexpr auto SHRPX_OPT_BACKEND_TLS = "backend-tls"_sr; constexpr auto SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST = - StringRef::from_lit("backend-connections-per-host"); -constexpr auto SHRPX_OPT_ERROR_PAGE = StringRef::from_lit("error-page"); -constexpr auto SHRPX_OPT_NO_KQUEUE = StringRef::from_lit("no-kqueue"); + "backend-connections-per-host"_sr; +constexpr auto SHRPX_OPT_ERROR_PAGE = "error-page"_sr; +constexpr auto SHRPX_OPT_NO_KQUEUE = "no-kqueue"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT = - StringRef::from_lit("frontend-http2-settings-timeout"); + "frontend-http2-settings-timeout"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT = - StringRef::from_lit("backend-http2-settings-timeout"); -constexpr auto SHRPX_OPT_API_MAX_REQUEST_BODY = - StringRef::from_lit("api-max-request-body"); -constexpr auto SHRPX_OPT_BACKEND_MAX_BACKOFF = - StringRef::from_lit("backend-max-backoff"); -constexpr auto SHRPX_OPT_SERVER_NAME = StringRef::from_lit("server-name"); -constexpr auto SHRPX_OPT_NO_SERVER_REWRITE = - StringRef::from_lit("no-server-rewrite"); + "backend-http2-settings-timeout"_sr; +constexpr auto SHRPX_OPT_API_MAX_REQUEST_BODY = "api-max-request-body"_sr; +constexpr auto SHRPX_OPT_BACKEND_MAX_BACKOFF = "backend-max-backoff"_sr; +constexpr auto SHRPX_OPT_SERVER_NAME = "server-name"_sr; +constexpr auto SHRPX_OPT_NO_SERVER_REWRITE = "no-server-rewrite"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE = - StringRef::from_lit("frontend-http2-optimize-write-buffer-size"); + "frontend-http2-optimize-write-buffer-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE = - StringRef::from_lit("frontend-http2-optimize-window-size"); + "frontend-http2-optimize-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE = - StringRef::from_lit("frontend-http2-window-size"); + "frontend-http2-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE = - StringRef::from_lit("frontend-http2-connection-window-size"); + "frontend-http2-connection-window-size"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE = - StringRef::from_lit("backend-http2-window-size"); + "backend-http2-window-size"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE = - StringRef::from_lit("backend-http2-connection-window-size"); + "backend-http2-connection-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE = - StringRef::from_lit("frontend-http2-encoder-dynamic-table-size"); + "frontend-http2-encoder-dynamic-table-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE = - StringRef::from_lit("frontend-http2-decoder-dynamic-table-size"); + "frontend-http2-decoder-dynamic-table-size"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE = - StringRef::from_lit("backend-http2-encoder-dynamic-table-size"); + "backend-http2-encoder-dynamic-table-size"_sr; constexpr auto SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE = - StringRef::from_lit("backend-http2-decoder-dynamic-table-size"); -constexpr auto SHRPX_OPT_ECDH_CURVES = StringRef::from_lit("ecdh-curves"); -constexpr auto SHRPX_OPT_TLS_SCT_DIR = StringRef::from_lit("tls-sct-dir"); -constexpr auto SHRPX_OPT_BACKEND_CONNECT_TIMEOUT = - StringRef::from_lit("backend-connect-timeout"); -constexpr auto SHRPX_OPT_DNS_CACHE_TIMEOUT = - StringRef::from_lit("dns-cache-timeout"); -constexpr auto SHRPX_OPT_DNS_LOOKUP_TIMEOUT = - StringRef::from_lit("dns-lookup-timeout"); -constexpr auto SHRPX_OPT_DNS_MAX_TRY = StringRef::from_lit("dns-max-try"); + "backend-http2-decoder-dynamic-table-size"_sr; +constexpr auto SHRPX_OPT_ECDH_CURVES = "ecdh-curves"_sr; +constexpr auto SHRPX_OPT_TLS_SCT_DIR = "tls-sct-dir"_sr; +constexpr auto SHRPX_OPT_BACKEND_CONNECT_TIMEOUT = "backend-connect-timeout"_sr; +constexpr auto SHRPX_OPT_DNS_CACHE_TIMEOUT = "dns-cache-timeout"_sr; +constexpr auto SHRPX_OPT_DNS_LOOKUP_TIMEOUT = "dns-lookup-timeout"_sr; +constexpr auto SHRPX_OPT_DNS_MAX_TRY = "dns-max-try"_sr; constexpr auto SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT = - StringRef::from_lit("frontend-keep-alive-timeout"); -constexpr auto SHRPX_OPT_PSK_SECRETS = StringRef::from_lit("psk-secrets"); -constexpr auto SHRPX_OPT_CLIENT_PSK_SECRETS = - StringRef::from_lit("client-psk-secrets"); + "frontend-keep-alive-timeout"_sr; +constexpr auto SHRPX_OPT_PSK_SECRETS = "psk-secrets"_sr; +constexpr auto SHRPX_OPT_CLIENT_PSK_SECRETS = "client-psk-secrets"_sr; constexpr auto SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST = - StringRef::from_lit("client-no-http2-cipher-block-list"); + "client-no-http2-cipher-block-list"_sr; constexpr auto SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST = - StringRef::from_lit("client-no-http2-cipher-black-list"); -constexpr auto SHRPX_OPT_CLIENT_CIPHERS = StringRef::from_lit("client-ciphers"); -constexpr auto SHRPX_OPT_ACCESSLOG_WRITE_EARLY = - StringRef::from_lit("accesslog-write-early"); -constexpr auto SHRPX_OPT_TLS_MIN_PROTO_VERSION = - StringRef::from_lit("tls-min-proto-version"); -constexpr auto SHRPX_OPT_TLS_MAX_PROTO_VERSION = - StringRef::from_lit("tls-max-proto-version"); -constexpr auto SHRPX_OPT_REDIRECT_HTTPS_PORT = - StringRef::from_lit("redirect-https-port"); -constexpr auto SHRPX_OPT_FRONTEND_MAX_REQUESTS = - StringRef::from_lit("frontend-max-requests"); -constexpr auto SHRPX_OPT_SINGLE_THREAD = StringRef::from_lit("single-thread"); -constexpr auto SHRPX_OPT_SINGLE_PROCESS = StringRef::from_lit("single-process"); + "client-no-http2-cipher-black-list"_sr; +constexpr auto SHRPX_OPT_CLIENT_CIPHERS = "client-ciphers"_sr; +constexpr auto SHRPX_OPT_ACCESSLOG_WRITE_EARLY = "accesslog-write-early"_sr; +constexpr auto SHRPX_OPT_TLS_MIN_PROTO_VERSION = "tls-min-proto-version"_sr; +constexpr auto SHRPX_OPT_TLS_MAX_PROTO_VERSION = "tls-max-proto-version"_sr; +constexpr auto SHRPX_OPT_REDIRECT_HTTPS_PORT = "redirect-https-port"_sr; +constexpr auto SHRPX_OPT_FRONTEND_MAX_REQUESTS = "frontend-max-requests"_sr; +constexpr auto SHRPX_OPT_SINGLE_THREAD = "single-thread"_sr; +constexpr auto SHRPX_OPT_SINGLE_PROCESS = "single-process"_sr; constexpr auto SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO = - StringRef::from_lit("no-add-x-forwarded-proto"); + "no-add-x-forwarded-proto"_sr; constexpr auto SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO = - StringRef::from_lit("no-strip-incoming-x-forwarded-proto"); -constexpr auto SHRPX_OPT_OCSP_STARTUP = StringRef::from_lit("ocsp-startup"); -constexpr auto SHRPX_OPT_NO_VERIFY_OCSP = StringRef::from_lit("no-verify-ocsp"); + "no-strip-incoming-x-forwarded-proto"_sr; +constexpr auto SHRPX_OPT_OCSP_STARTUP = "ocsp-startup"_sr; +constexpr auto SHRPX_OPT_NO_VERIFY_OCSP = "no-verify-ocsp"_sr; constexpr auto SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED = - StringRef::from_lit("verify-client-tolerate-expired"); + "verify-client-tolerate-expired"_sr; constexpr auto SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR = - StringRef::from_lit("ignore-per-pattern-mruby-error"); + "ignore-per-pattern-mruby-error"_sr; constexpr auto SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA = - StringRef::from_lit("tls-no-postpone-early-data"); -constexpr auto SHRPX_OPT_TLS_MAX_EARLY_DATA = - StringRef::from_lit("tls-max-early-data"); -constexpr auto SHRPX_OPT_TLS13_CIPHERS = StringRef::from_lit("tls13-ciphers"); -constexpr auto SHRPX_OPT_TLS13_CLIENT_CIPHERS = - StringRef::from_lit("tls13-client-ciphers"); + "tls-no-postpone-early-data"_sr; +constexpr auto SHRPX_OPT_TLS_MAX_EARLY_DATA = "tls-max-early-data"_sr; +constexpr auto SHRPX_OPT_TLS13_CIPHERS = "tls13-ciphers"_sr; +constexpr auto SHRPX_OPT_TLS13_CLIENT_CIPHERS = "tls13-client-ciphers"_sr; constexpr auto SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA = - StringRef::from_lit("no-strip-incoming-early-data"); -constexpr auto SHRPX_OPT_QUIC_BPF_PROGRAM_FILE = - StringRef::from_lit("quic-bpf-program-file"); -constexpr auto SHRPX_OPT_NO_QUIC_BPF = StringRef::from_lit("no-quic-bpf"); -constexpr auto SHRPX_OPT_HTTP2_ALTSVC = StringRef::from_lit("http2-altsvc"); + "no-strip-incoming-early-data"_sr; +constexpr auto SHRPX_OPT_QUIC_BPF_PROGRAM_FILE = "quic-bpf-program-file"_sr; +constexpr auto SHRPX_OPT_NO_QUIC_BPF = "no-quic-bpf"_sr; +constexpr auto SHRPX_OPT_HTTP2_ALTSVC = "http2-altsvc"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_READ_TIMEOUT = - StringRef::from_lit("frontend-http3-read-timeout"); + "frontend-http3-read-timeout"_sr; constexpr auto SHRPX_OPT_FRONTEND_QUIC_IDLE_TIMEOUT = - StringRef::from_lit("frontend-quic-idle-timeout"); -constexpr auto SHRPX_OPT_FRONTEND_QUIC_DEBUG_LOG = - StringRef::from_lit("frontend-quic-debug-log"); + "frontend-quic-idle-timeout"_sr; +constexpr auto SHRPX_OPT_FRONTEND_QUIC_DEBUG_LOG = "frontend-quic-debug-log"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_WINDOW_SIZE = - StringRef::from_lit("frontend-http3-window-size"); + "frontend-http3-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE = - StringRef::from_lit("frontend-http3-connection-window-size"); + "frontend-http3-connection-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_MAX_WINDOW_SIZE = - StringRef::from_lit("frontend-http3-max-window-size"); + "frontend-http3-max-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE = - StringRef::from_lit("frontend-http3-max-connection-window-size"); + "frontend-http3-max-connection-window-size"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("frontend-http3-max-concurrent-streams"); + "frontend-http3-max-concurrent-streams"_sr; constexpr auto SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA = - StringRef::from_lit("frontend-quic-early-data"); -constexpr auto SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR = - StringRef::from_lit("frontend-quic-qlog-dir"); + "frontend-quic-early-data"_sr; +constexpr auto SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR = "frontend-quic-qlog-dir"_sr; constexpr auto SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN = - StringRef::from_lit("frontend-quic-require-token"); + "frontend-quic-require-token"_sr; constexpr auto SHRPX_OPT_FRONTEND_QUIC_CONGESTION_CONTROLLER = - StringRef::from_lit("frontend-quic-congestion-controller"); -constexpr auto SHRPX_OPT_QUIC_SERVER_ID = StringRef::from_lit("quic-server-id"); + "frontend-quic-congestion-controller"_sr; +constexpr auto SHRPX_OPT_QUIC_SERVER_ID = "quic-server-id"_sr; constexpr auto SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE = - StringRef::from_lit("frontend-quic-secret-file"); -constexpr auto SHRPX_OPT_RLIMIT_MEMLOCK = StringRef::from_lit("rlimit-memlock"); -constexpr auto SHRPX_OPT_MAX_WORKER_PROCESSES = - StringRef::from_lit("max-worker-processes"); + "frontend-quic-secret-file"_sr; +constexpr auto SHRPX_OPT_RLIMIT_MEMLOCK = "rlimit-memlock"_sr; +constexpr auto SHRPX_OPT_MAX_WORKER_PROCESSES = "max-worker-processes"_sr; constexpr auto SHRPX_OPT_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD = - StringRef::from_lit("worker-process-grace-shutdown-period"); + "worker-process-grace-shutdown-period"_sr; constexpr auto SHRPX_OPT_FRONTEND_QUIC_INITIAL_RTT = - StringRef::from_lit("frontend-quic-initial-rtt"); -constexpr auto SHRPX_OPT_REQUIRE_HTTP_SCHEME = - StringRef::from_lit("require-http-scheme"); -constexpr auto SHRPX_OPT_TLS_KTLS = StringRef::from_lit("tls-ktls"); -constexpr auto SHRPX_OPT_ALPN_LIST = StringRef::from_lit("alpn-list"); -constexpr auto SHRPX_OPT_FRONTEND_HEADER_TIMEOUT = - StringRef::from_lit("frontend-header-timeout"); + "frontend-quic-initial-rtt"_sr; +constexpr auto SHRPX_OPT_REQUIRE_HTTP_SCHEME = "require-http-scheme"_sr; +constexpr auto SHRPX_OPT_TLS_KTLS = "tls-ktls"_sr; +constexpr auto SHRPX_OPT_ALPN_LIST = "alpn-list"_sr; +constexpr auto SHRPX_OPT_FRONTEND_HEADER_TIMEOUT = "frontend-header-timeout"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_IDLE_TIMEOUT = - StringRef::from_lit("frontend-http2-idle-timeout"); + "frontend-http2-idle-timeout"_sr; constexpr auto SHRPX_OPT_FRONTEND_HTTP3_IDLE_TIMEOUT = - StringRef::from_lit("frontend-http3-idle-timeout"); + "frontend-http3-idle-timeout"_sr; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; -constexpr char DEFAULT_DOWNSTREAM_HOST[] = "127.0.0.1"; +constexpr auto DEFAULT_DOWNSTREAM_HOST = "127.0.0.1"_sr; constexpr int16_t DEFAULT_DOWNSTREAM_PORT = 80; enum class Proto { @@ -1393,8 +1335,8 @@ enum { SHRPX_OPTID_MAXIDX, }; -// Looks up token for given option name |name| of length |namelen|. -int option_lookup_token(const char *name, size_t namelen); +// Looks up token for given option name |name|. +int option_lookup_token(const StringRef &name); // Parses option name |opt| and value |optarg|. The results are // stored into the object pointed by |config|. This function returns 0 diff --git a/src/shrpx_config_test.cc b/src/shrpx_config_test.cc index 068f185..9e08f81 100644 --- a/src/shrpx_config_test.cc +++ b/src/shrpx_config_test.cc @@ -35,6 +35,8 @@ #include "shrpx_config.h" #include "shrpx_log.h" +using namespace std::literals; + namespace shrpx { namespace { @@ -54,32 +56,32 @@ const MunitSuite config_suite{ void test_shrpx_config_parse_header(void) { BlockAllocator balloc(4096, 4096); - auto p = parse_header(balloc, StringRef::from_lit("a: b")); - assert_stdstring_equal("a", p.name.str()); - assert_stdstring_equal("b", p.value.str()); + auto p = parse_header(balloc, "a: b"_sr); + assert_stdsv_equal("a"sv, p.name); + assert_stdsv_equal("b"sv, p.value); - p = parse_header(balloc, StringRef::from_lit("a: b")); - assert_stdstring_equal("a", p.name.str()); - assert_stdstring_equal("b", p.value.str()); + p = parse_header(balloc, "a: b"_sr); + assert_stdsv_equal("a"sv, p.name); + assert_stdsv_equal("b"sv, p.value); - p = parse_header(balloc, StringRef::from_lit(":a: b")); + p = parse_header(balloc, ":a: b"_sr); assert_true(p.name.empty()); - p = parse_header(balloc, StringRef::from_lit("a: :b")); - assert_stdstring_equal("a", p.name.str()); - assert_stdstring_equal(":b", p.value.str()); + p = parse_header(balloc, "a: :b"_sr); + assert_stdsv_equal("a"sv, p.name); + assert_stdsv_equal(":b"sv, p.value); - p = parse_header(balloc, StringRef::from_lit(": b")); + p = parse_header(balloc, ": b"_sr); assert_true(p.name.empty()); - p = parse_header(balloc, StringRef::from_lit("alpha: bravo charlie")); - assert_stdstring_equal("alpha", p.name.str()); - assert_stdstring_equal("bravo charlie", p.value.str()); + p = parse_header(balloc, "alpha: bravo charlie"_sr); + assert_stdsv_equal("alpha", p.name); + assert_stdsv_equal("bravo charlie", p.value); - p = parse_header(balloc, StringRef::from_lit("a,: b")); + p = parse_header(balloc, "a,: b"_sr); assert_true(p.name.empty()); - p = parse_header(balloc, StringRef::from_lit("a: b\x0a")); + p = parse_header(balloc, "a: b\x0a"_sr); assert_true(p.name.empty()); } @@ -87,91 +89,90 @@ void test_shrpx_config_parse_log_format(void) { BlockAllocator balloc(4096, 4096); auto res = parse_log_format( - balloc, StringRef::from_lit( - R"($remote_addr - $remote_user [$time_local] )" - R"("$request" $status $body_bytes_sent )" - R"("${http_referer}" $http_host "$http_user_agent")")); + balloc, R"($remote_addr - $remote_user [$time_local] )" + R"("$request" $status $body_bytes_sent )" + R"("${http_referer}" $http_host "$http_user_agent")"_sr); assert_size(16, ==, res.size()); assert_enum_class(LogFragmentType::REMOTE_ADDR, ==, res[0].type); assert_enum_class(LogFragmentType::LITERAL, ==, res[1].type); - assert_stdstring_equal(" - $remote_user [", res[1].value.str()); + assert_stdsv_equal(" - $remote_user ["sv, res[1].value); assert_enum_class(LogFragmentType::TIME_LOCAL, ==, res[2].type); assert_enum_class(LogFragmentType::LITERAL, ==, res[3].type); - assert_stdstring_equal("] \"", res[3].value.str()); + assert_stdsv_equal("] \""sv, res[3].value); assert_enum_class(LogFragmentType::REQUEST, ==, res[4].type); assert_enum_class(LogFragmentType::LITERAL, ==, res[5].type); - assert_stdstring_equal("\" ", res[5].value.str()); + assert_stdsv_equal("\" "sv, res[5].value); assert_enum_class(LogFragmentType::STATUS, ==, res[6].type); assert_enum_class(LogFragmentType::LITERAL, ==, res[7].type); - assert_stdstring_equal(" ", res[7].value.str()); + assert_stdsv_equal(" "sv, res[7].value); assert_enum_class(LogFragmentType::BODY_BYTES_SENT, ==, res[8].type); assert_enum_class(LogFragmentType::LITERAL, ==, res[9].type); - assert_stdstring_equal(" \"", res[9].value.str()); + assert_stdsv_equal(" \""sv, res[9].value); assert_enum_class(LogFragmentType::HTTP, ==, res[10].type); - assert_stdstring_equal("referer", res[10].value.str()); + assert_stdsv_equal("referer"sv, res[10].value); assert_enum_class(LogFragmentType::LITERAL, ==, res[11].type); - assert_stdstring_equal("\" ", res[11].value.str()); + assert_stdsv_equal("\" "sv, res[11].value); assert_enum_class(LogFragmentType::AUTHORITY, ==, res[12].type); assert_enum_class(LogFragmentType::LITERAL, ==, res[13].type); - assert_stdstring_equal(" \"", res[13].value.str()); + assert_stdsv_equal(" \""sv, res[13].value); assert_enum_class(LogFragmentType::HTTP, ==, res[14].type); - assert_stdstring_equal("user-agent", res[14].value.str()); + assert_stdsv_equal("user-agent"sv, res[14].value); assert_enum_class(LogFragmentType::LITERAL, ==, res[15].type); - assert_stdstring_equal("\"", res[15].value.str()); + assert_stdsv_equal("\""sv, res[15].value); - res = parse_log_format(balloc, StringRef::from_lit("$")); + res = parse_log_format(balloc, "$"_sr); assert_size(1, ==, res.size()); assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type); - assert_stdstring_equal("$", res[0].value.str()); + assert_stdsv_equal("$"sv, res[0].value); - res = parse_log_format(balloc, StringRef::from_lit("${")); + res = parse_log_format(balloc, "${"_sr); assert_size(1, ==, res.size()); assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type); - assert_stdstring_equal("${", res[0].value.str()); + assert_stdsv_equal("${"sv, res[0].value); - res = parse_log_format(balloc, StringRef::from_lit("${a")); + res = parse_log_format(balloc, "${a"_sr); assert_size(1, ==, res.size()); assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type); - assert_stdstring_equal("${a", res[0].value.str()); + assert_stdsv_equal("${a"sv, res[0].value); - res = parse_log_format(balloc, StringRef::from_lit("${a ")); + res = parse_log_format(balloc, "${a "_sr); assert_size(1, ==, res.size()); assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type); - assert_stdstring_equal("${a ", res[0].value.str()); + assert_stdsv_equal("${a "sv, res[0].value); - res = parse_log_format(balloc, StringRef::from_lit("$$remote_addr")); + res = parse_log_format(balloc, "$$remote_addr"_sr); assert_size(2, ==, res.size()); assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type); - assert_stdstring_equal("$", res[0].value.str()); + assert_stdsv_equal("$"sv, res[0].value); assert_enum_class(LogFragmentType::REMOTE_ADDR, ==, res[1].type); - assert_stdstring_equal("", res[1].value.str()); + assert_stdsv_equal(""sv, res[1].value); } void test_shrpx_config_read_tls_ticket_key_file(void) { diff --git a/src/shrpx_connection.cc b/src/shrpx_connection.cc index d863284..972faf4 100644 --- a/src/shrpx_connection.cc +++ b/src/shrpx_connection.cc @@ -782,8 +782,8 @@ int Connection::write_tls_pending_handshake() { << " protocol=" << tls_info.protocol << " resumption=" << (tls_info.session_reused ? "yes" : "no") << " session_id=" - << util::format_hex(tls_info.session_id, - tls_info.session_id_length); + << util::format_hex(std::span{tls_info.session_id, + tls_info.session_id_length}); } } diff --git a/src/shrpx_connection_handler.cc b/src/shrpx_connection_handler.cc index b29ce9a..ad88aa6 100644 --- a/src/shrpx_connection_handler.cc +++ b/src/shrpx_connection_handler.cc @@ -647,7 +647,7 @@ int ConnectionHandler::start_ocsp_update(const char *cert_file) { char *const argv[] = { const_cast<char *>( - get_config()->tls.ocsp.fetch_ocsp_response_file.c_str()), + get_config()->tls.ocsp.fetch_ocsp_response_file.data()), const_cast<char *>(cert_file), nullptr}; Process proc; @@ -740,8 +740,7 @@ void ConnectionHandler::handle_ocsp_complete() { auto quic_tls_ctx_data = static_cast<tls::TLSContextData *>( SSL_CTX_get_app_data(quic_ssl_ctx)); # ifdef HAVE_ATOMIC_STD_SHARED_PTR - std::atomic_store_explicit( - &quic_tls_ctx_data->ocsp_data, + quic_tls_ctx_data->ocsp_data.store( std::make_shared<std::vector<uint8_t>>(ocsp_.resp), std::memory_order_release); # else // !HAVE_ATOMIC_STD_SHARED_PTR @@ -753,8 +752,7 @@ void ConnectionHandler::handle_ocsp_complete() { #endif // ENABLE_HTTP3 #ifdef HAVE_ATOMIC_STD_SHARED_PTR - std::atomic_store_explicit( - &tls_ctx_data->ocsp_data, + tls_ctx_data->ocsp_data.store( std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp)), std::memory_order_release); #else // !HAVE_ATOMIC_STD_SHARED_PTR @@ -1004,10 +1002,12 @@ void ConnectionHandler::set_enable_acceptor_on_ocsp_completion(bool f) { } #ifdef ENABLE_HTTP3 -int ConnectionHandler::forward_quic_packet( - const UpstreamAddr *faddr, const Address &remote_addr, - const Address &local_addr, const ngtcp2_pkt_info &pi, const WorkerID &wid, - const uint8_t *data, size_t datalen) { +int ConnectionHandler::forward_quic_packet(const UpstreamAddr *faddr, + const Address &remote_addr, + const Address &local_addr, + const ngtcp2_pkt_info &pi, + const WorkerID &wid, + std::span<const uint8_t> data) { assert(!get_config()->single_thread); auto worker = find_worker(wid); @@ -1018,7 +1018,7 @@ int ConnectionHandler::forward_quic_packet( WorkerEvent wev{}; wev.type = WorkerEventType::QUIC_PKT_FORWARD; wev.quic_pkt = std::make_unique<QUICPacket>(faddr->index, remote_addr, - local_addr, pi, data, datalen); + local_addr, pi, data); worker->send(std::move(wev)); @@ -1104,8 +1104,8 @@ void ConnectionHandler::set_quic_lingering_worker_processes( int ConnectionHandler::forward_quic_packet_to_lingering_worker_process( QUICLingeringWorkerProcess *quic_lwp, const Address &remote_addr, - const Address &local_addr, const ngtcp2_pkt_info &pi, const uint8_t *data, - size_t datalen) { + const Address &local_addr, const ngtcp2_pkt_info &pi, + std::span<const uint8_t> data) { std::array<uint8_t, 512> header; assert(header.size() >= 1 + 1 + 1 + 1 + sizeof(sockaddr_storage) * 2); @@ -1129,8 +1129,8 @@ int ConnectionHandler::forward_quic_packet_to_lingering_worker_process( .iov_len = static_cast<size_t>(p - header.data()), }, { - .iov_base = const_cast<uint8_t *>(data), - .iov_len = datalen, + .iov_base = const_cast<uint8_t *>(data.data()), + .iov_len = data.size(), }, }; @@ -1279,8 +1279,7 @@ int ConnectionHandler::quic_ipc_read() { // Ignore return value quic_conn_handler->handle_packet(faddr, pkt->remote_addr, pkt->local_addr, - pkt->pi, pkt->data.data(), - pkt->data.size()); + pkt->pi, pkt->data); return 0; } diff --git a/src/shrpx_connection_handler.h b/src/shrpx_connection_handler.h index 47ec209..16e56e0 100644 --- a/src/shrpx_connection_handler.h +++ b/src/shrpx_connection_handler.h @@ -195,8 +195,7 @@ public: int forward_quic_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const WorkerID &wid, const uint8_t *data, - size_t datalen); + const WorkerID &wid, std::span<const uint8_t> data); void set_quic_keying_materials(std::shared_ptr<QUICKeyingMaterials> qkms); const std::shared_ptr<QUICKeyingMaterials> &get_quic_keying_materials() const; @@ -215,8 +214,8 @@ public: int forward_quic_packet_to_lingering_worker_process( QUICLingeringWorkerProcess *quic_lwp, const Address &remote_addr, - const Address &local_addr, const ngtcp2_pkt_info &pi, const uint8_t *data, - size_t datalen); + const Address &local_addr, const ngtcp2_pkt_info &pi, + std::span<const uint8_t> data); void set_quic_ipc_fd(int fd); diff --git a/src/shrpx_dns_resolver.cc b/src/shrpx_dns_resolver.cc index 8253942..ceda612 100644 --- a/src/shrpx_dns_resolver.cc +++ b/src/shrpx_dns_resolver.cc @@ -178,7 +178,7 @@ int DNSResolver::resolve(const StringRef &name, int family) { ares_addrinfo_hints hints{}; hints.ai_family = family_; - ares_getaddrinfo(channel_, name_.c_str(), nullptr, &hints, addrinfo_cb, this); + ares_getaddrinfo(channel_, name_.data(), nullptr, &hints, addrinfo_cb, this); reset_timeout(); return 0; diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index 5fd717e..73d7f11 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -344,7 +344,7 @@ StringRef Downstream::assemble_request_cookie() { } auto iov = make_byte_ref(balloc_, len + 1); - auto p = iov.base; + auto p = std::begin(iov); for (auto &kv : req_.fs.headers()) { if (kv.token != http2::HD_COOKIE || kv.value.empty()) { @@ -367,11 +367,11 @@ StringRef Downstream::assemble_request_cookie() { } // cut trailing "; " - if (p - iov.base >= 2) { + if (p - std::begin(iov) >= 2) { p -= 2; } - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } uint32_t Downstream::find_affinity_cookie(const StringRef &name) { @@ -391,7 +391,7 @@ uint32_t Downstream::find_affinity_cookie(const StringRef &name) { return 0; } - if (!util::streq(name, StringRef{it, end})) { + if (name != StringRef{it, end}) { it = std::find(it, std::end(kv.value), ';'); continue; } @@ -474,12 +474,11 @@ void add_header(size_t &sum, HeaderRefs &headers, const StringRef &name, namespace { StringRef alloc_header_name(BlockAllocator &balloc, const StringRef &name) { auto iov = make_byte_ref(balloc, name.size() + 1); - auto p = iov.base; - p = std::copy(std::begin(name), std::end(name), p); - util::inp_strlower(iov.base, p); + auto p = std::copy(std::begin(name), std::end(name), std::begin(iov)); + util::inp_strlower(std::begin(iov), p); *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } } // namespace @@ -521,13 +520,13 @@ int FieldStore::parse_content_length() { } auto len = util::parse_uint(kv.value); - if (len == -1) { + if (!len) { return -1; } if (content_length != -1) { return -1; } - content_length = len; + content_length = *len; } return 0; } @@ -732,7 +731,7 @@ void Downstream::rewrite_location_response_header( } http_parser_url u{}; - auto rv = http_parser_parse_url(hd->value.c_str(), hd->value.size(), 0, &u); + auto rv = http_parser_parse_url(hd->value.data(), hd->value.size(), 0, &u); if (rv != 0) { return; } @@ -841,7 +840,7 @@ void Downstream::check_upgrade_fulfilled_http1() { auto expected = http2::make_websocket_accept_token(accept_buf.data(), ws_key_); - upgraded_ = expected != "" && expected == accept->value; + upgraded_ = !expected.empty() && expected == accept->value; } else { upgraded_ = resp_.http_status / 100 == 2; } @@ -871,15 +870,14 @@ void Downstream::inspect_http1_request() { if (upgrade) { const auto &val = upgrade->value; // TODO Perform more strict checking for upgrade headers - if (util::streq_l(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, val.c_str(), - val.size())) { + if (NGHTTP2_CLEARTEXT_PROTO_VERSION_ID ""_sr == val) { req_.http2_upgrade_seen = true; } else { req_.upgrade_request = true; // TODO Should we check Sec-WebSocket-Key, and // Sec-WebSocket-Version as well? - if (util::strieq_l("websocket", val)) { + if (util::strieq("websocket"_sr, val)) { req_.connect_proto = ConnectProto::WEBSOCKET; } } @@ -892,8 +890,7 @@ void Downstream::inspect_http1_request() { auto expect = req_.fs.header(http2::HD_EXPECT); expect_100_continue_ = - expect && - util::strieq(expect->value, StringRef::from_lit("100-continue")); + expect && util::strieq(expect->value, "100-continue"_sr); } void Downstream::inspect_http1_response() { diff --git a/src/shrpx_downstream_test.cc b/src/shrpx_downstream_test.cc index 46db9b7..bbccea8 100644 --- a/src/shrpx_downstream_test.cc +++ b/src/shrpx_downstream_test.cc @@ -30,6 +30,8 @@ #include "shrpx_downstream.h" +using namespace std::literals; + namespace shrpx { namespace { @@ -52,40 +54,35 @@ const MunitSuite downstream_suite{ void test_downstream_field_store_append_last_header(void) { BlockAllocator balloc(16, 16); FieldStore fs(balloc, 0); - fs.alloc_add_header_name(StringRef::from_lit("alpha")); - auto bravo = StringRef::from_lit("BRAVO"); - fs.append_last_header_key(bravo.c_str(), bravo.size()); + fs.alloc_add_header_name("alpha"_sr); + auto bravo = "BRAVO"_sr; + fs.append_last_header_key(bravo.data(), bravo.size()); // Add more characters so that relloc occurs - auto golf = StringRef::from_lit("golF0123456789"); - fs.append_last_header_key(golf.c_str(), golf.size()); + auto golf = "golF0123456789"_sr; + fs.append_last_header_key(golf.data(), golf.size()); - auto charlie = StringRef::from_lit("Charlie"); - fs.append_last_header_value(charlie.c_str(), charlie.size()); - auto delta = StringRef::from_lit("deltA"); - fs.append_last_header_value(delta.c_str(), delta.size()); + auto charlie = "Charlie"_sr; + fs.append_last_header_value(charlie.data(), charlie.size()); + auto delta = "deltA"_sr; + fs.append_last_header_value(delta.data(), delta.size()); // Add more characters so that relloc occurs - auto echo = StringRef::from_lit("echo0123456789"); - fs.append_last_header_value(echo.c_str(), echo.size()); + auto echo = "echo0123456789"_sr; + fs.append_last_header_value(echo.data(), echo.size()); - fs.add_header_token(StringRef::from_lit("echo"), - StringRef::from_lit("foxtrot"), false, -1); + fs.add_header_token("echo"_sr, "foxtrot"_sr, false, -1); - auto ans = - HeaderRefs{{StringRef::from_lit("alphabravogolf0123456789"), - StringRef::from_lit("CharliedeltAecho0123456789")}, - {StringRef::from_lit("echo"), StringRef::from_lit("foxtrot")}}; + auto ans = HeaderRefs{ + {"alphabravogolf0123456789"_sr, "CharliedeltAecho0123456789"_sr}, + {"echo"_sr, "foxtrot"_sr}}; assert_true(ans == fs.headers()); } void test_downstream_field_store_header(void) { BlockAllocator balloc(16, 16); FieldStore fs(balloc, 0); - fs.add_header_token(StringRef::from_lit("alpha"), StringRef::from_lit("0"), - false, -1); - fs.add_header_token(StringRef::from_lit(":authority"), - StringRef::from_lit("1"), false, http2::HD__AUTHORITY); - fs.add_header_token(StringRef::from_lit("content-length"), - StringRef::from_lit("2"), false, + fs.add_header_token("alpha"_sr, "0"_sr, false, -1); + fs.add_header_token(":authority"_sr, "1"_sr, false, http2::HD__AUTHORITY); + fs.add_header_token("content-length"_sr, "2"_sr, false, http2::HD_CONTENT_LENGTH); // By token @@ -95,25 +92,19 @@ void test_downstream_field_store_header(void) { // By name assert_true(HeaderRef(StringRef{"alpha"}, StringRef{"0"}) == - *fs.header(StringRef::from_lit("alpha"))); - assert_null(fs.header(StringRef::from_lit("bravo"))); + *fs.header("alpha"_sr)); + assert_null(fs.header("bravo"_sr)); } void test_downstream_crumble_request_cookie(void) { Downstream d(nullptr, nullptr, 0); auto &req = d.request(); - req.fs.add_header_token(StringRef::from_lit(":method"), - StringRef::from_lit("get"), false, -1); - req.fs.add_header_token(StringRef::from_lit(":path"), - StringRef::from_lit("/"), false, -1); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("alpha; bravo; ; ;; charlie;;"), - true, http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit(";delta"), false, + req.fs.add_header_token(":method"_sr, "get"_sr, false, -1); + req.fs.add_header_token(":path"_sr, "/"_sr, false, -1); + req.fs.add_header_token("cookie"_sr, "alpha; bravo; ; ;; charlie;;"_sr, true, http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("echo"), false, http2::HD_COOKIE); + req.fs.add_header_token("cookie"_sr, ";delta"_sr, false, http2::HD_COOKIE); + req.fs.add_header_token("cookie"_sr, "echo"_sr, false, http2::HD_COOKIE); std::vector<nghttp2_nv> nva; d.crumble_request_cookie(nva); @@ -131,12 +122,11 @@ void test_downstream_crumble_request_cookie(void) { nv.flags & NGHTTP2_NV_FLAG_NO_INDEX); }); - HeaderRefs ans = { - {StringRef::from_lit("cookie"), StringRef::from_lit("alpha")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("bravo")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("charlie")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("delta")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("echo")}}; + HeaderRefs ans = {{"cookie"_sr, "alpha"_sr}, + {"cookie"_sr, "bravo"_sr}, + {"cookie"_sr, "charlie"_sr}, + {"cookie"_sr, "delta"_sr}, + {"cookie"_sr, "echo"_sr}}; assert_true(ans == cookies); assert_true(cookies[0].no_index); @@ -148,38 +138,27 @@ void test_downstream_assemble_request_cookie(void) { Downstream d(nullptr, nullptr, 0); auto &req = d.request(); - req.fs.add_header_token(StringRef::from_lit(":method"), - StringRef::from_lit("get"), false, -1); - req.fs.add_header_token(StringRef::from_lit(":path"), - StringRef::from_lit("/"), false, -1); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("alpha"), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("bravo;"), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("charlie; "), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("delta;;"), false, - http2::HD_COOKIE); - assert_stdstring_equal("alpha; bravo; charlie; delta", - d.assemble_request_cookie().str()); + req.fs.add_header_token(":method"_sr, "get"_sr, false, -1); + req.fs.add_header_token(":path"_sr, "/"_sr, false, -1); + req.fs.add_header_token("cookie"_sr, "alpha"_sr, false, http2::HD_COOKIE); + req.fs.add_header_token("cookie"_sr, "bravo;"_sr, false, http2::HD_COOKIE); + req.fs.add_header_token("cookie"_sr, "charlie; "_sr, false, http2::HD_COOKIE); + req.fs.add_header_token("cookie"_sr, "delta;;"_sr, false, http2::HD_COOKIE); + assert_stdsv_equal("alpha; bravo; charlie; delta"sv, + d.assemble_request_cookie()); } void test_downstream_rewrite_location_response_header(void) { Downstream d(nullptr, nullptr, 0); auto &req = d.request(); auto &resp = d.response(); - d.set_request_downstream_host(StringRef::from_lit("localhost2")); - req.authority = StringRef::from_lit("localhost:8443"); - resp.fs.add_header_token(StringRef::from_lit("location"), - StringRef::from_lit("http://localhost2:3000/"), - false, http2::HD_LOCATION); - d.rewrite_location_response_header(StringRef::from_lit("https")); + d.set_request_downstream_host("localhost2"_sr); + req.authority = "localhost:8443"_sr; + resp.fs.add_header_token("location"_sr, "http://localhost2:3000/"_sr, false, + http2::HD_LOCATION); + d.rewrite_location_response_header("https"_sr); auto location = resp.fs.header(http2::HD_LOCATION); - assert_stdstring_equal("https://localhost:8443/", (*location).value.str()); + assert_stdsv_equal("https://localhost:8443/"sv, (*location).value); } void test_downstream_supports_non_final_response(void) { @@ -216,32 +195,26 @@ void test_downstream_find_affinity_cookie(void) { Downstream d(nullptr, nullptr, 0); auto &req = d.request(); - req.fs.add_header_token(StringRef::from_lit("cookie"), StringRef{}, false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("a=b;;c=d"), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("content-length"), - StringRef::from_lit("599"), false, + req.fs.add_header_token("cookie"_sr, StringRef{}, false, http2::HD_COOKIE); + req.fs.add_header_token("cookie"_sr, "a=b;;c=d"_sr, false, http2::HD_COOKIE); + req.fs.add_header_token("content-length"_sr, "599"_sr, false, http2::HD_CONTENT_LENGTH); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("lb=deadbeef;LB=f1f2f3f4"), false, + req.fs.add_header_token("cookie"_sr, "lb=deadbeef;LB=f1f2f3f4"_sr, false, http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("short=e1e2e3e"), false, + req.fs.add_header_token("cookie"_sr, "short=e1e2e3e"_sr, false, http2::HD_COOKIE); uint32_t aff; - aff = d.find_affinity_cookie(StringRef::from_lit("lb")); + aff = d.find_affinity_cookie("lb"_sr); assert_uint32(0xdeadbeef, ==, aff); - aff = d.find_affinity_cookie(StringRef::from_lit("LB")); + aff = d.find_affinity_cookie("LB"_sr); assert_uint32(0xf1f2f3f4, ==, aff); - aff = d.find_affinity_cookie(StringRef::from_lit("short")); + aff = d.find_affinity_cookie("short"_sr); assert_uint32(0, ==, aff); } diff --git a/src/shrpx_health_monitor_downstream_connection.cc b/src/shrpx_health_monitor_downstream_connection.cc index 89e5396..710de96 100644 --- a/src/shrpx_health_monitor_downstream_connection.cc +++ b/src/shrpx_health_monitor_downstream_connection.cc @@ -74,8 +74,7 @@ int HealthMonitorDownstreamConnection::end_upload_data() { resp.http_status = 200; - resp.fs.add_header_token(StringRef::from_lit("content-length"), - StringRef::from_lit("0"), false, + resp.fs.add_header_token("content-length"_sr, "0"_sr, false, http2::HD_CONTENT_LENGTH); if (upstream->send_reply(downstream_, nullptr, 0) != 0) { diff --git a/src/shrpx_http.cc b/src/shrpx_http.cc index 4750500..cd7e14b 100644 --- a/src/shrpx_http.cc +++ b/src/shrpx_http.cc @@ -41,7 +41,7 @@ StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) { const auto &error_pages = httpconf.error_pages; for (const auto &page : error_pages) { if (page.http_status == 0 || page.http_status == http_status) { - return StringRef{std::begin(page.content), std::end(page.content)}; + return StringRef{std::span{page.content}}; } } @@ -49,12 +49,10 @@ StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) { auto reason_phrase = http2::get_reason_phrase(http_status); return concat_string_ref( - balloc, StringRef::from_lit(R"(<!DOCTYPE html><html lang="en"><title>)"), - status_string, StringRef::from_lit(" "), reason_phrase, - StringRef::from_lit("</title><body><h1>"), status_string, - StringRef::from_lit(" "), reason_phrase, - StringRef::from_lit("</h1><footer>"), httpconf.server_name, - StringRef::from_lit("</footer></body></html>")); + balloc, R"(<!DOCTYPE html><html lang="en"><title>)"_sr, status_string, + " "_sr, reason_phrase, "</title><body><h1>"_sr, status_string, " "_sr, + reason_phrase, "</h1><footer>"_sr, httpconf.server_name, + "</footer></body></html>"_sr); } StringRef create_forwarded(BlockAllocator &balloc, int params, @@ -75,7 +73,7 @@ StringRef create_forwarded(BlockAllocator &balloc, int params, } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); if ((params & FORWARDED_BY) && !node_by.empty()) { // This must be quoted-string unless it is obfuscated version @@ -118,14 +116,14 @@ StringRef create_forwarded(BlockAllocator &balloc, int params, *p++ = ';'; } - if (iov.base == p) { + if (std::begin(iov) == p) { return StringRef{}; } --p; *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } std::string colorizeHeaders(const char *hdrs) { @@ -146,7 +144,7 @@ std::string colorizeHeaders(const char *hdrs) { nhdrs += TTY_HTTP_HD; nhdrs.append(p, np); nhdrs += TTY_RST; - auto redact = util::strieq_l("authorization", StringRef{p, np}); + auto redact = util::strieq("authorization"_sr, StringRef{p, np}); p = np; np = strchr(p, '\n'); if (!np) { @@ -176,8 +174,8 @@ nghttp2_ssize select_padding_callback(nghttp2_session *session, StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name, uint32_t affinity_cookie, const StringRef &path, bool secure) { - static constexpr auto PATH_PREFIX = StringRef::from_lit("; Path="); - static constexpr auto SECURE = StringRef::from_lit("; Secure"); + static constexpr auto PATH_PREFIX = "; Path="_sr; + static constexpr auto SECURE = "; Secure"_sr; // <name>=<value>[; Path=<path>][; Secure] size_t len = name.size() + 1 + 8; @@ -189,14 +187,10 @@ StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name, } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - p = std::copy(std::begin(name), std::end(name), p); + auto p = std::copy(std::begin(name), std::end(name), std::begin(iov)); *p++ = '='; affinity_cookie = htonl(affinity_cookie); - p = util::format_hex(p, - StringRef{reinterpret_cast<uint8_t *>(&affinity_cookie), - reinterpret_cast<uint8_t *>(&affinity_cookie) + - sizeof(affinity_cookie)}); + p = util::format_hex(p, std::span{&affinity_cookie, 1}); if (!path.empty()) { p = std::copy(std::begin(PATH_PREFIX), std::end(PATH_PREFIX), p); p = std::copy(std::begin(path), std::end(path), p); @@ -205,14 +199,14 @@ StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name, p = std::copy(std::begin(SECURE), std::end(SECURE), p); } *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } bool require_cookie_secure_attribute(SessionAffinityCookieSecure secure, const StringRef &scheme) { switch (secure) { case SessionAffinityCookieSecure::AUTO: - return scheme == "https"; + return scheme == "https"_sr; case SessionAffinityCookieSecure::YES: return true; default: @@ -247,7 +241,7 @@ StringRef create_altsvc_header_value(BlockAllocator &balloc, // We will write additional ", " at the end, and cut it later. auto iov = make_byte_ref(balloc, len + 2); - auto p = iov.base; + auto p = std::begin(iov); for (auto &altsvc : altsvcs) { p = util::percent_encode_token(p, altsvc.protocol_id); @@ -266,13 +260,13 @@ StringRef create_altsvc_header_value(BlockAllocator &balloc, p -= 2; *p = '\0'; - assert(static_cast<size_t>(p - iov.base) == len); + assert(static_cast<size_t>(p - std::begin(iov)) == len); - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } bool check_http_scheme(const StringRef &scheme, bool encrypted) { - return encrypted ? scheme == "https" : scheme == "http"; + return encrypted ? scheme == "https"_sr : scheme == "http"_sr; } } // namespace http diff --git a/src/shrpx_http2_downstream_connection.cc b/src/shrpx_http2_downstream_connection.cc index a6c9d53..dadf10a 100644 --- a/src/shrpx_http2_downstream_connection.cc +++ b/src/shrpx_http2_downstream_connection.cc @@ -295,11 +295,11 @@ int Http2DownstreamConnection::push_request_headers() { httpconf.add_request_headers.size()); if (req.connect_proto == ConnectProto::WEBSOCKET) { - nva.push_back(http2::make_nv_ll(":method", "CONNECT")); - nva.push_back(http2::make_nv_ll(":protocol", "websocket")); + nva.push_back(http2::make_field(":method"_sr, "CONNECT"_sr)); + nva.push_back(http2::make_field(":protocol"_sr, "websocket"_sr)); } else { - nva.push_back(http2::make_nv_ls_nocopy( - ":method", http2::to_method_string(req.method))); + nva.push_back( + http2::make_field(":method"_sr, http2::to_method_string(req.method))); } if (!req.regular_connect_method()) { @@ -308,25 +308,25 @@ int Http2DownstreamConnection::push_request_headers() { auto addr = http2session_->get_addr(); assert(addr); // We will handle more protocol scheme upgrade in the future. - if (addr->tls && addr->upgrade_scheme && req.scheme == "http") { - nva.push_back(http2::make_nv_ll(":scheme", "https")); + if (addr->tls && addr->upgrade_scheme && req.scheme == "http"_sr) { + nva.push_back(http2::make_field(":scheme"_sr, "https"_sr)); } else { - nva.push_back(http2::make_nv_ls_nocopy(":scheme", req.scheme)); + nva.push_back(http2::make_field(":scheme"_sr, req.scheme)); } if (req.method == HTTP_OPTIONS && req.path.empty()) { - nva.push_back(http2::make_nv_ll(":path", "*")); + nva.push_back(http2::make_field(":path"_sr, "*"_sr)); } else { - nva.push_back(http2::make_nv_ls_nocopy(":path", req.path)); + nva.push_back(http2::make_field(":path"_sr, req.path)); } if (!req.no_authority || req.connect_proto != ConnectProto::NONE) { - nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); + nva.push_back(http2::make_field(":authority"_sr, authority)); } else { - nva.push_back(http2::make_nv_ls_nocopy("host", authority)); + nva.push_back(http2::make_field("host"_sr, authority)); } } else { - nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); + nva.push_back(http2::make_field(":authority"_sr, authority)); } auto &fwdconf = httpconf.forwarded; @@ -354,7 +354,7 @@ int Http2DownstreamConnection::push_request_headers() { auto conn = handler->get_connection(); if (conn->tls.ssl && !SSL_is_init_finished(conn->tls.ssl)) { - nva.push_back(http2::make_nv_ll("early-data", "1")); + nva.push_back(http2::make_field("early-data"_sr, "1"_sr)); } #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL @@ -377,15 +377,14 @@ int Http2DownstreamConnection::push_request_headers() { if (value.empty()) { value = fwd->value; } else { - value = concat_string_ref(balloc, fwd->value, - StringRef::from_lit(", "), value); + value = concat_string_ref(balloc, fwd->value, ", "_sr, value); } } - nva.push_back(http2::make_nv_ls_nocopy("forwarded", value)); + nva.push_back(http2::make_field("forwarded"_sr, value)); } } else if (fwd) { - nva.push_back(http2::make_nv_ls_nocopy("forwarded", fwd->value)); + nva.push_back(http2::make_field("forwarded"_sr, fwd->value)); } auto xff = xffconf.strip_incoming ? nullptr @@ -395,14 +394,13 @@ int Http2DownstreamConnection::push_request_headers() { StringRef xff_value; const auto &addr = upstream->get_client_handler()->get_ipaddr(); if (xff) { - xff_value = concat_string_ref(balloc, xff->value, - StringRef::from_lit(", "), addr); + xff_value = concat_string_ref(balloc, xff->value, ", "_sr, addr); } else { xff_value = addr; } - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-for", xff_value)); + nva.push_back(http2::make_field("x-forwarded-for"_sr, xff_value)); } else if (xff) { - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-for", xff->value)); + nva.push_back(http2::make_field("x-forwarded-for"_sr, xff->value)); } if (!config->http2_proxy && !req.regular_connect_method()) { @@ -414,21 +412,20 @@ int Http2DownstreamConnection::push_request_headers() { StringRef xfp_value; // We use same protocol with :scheme header field if (xfp) { - xfp_value = concat_string_ref(balloc, xfp->value, - StringRef::from_lit(", "), req.scheme); + xfp_value = concat_string_ref(balloc, xfp->value, ", "_sr, req.scheme); } else { xfp_value = req.scheme; } - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-proto", xfp_value)); + nva.push_back(http2::make_field("x-forwarded-proto"_sr, xfp_value)); } else if (xfp) { - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-proto", xfp->value)); + nva.push_back(http2::make_field("x-forwarded-proto"_sr, xfp->value)); } } auto via = req.fs.header(http2::HD_VIA); if (httpconf.no_via) { if (via) { - nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); + nva.push_back(http2::make_field("via"_sr, (*via).value)); } } else { size_t vialen = 16; @@ -437,7 +434,7 @@ int Http2DownstreamConnection::push_request_headers() { } auto iov = make_byte_ref(balloc, vialen + 1); - auto p = iov.base; + auto p = std::begin(iov); if (via) { p = std::copy(std::begin(via->value), std::end(via->value), p); @@ -446,7 +443,8 @@ int Http2DownstreamConnection::push_request_headers() { p = http::create_via_header_value(p, req.http_major, req.http_minor); *p = '\0'; - nva.push_back(http2::make_nv_ls_nocopy("via", StringRef{iov.base, p})); + nva.push_back( + http2::make_field("via"_sr, StringRef{std::span{std::begin(iov), p}})); } auto te = req.fs.header(http2::HD_TE); @@ -454,22 +452,23 @@ int Http2DownstreamConnection::push_request_headers() { // "trailers". We just forward "trailers". // TODO more strict handling required here. if (te && http2::contains_trailers(te->value)) { - nva.push_back(http2::make_nv_ll("te", "trailers")); + nva.push_back(http2::make_field("te"_sr, "trailers"_sr)); } for (auto &p : httpconf.add_request_headers) { - nva.push_back(http2::make_nv_nocopy(p.name, p.value)); + nva.push_back(http2::make_field(p.name, p.value)); } if (LOG_ENABLED(INFO)) { std::stringstream ss; for (auto &nv : nva) { - if (util::streq_l("authorization", nv.name, nv.namelen)) { - ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST - << ": <redacted>\n"; + auto name = StringRef{nv.name, nv.namelen}; + + if ("authorization"_sr == name) { + ss << TTY_HTTP_HD << name << TTY_RST << ": <redacted>\n"; continue; } - ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": " + ss << TTY_HTTP_HD << name << TTY_RST << ": " << StringRef{nv.value, nv.valuelen} << "\n"; } DCLOG(INFO, this) << "HTTP request headers\n" << ss.str(); diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index dccdae4..4fc73ba 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -468,11 +468,11 @@ int Http2Session::initiate_connection() { auto sni_name = addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni}; - if (!util::numeric_host(sni_name.c_str())) { + if (!util::numeric_host(sni_name.data())) { // TLS extensions: SNI. There is no documentation about the return // code for this function (actually this is macro wrapping SSL_ctrl // at the time of this writing). - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str()); + SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.data()); } auto tls_session = tls::reuse_tls_session(addr_->tls_session_cache); @@ -693,7 +693,7 @@ int Http2Session::downstream_connect_proxy() { } std::string req = "CONNECT "; - req.append(addr_->hostport.c_str(), addr_->hostport.size()); + req.append(addr_->hostport.data(), addr_->hostport.size()); if (addr_->port == 80 || addr_->port == 443) { req += ':'; req += util::utos(addr_->port); @@ -939,7 +939,9 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } - auto token = http2::lookup_token(namebuf.base, namebuf.len); + auto nameref = StringRef{namebuf.base, namebuf.len}; + auto valueref = StringRef{valuebuf.base, valuebuf.len}; + auto token = http2::lookup_token(nameref); auto no_index = flags & NGHTTP2_NV_FLAG_NO_INDEX; downstream->add_rcbuf(name); @@ -947,15 +949,11 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, if (trailer) { // just store header fields for trailer part - resp.fs.add_trailer_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, - no_index, token); + resp.fs.add_trailer_token(nameref, valueref, no_index, token); return 0; } - resp.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + resp.fs.add_header_token(nameref, valueref, no_index, token); return 0; } case NGHTTP2_PUSH_PROMISE: { @@ -993,9 +991,10 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, promised_downstream->add_rcbuf(name); promised_downstream->add_rcbuf(value); - auto token = http2::lookup_token(namebuf.base, namebuf.len); - promised_req.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, + auto nameref = StringRef{namebuf.base, namebuf.len}; + auto valueref = StringRef{valuebuf.base, valuebuf.len}; + auto token = http2::lookup_token(nameref); + promised_req.fs.add_header_token(nameref, valueref, flags & NGHTTP2_NV_FLAG_NO_INDEX, token); return 0; @@ -1171,7 +1170,8 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream, auto content_length = resp.fs.header(http2::HD_CONTENT_LENGTH); if (content_length) { // libnghttp2 guarantees this can be parsed - resp.fs.content_length = util::parse_uint(content_length->value); + resp.fs.content_length = + util::parse_uint(content_length->value).value_or(-1); } if (resp.fs.content_length == -1 && downstream->expect_response_body()) { @@ -1184,8 +1184,7 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream, // Otherwise, use chunked encoding to keep upstream connection // open. In HTTP2, we are supposed not to receive // transfer-encoding. - resp.fs.add_header_token(StringRef::from_lit("transfer-encoding"), - StringRef::from_lit("chunked"), false, + resp.fs.add_header_token("transfer-encoding"_sr, "chunked"_sr, false, http2::HD_TRANSFER_ENCODING); downstream->set_chunked_response(true); } @@ -2279,7 +2278,7 @@ int Http2Session::handle_downstream_push_promise_complete( } // For server-wide OPTIONS request, path is empty. - if (method_token != HTTP_OPTIONS || path->value != "*") { + if (method_token != HTTP_OPTIONS || path->value != "*"_sr) { promised_req.path = http2::rewrite_clean_path(promised_balloc, path->value); } diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 7816f5f..4c59ddc 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -118,7 +118,7 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http) { std::end(http2_settings)); rv = nghttp2_session_upgrade2( - session_, settings_payload.byte(), settings_payload.size(), + session_, settings_payload.data(), settings_payload.size(), http->get_downstream()->request().method == HTTP_HEAD, nullptr); if (rv != 0) { if (LOG_ENABLED(INFO)) { @@ -209,7 +209,9 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, return 0; } - auto token = http2::lookup_token(namebuf.base, namebuf.len); + auto nameref = StringRef{namebuf.base, namebuf.len}; + auto valueref = StringRef{valuebuf.base, valuebuf.len}; + auto token = http2::lookup_token(nameref); auto no_index = flags & NGHTTP2_NV_FLAG_NO_INDEX; downstream->add_rcbuf(name); @@ -217,15 +219,11 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) { // just store header fields for trailer part - req.fs.add_trailer_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + req.fs.add_trailer_token(nameref, valueref, no_index, token); return 0; } - req.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + req.fs.add_header_token(nameref, valueref, no_index, token); return 0; } } // namespace @@ -322,7 +320,7 @@ int Http2Upstream::on_request_headers(Downstream *downstream, if (LOG_ENABLED(INFO)) { std::stringstream ss; for (auto &nv : nva) { - if (nv.name == "authorization") { + if (nv.name == "authorization"_sr) { ss << TTY_HTTP_HD << nv.name << TTY_RST << ": <redacted>\n"; continue; } @@ -343,7 +341,8 @@ int Http2Upstream::on_request_headers(Downstream *downstream, auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH); if (content_length) { // libnghttp2 guarantees this can be parsed - req.fs.content_length = util::parse_uint(content_length->value); + req.fs.content_length = + util::parse_uint(content_length->value).value_or(-1); } // presence of mandatory header fields are guaranteed by libnghttp2. @@ -385,8 +384,7 @@ int Http2Upstream::on_request_headers(Downstream *downstream, } if (path) { - if (method_token == HTTP_OPTIONS && - path->value == StringRef::from_lit("*")) { + if (method_token == HTTP_OPTIONS && path->value == "*"_sr) { // Server-wide OPTIONS request. Path is empty. } else if (config->http2_proxy && faddr->alt_mode == UpstreamAltMode::NONE) { @@ -399,7 +397,7 @@ int Http2Upstream::on_request_headers(Downstream *downstream, auto connect_proto = req.fs.header(http2::HD__PROTOCOL); if (connect_proto) { - if (connect_proto->value != "websocket") { + if (connect_proto->value != "websocket"_sr) { if (error_reply(downstream, 400) != 0) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } @@ -744,7 +742,7 @@ int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, auto value = make_string_ref(promised_balloc, StringRef{nv.value, nv.valuelen}); - auto token = http2::lookup_token(nv.name, nv.namelen); + auto token = http2::lookup_token(name); switch (token) { case http2::HD__METHOD: req.method = http2::lookup_method_token(value); @@ -1510,10 +1508,16 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body, nghttp2_data_provider2 data_prd, *data_prd_ptr = nullptr; - if (bodylen) { + const auto &req = downstream->request(); + + if (req.method != HTTP_HEAD && bodylen) { data_prd.source.ptr = downstream; data_prd.read_callback = downstream_data_read_callback; data_prd_ptr = &data_prd; + + auto buf = downstream->get_response_buf(); + + buf->append(body, bodylen); } const auto &resp = downstream->response(); @@ -1529,7 +1533,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body, auto response_status = http2::stringify_status(balloc, resp.http_status); - nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); + nva.push_back(http2::make_field(":status"_sr, response_status)); for (auto &kv : headers) { if (kv.name.empty() || kv.name[0] == ':') { @@ -1544,15 +1548,16 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body, case http2::HD_UPGRADE: continue; } - nva.push_back(http2::make_nv_nocopy(kv.name, kv.value, kv.no_index)); + nva.push_back( + http2::make_field(kv.name, kv.value, http2::no_index(kv.no_index))); } if (!resp.fs.header(http2::HD_SERVER)) { - nva.push_back(http2::make_nv_ls_nocopy("server", config->http.server_name)); + nva.push_back(http2::make_field("server"_sr, config->http.server_name)); } for (auto &p : httpconf.add_response_headers) { - nva.push_back(http2::make_nv_nocopy(p.name, p.value)); + nva.push_back(http2::make_field(p.name, p.value)); } rv = nghttp2_submit_response2(session_, downstream->get_stream_id(), @@ -1563,10 +1568,6 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body, return -1; } - auto buf = downstream->get_response_buf(); - - buf->append(body, bodylen); - downstream->set_response_state(DownstreamState::MSG_COMPLETE); if (data_prd_ptr) { @@ -1585,13 +1586,22 @@ int Http2Upstream::error_reply(Downstream *downstream, auto html = http::create_error_html(balloc, status_code); resp.http_status = status_code; - auto body = downstream->get_response_buf(); - body->append(html); - downstream->set_response_state(DownstreamState::MSG_COMPLETE); - nghttp2_data_provider2 data_prd; - data_prd.source.ptr = downstream; - data_prd.read_callback = downstream_data_read_callback; + nghttp2_data_provider2 data_prd, *data_prd_ptr = nullptr; + + const auto &req = downstream->request(); + + if (req.method != HTTP_HEAD) { + data_prd.source.ptr = downstream; + data_prd.read_callback = downstream_data_read_callback; + data_prd_ptr = &data_prd; + + auto body = downstream->get_response_buf(); + + body->append(html); + } + + downstream->set_response_state(DownstreamState::MSG_COMPLETE); auto lgconf = log_config(); lgconf->update_tstamp(std::chrono::system_clock::now()); @@ -1600,15 +1610,15 @@ int Http2Upstream::error_reply(Downstream *downstream, auto content_length = util::make_string_ref_uint(balloc, html.size()); auto date = make_string_ref(balloc, lgconf->tstamp->time_http); - auto nva = std::array<nghttp2_nv, 5>{ - {http2::make_nv_ls_nocopy(":status", response_status), - http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), - http2::make_nv_ls_nocopy("server", get_config()->http.server_name), - http2::make_nv_ls_nocopy("content-length", content_length), - http2::make_nv_ls_nocopy("date", date)}}; + auto nva = std::to_array( + {http2::make_field(":status"_sr, response_status), + http2::make_field("content-type"_sr, "text/html; charset=UTF-8"_sr), + http2::make_field("server"_sr, get_config()->http.server_name), + http2::make_field("content-length"_sr, content_length), + http2::make_field("date"_sr, date)}); rv = nghttp2_submit_response2(session_, downstream->get_stream_id(), - nva.data(), nva.size(), &data_prd); + nva.data(), nva.size(), data_prd_ptr); if (rv < NGHTTP2_ERR_FATAL) { ULOG(FATAL, this) << "nghttp2_submit_response2() failed: " << nghttp2_strerror(rv); @@ -1747,7 +1757,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { if (downstream->get_non_final_response()) { auto response_status = http2::stringify_status(balloc, resp.http_status); - nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); + nva.push_back(http2::make_field(":status"_sr, response_status)); http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), http2::HDOP_STRIP_ALL); @@ -1780,16 +1790,16 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { response_status = http2::stringify_status(balloc, resp.http_status); } - nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); + nva.push_back(http2::make_field(":status"_sr, response_status)); http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), striphd_flags); if (!config->http2_proxy && !httpconf.no_server_rewrite) { - nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name)); + nva.push_back(http2::make_field("server"_sr, httpconf.server_name)); } else { auto server = resp.fs.header(http2::HD_SERVER); if (server) { - nva.push_back(http2::make_nv_ls_nocopy("server", (*server).value)); + nva.push_back(http2::make_field("server"_sr, (*server).value)); } } @@ -1805,22 +1815,22 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { http::require_cookie_secure_attribute(cookieconf.secure, req.scheme); auto cookie_str = http::create_affinity_cookie( balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure); - nva.push_back(http2::make_nv_ls_nocopy("set-cookie", cookie_str)); + nva.push_back(http2::make_field("set-cookie"_sr, cookie_str)); } } if (!resp.fs.header(http2::HD_ALT_SVC)) { // We won't change or alter alt-svc from backend for now if (!httpconf.http2_altsvc_header_value.empty()) { - nva.push_back(http2::make_nv_ls_nocopy( - "alt-svc", httpconf.http2_altsvc_header_value)); + nva.push_back( + http2::make_field("alt-svc"_sr, httpconf.http2_altsvc_header_value)); } } auto via = resp.fs.header(http2::HD_VIA); if (httpconf.no_via) { if (via) { - nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); + nva.push_back(http2::make_field("via"_sr, (*via).value)); } } else { // we don't create more than 16 bytes in @@ -1831,7 +1841,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); if (via) { p = std::copy(std::begin(via->value), std::end(via->value), p); p = util::copy_lit(p, ", "); @@ -1839,17 +1849,18 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { p = http::create_via_header_value(p, resp.http_major, resp.http_minor); *p = '\0'; - nva.push_back(http2::make_nv_ls_nocopy("via", StringRef{iov.base, p})); + nva.push_back( + http2::make_field("via"_sr, StringRef{std::span{std::begin(iov), p}})); } for (auto &p : httpconf.add_response_headers) { - nva.push_back(http2::make_nv_nocopy(p.name, p.value)); + nva.push_back(http2::make_field(p.name, p.value)); } if (downstream->get_stream_id() % 2 == 0) { // This header field is basically for human on client side to // figure out that the resource is pushed. - nva.push_back(http2::make_nv_ll("x-http2-push", "1")); + nva.push_back(http2::make_field("x-http2-push"_sr, "1"_sr)); } if (LOG_ENABLED(INFO)) { @@ -1993,7 +2004,7 @@ int Http2Upstream::on_downstream_abort_request_with_https_redirect( int Http2Upstream::redirect_to_https(Downstream *downstream) { auto &req = downstream->request(); - if (req.regular_connect_method() || req.scheme != "http") { + if (req.regular_connect_method() || req.scheme != "http"_sr) { return error_reply(downstream, 400); } @@ -2007,19 +2018,16 @@ int Http2Upstream::redirect_to_https(Downstream *downstream) { auto &httpconf = config->http; StringRef loc; - if (httpconf.redirect_https_port == StringRef::from_lit("443")) { - loc = concat_string_ref(balloc, StringRef::from_lit("https://"), authority, - req.path); + if (httpconf.redirect_https_port == "443"_sr) { + loc = concat_string_ref(balloc, "https://"_sr, authority, req.path); } else { - loc = concat_string_ref(balloc, StringRef::from_lit("https://"), authority, - StringRef::from_lit(":"), + loc = concat_string_ref(balloc, "https://"_sr, authority, ":"_sr, httpconf.redirect_https_port, req.path); } auto &resp = downstream->response(); resp.http_status = 308; - resp.fs.add_header_token(StringRef::from_lit("location"), loc, false, - http2::HD_LOCATION); + resp.fs.add_header_token("location"_sr, loc, false, http2::HD_LOCATION); return send_reply(downstream, nullptr, 0); } @@ -2216,10 +2224,10 @@ int Http2Upstream::submit_push_promise(const StringRef &scheme, nva.reserve(4 + req.fs.headers().size()); // just use "GET" for now - nva.push_back(http2::make_nv_ll(":method", "GET")); - nva.push_back(http2::make_nv_ls_nocopy(":scheme", scheme)); - nva.push_back(http2::make_nv_ls_nocopy(":path", path)); - nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); + nva.push_back(http2::make_field(":method"_sr, "GET"_sr)); + nva.push_back(http2::make_field(":scheme"_sr, scheme)); + nva.push_back(http2::make_field(":path"_sr, path)); + nva.push_back(http2::make_field(":authority"_sr, authority)); for (auto &kv : req.fs.headers()) { switch (kv.token) { @@ -2234,7 +2242,8 @@ int Http2Upstream::submit_push_promise(const StringRef &scheme, case http2::HD_CACHE_CONTROL: case http2::HD_HOST: case http2::HD_USER_AGENT: - nva.push_back(http2::make_nv_nocopy(kv.name, kv.value, kv.no_index)); + nva.push_back( + http2::make_field(kv.name, kv.value, http2::no_index(kv.no_index))); break; } } @@ -2378,7 +2387,8 @@ int Http2Upstream::on_downstream_push_promise_complete( nva.reserve(headers.size()); for (auto &kv : headers) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + nva.push_back( + http2::make_field_nv(kv.name, kv.value, http2::no_index(kv.no_index))); } auto promised_stream_id = nghttp2_submit_push_promise( diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index d12d2da..0be846d 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -120,6 +120,9 @@ Http3Upstream::Http3Upstream(ClientHandler *handler) !get_config()->http2_proxy}, tx_{ .data = std::unique_ptr<uint8_t[]>(new uint8_t[64_k]), +#ifndef UDP_SEGMENT + .no_gso = true, +#endif // UDP_SEGMENT } { auto conn = handler_->get_connection(); conn->conn_ref.get_conn = shrpx::get_conn; @@ -273,7 +276,7 @@ int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, void *user_data, void *stream_user_data) { auto upstream = static_cast<Http3Upstream *>(user_data); - if (upstream->recv_stream_data(flags, stream_id, data, datalen) != 0) { + if (upstream->recv_stream_data(flags, stream_id, {data, datalen}) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -282,11 +285,12 @@ int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, } // namespace int Http3Upstream::recv_stream_data(uint32_t flags, int64_t stream_id, - const uint8_t *data, size_t datalen) { + std::span<const uint8_t> data) { assert(httpconn_); - auto nconsumed = nghttp3_conn_read_stream( - httpconn_, stream_id, data, datalen, flags & NGTCP2_STREAM_DATA_FLAG_FIN); + auto nconsumed = + nghttp3_conn_read_stream(httpconn_, stream_id, data.data(), data.size(), + flags & NGTCP2_STREAM_DATA_FLAG_FIN); if (nconsumed < 0) { ULOG(ERROR, this) << "nghttp3_conn_read_stream: " << nghttp3_strerror(nconsumed); @@ -506,25 +510,22 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, } // namespace int Http3Upstream::send_new_token(const ngtcp2_addr *remote_addr) { - std::array<uint8_t, NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN + 1> token; - size_t tokenlen; - auto worker = handler_->get_worker(); auto conn_handler = worker->get_connection_handler(); auto &qkms = conn_handler->get_quic_keying_materials(); auto &qkm = qkms->keying_materials.front(); - if (generate_token(token.data(), tokenlen, remote_addr->addr, - remote_addr->addrlen, qkm.secret.data(), - qkm.secret.size()) != 0) { + std::array<uint8_t, NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN + 1> tokenbuf; + + auto token = generate_token(tokenbuf, remote_addr->addr, remote_addr->addrlen, + qkm.secret, qkm.id); + if (!token) { return -1; } - assert(tokenlen == NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN); - - token[tokenlen++] = qkm.id; + assert(token->size() == NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN + 1); - auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), tokenlen); + auto rv = ngtcp2_conn_submit_new_token(conn_, token->data(), token->size()); if (rv != 0) { ULOG(ERROR, this) << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv); @@ -553,8 +554,8 @@ int recv_tx_key(ngtcp2_conn *conn, ngtcp2_encryption_level level, int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_hd &initial_hd, - const ngtcp2_cid *odcid, const uint8_t *token, - size_t tokenlen, ngtcp2_token_type token_type) { + const ngtcp2_cid *odcid, std::span<const uint8_t> token, + ngtcp2_token_type token_type) { int rv; auto worker = handler_->get_worker(); @@ -637,8 +638,8 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, settings.max_window = http3conf.upstream.max_connection_window_size; settings.max_stream_window = http3conf.upstream.max_window_size; settings.rand_ctx.native_handle = &worker->get_randgen(); - settings.token = token; - settings.tokenlen = tokenlen; + settings.token = token.data(); + settings.tokenlen = token.size(); settings.token_type = token_type; settings.initial_pkt_num = std::uniform_int_distribution<uint32_t>( 0, std::numeric_limits<int32_t>::max())(worker->get_randgen()); @@ -779,17 +780,14 @@ int Http3Upstream::on_write() { int Http3Upstream::write_streams() { std::array<nghttp3_vec, 16> vec; auto max_udp_payload_size = ngtcp2_conn_get_max_tx_udp_payload_size(conn_); -#ifdef UDP_SEGMENT auto path_max_udp_payload_size = ngtcp2_conn_get_path_max_tx_udp_payload_size(conn_); -#endif // UDP_SEGMENT - auto max_pktcnt = - std::max(ngtcp2_conn_get_send_quantum(conn_) / max_udp_payload_size, - static_cast<size_t>(1)); ngtcp2_pkt_info pi, prev_pi; - uint8_t *bufpos = tx_.data.get(); + auto txbuf = + std::span{tx_.data.get(), std::max(ngtcp2_conn_get_send_quantum(conn_), + path_max_udp_payload_size)}; + auto buf = txbuf; ngtcp2_path_storage ps, prev_ps; - size_t pktcnt = 0; int rv; size_t gso_size = 0; auto ts = quic_timestamp(); @@ -824,9 +822,12 @@ int Http3Upstream::write_streams() { flags |= NGTCP2_WRITE_STREAM_FLAG_FIN; } + auto buflen = buf.size() >= max_udp_payload_size + ? max_udp_payload_size + : path_max_udp_payload_size; auto nwrite = ngtcp2_conn_writev_stream( - conn_, &ps.path, &pi, bufpos, max_udp_payload_size, &ndatalen, flags, - stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt, ts); + conn_, &ps.path, &pi, buf.data(), buflen, &ndatalen, flags, stream_id, + reinterpret_cast<const ngtcp2_vec *>(v), vcnt, ts); if (nwrite < 0) { switch (nwrite) { case NGTCP2_ERR_STREAM_DATA_BLOCKED: @@ -872,18 +873,17 @@ int Http3Upstream::write_streams() { } if (nwrite == 0) { - if (bufpos - tx_.data.get()) { + auto data = std::span{std::begin(txbuf), std::begin(buf)}; + if (!data.empty()) { auto faddr = static_cast<UpstreamAddr *>(prev_ps.path.user_data); - auto data = tx_.data.get(); - auto datalen = bufpos - data; - rv = send_packet(faddr, prev_ps.path.remote.addr, - prev_ps.path.remote.addrlen, prev_ps.path.local.addr, - prev_ps.path.local.addrlen, prev_pi, data, datalen, - gso_size); + auto [rest, rv] = + send_packet(faddr, prev_ps.path.remote.addr, + prev_ps.path.remote.addrlen, prev_ps.path.local.addr, + prev_ps.path.local.addrlen, prev_pi, data, gso_size); if (rv == SHRPX_ERR_SEND_BLOCKED) { on_send_blocked(faddr, prev_ps.path.remote, prev_ps.path.local, - prev_pi, data, datalen, gso_size); + prev_pi, rest, gso_size); signal_write_upstream_addr(faddr); } @@ -894,10 +894,11 @@ int Http3Upstream::write_streams() { return 0; } - bufpos += nwrite; + auto last_pkt = std::begin(buf); + + buf = buf.subspan(nwrite); -#ifdef UDP_SEGMENT - if (pktcnt == 0) { + if (last_pkt == std::begin(txbuf)) { ngtcp2_path_copy(&prev_ps.path, &ps.path); prev_pi = pi; gso_size = nwrite; @@ -907,35 +908,36 @@ int Http3Upstream::write_streams() { (gso_size > path_max_udp_payload_size && static_cast<size_t>(nwrite) != gso_size)) { auto faddr = static_cast<UpstreamAddr *>(prev_ps.path.user_data); - auto data = tx_.data.get(); - auto datalen = bufpos - data - nwrite; + auto data = std::span{std::begin(txbuf), last_pkt}; - rv = send_packet(faddr, prev_ps.path.remote.addr, - prev_ps.path.remote.addrlen, prev_ps.path.local.addr, - prev_ps.path.local.addrlen, prev_pi, data, datalen, - gso_size); + auto [rest, rv] = + send_packet(faddr, prev_ps.path.remote.addr, + prev_ps.path.remote.addrlen, prev_ps.path.local.addr, + prev_ps.path.local.addrlen, prev_pi, data, gso_size); switch (rv) { case SHRPX_ERR_SEND_BLOCKED: on_send_blocked(faddr, prev_ps.path.remote, prev_ps.path.local, prev_pi, - data, datalen, gso_size); + rest, gso_size); + data = std::span{last_pkt, std::begin(buf)}; on_send_blocked(static_cast<UpstreamAddr *>(ps.path.user_data), - ps.path.remote, ps.path.local, pi, bufpos - nwrite, - nwrite, 0); + ps.path.remote, ps.path.local, pi, data, data.size()); signal_write_upstream_addr(faddr); break; default: { auto faddr = static_cast<UpstreamAddr *>(ps.path.user_data); - auto data = bufpos - nwrite; + auto data = std::span{last_pkt, std::begin(buf)}; - rv = send_packet(faddr, ps.path.remote.addr, ps.path.remote.addrlen, - ps.path.local.addr, ps.path.local.addrlen, pi, data, - nwrite, 0); + auto [rest, rv] = send_packet( + faddr, ps.path.remote.addr, ps.path.remote.addrlen, + ps.path.local.addr, ps.path.local.addrlen, pi, data, data.size()); if (rv == SHRPX_ERR_SEND_BLOCKED) { - on_send_blocked(faddr, ps.path.remote, ps.path.local, pi, data, - nwrite, 0); + assert(rest.size() == data.size()); + + on_send_blocked(faddr, ps.path.remote, ps.path.local, pi, rest, + rest.size()); signal_write_upstream_addr(faddr); } @@ -947,16 +949,16 @@ int Http3Upstream::write_streams() { return 0; } - if (++pktcnt == max_pktcnt || static_cast<size_t>(nwrite) < gso_size) { + if (buf.size() < path_max_udp_payload_size || + static_cast<size_t>(nwrite) < gso_size) { auto faddr = static_cast<UpstreamAddr *>(ps.path.user_data); - auto data = tx_.data.get(); - auto datalen = bufpos - data; + auto data = std::span{std::begin(txbuf), std::begin(buf)}; - rv = send_packet(faddr, ps.path.remote.addr, ps.path.remote.addrlen, - ps.path.local.addr, ps.path.local.addrlen, pi, data, - datalen, gso_size); + auto [rest, rv] = send_packet(faddr, ps.path.remote.addr, + ps.path.remote.addrlen, ps.path.local.addr, + ps.path.local.addrlen, pi, data, gso_size); if (rv == SHRPX_ERR_SEND_BLOCKED) { - on_send_blocked(faddr, ps.path.remote, ps.path.local, pi, data, datalen, + on_send_blocked(faddr, ps.path.remote, ps.path.local, pi, rest, gso_size); signal_write_upstream_addr(faddr); @@ -966,33 +968,6 @@ int Http3Upstream::write_streams() { return 0; } -#else // !UDP_SEGMENT - auto faddr = static_cast<UpstreamAddr *>(ps.path.user_data); - auto data = tx_.data.get(); - auto datalen = bufpos - data; - - rv = send_packet(faddr, ps.path.remote.addr, ps.path.remote.addrlen, - ps.path.local.addr, ps.path.local.addrlen, pi, data, - datalen, 0); - if (rv == SHRPX_ERR_SEND_BLOCKED) { - on_send_blocked(faddr, ps.path.remote, ps.path.local, pi, data, datalen, - 0); - - ngtcp2_conn_update_pkt_tx_time(conn_, ts); - - signal_write_upstream_addr(faddr); - - return 0; - } - - if (++pktcnt == max_pktcnt) { - ngtcp2_conn_update_pkt_tx_time(conn_, ts); - - return 0; - } - - bufpos = tx_.data.get(); -#endif // !UDP_SEGMENT } return 0; @@ -1329,7 +1304,7 @@ int Http3Upstream::on_downstream_header_complete(Downstream *downstream) { if (downstream->get_non_final_response()) { auto response_status = http2::stringify_status(balloc, resp.http_status); - nva.push_back(http3::make_nv_ls_nocopy(":status", response_status)); + nva.push_back(http3::make_field(":status"_sr, response_status)); http3::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), http2::HDOP_STRIP_ALL); @@ -1361,16 +1336,16 @@ int Http3Upstream::on_downstream_header_complete(Downstream *downstream) { response_status = http2::stringify_status(balloc, resp.http_status); } - nva.push_back(http3::make_nv_ls_nocopy(":status", response_status)); + nva.push_back(http3::make_field(":status"_sr, response_status)); http3::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), striphd_flags); if (!config->http2_proxy && !httpconf.no_server_rewrite) { - nva.push_back(http3::make_nv_ls_nocopy("server", httpconf.server_name)); + nva.push_back(http3::make_field("server"_sr, httpconf.server_name)); } else { auto server = resp.fs.header(http2::HD_SERVER); if (server) { - nva.push_back(http3::make_nv_ls_nocopy("server", (*server).value)); + nva.push_back(http3::make_field("server"_sr, (*server).value)); } } @@ -1386,14 +1361,14 @@ int Http3Upstream::on_downstream_header_complete(Downstream *downstream) { http::require_cookie_secure_attribute(cookieconf.secure, req.scheme); auto cookie_str = http::create_affinity_cookie( balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure); - nva.push_back(http3::make_nv_ls_nocopy("set-cookie", cookie_str)); + nva.push_back(http3::make_field("set-cookie"_sr, cookie_str)); } } auto via = resp.fs.header(http2::HD_VIA); if (httpconf.no_via) { if (via) { - nva.push_back(http3::make_nv_ls_nocopy("via", (*via).value)); + nva.push_back(http3::make_field("via"_sr, (*via).value)); } } else { // we don't create more than 16 bytes in @@ -1404,7 +1379,7 @@ int Http3Upstream::on_downstream_header_complete(Downstream *downstream) { } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); if (via) { p = std::copy(std::begin(via->value), std::end(via->value), p); p = util::copy_lit(p, ", "); @@ -1412,11 +1387,12 @@ int Http3Upstream::on_downstream_header_complete(Downstream *downstream) { p = http::create_via_header_value(p, resp.http_major, resp.http_minor); *p = '\0'; - nva.push_back(http3::make_nv_ls_nocopy("via", StringRef{iov.base, p})); + nva.push_back( + http3::make_field("via"_sr, StringRef{std::span{std::begin(iov), p}})); } for (auto &p : httpconf.add_response_headers) { - nva.push_back(http3::make_nv_nocopy(p.name, p.value)); + nva.push_back(http3::make_field(p.name, p.value)); } if (LOG_ENABLED(INFO)) { @@ -1582,7 +1558,7 @@ void Http3Upstream::on_handler_delete() { send_packet(static_cast<UpstreamAddr *>(ps.path.user_data), ps.path.remote.addr, ps.path.remote.addrlen, ps.path.local.addr, - ps.path.local.addrlen, pi, conn_close_.data(), nwrite, 0); + ps.path.local.addrlen, pi, conn_close_, conn_close_.size()); } auto d = @@ -1700,9 +1676,15 @@ int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body, nghttp3_data_reader data_read, *data_read_ptr = nullptr; - if (bodylen) { + const auto &req = downstream->request(); + + if (req.method != HTTP_HEAD && bodylen) { data_read.read_data = downstream_read_data_callback; data_read_ptr = &data_read; + + auto buf = downstream->get_response_buf(); + + buf->append(body, bodylen); } const auto &resp = downstream->response(); @@ -1718,7 +1700,7 @@ int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body, auto response_status = http2::stringify_status(balloc, resp.http_status); - nva.push_back(http3::make_nv_ls_nocopy(":status", response_status)); + nva.push_back(http3::make_field(":status"_sr, response_status)); for (auto &kv : headers) { if (kv.name.empty() || kv.name[0] == ':') { @@ -1733,15 +1715,16 @@ int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body, case http2::HD_UPGRADE: continue; } - nva.push_back(http3::make_nv_nocopy(kv.name, kv.value, kv.no_index)); + nva.push_back( + http3::make_field(kv.name, kv.value, http3::never_index(kv.no_index))); } if (!resp.fs.header(http2::HD_SERVER)) { - nva.push_back(http3::make_nv_ls_nocopy("server", config->http.server_name)); + nva.push_back(http3::make_field("server"_sr, config->http.server_name)); } for (auto &p : httpconf.add_response_headers) { - nva.push_back(http3::make_nv_nocopy(p.name, p.value)); + nva.push_back(http3::make_field(p.name, p.value)); } rv = nghttp3_conn_submit_response(httpconn_, downstream->get_stream_id(), @@ -1752,10 +1735,6 @@ int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body, return -1; } - auto buf = downstream->get_response_buf(); - - buf->append(body, bodylen); - downstream->set_response_state(DownstreamState::MSG_COMPLETE); if (data_read_ptr) { @@ -1801,7 +1780,7 @@ void Http3Upstream::cancel_premature_downstream( int Http3Upstream::on_read(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen) { + std::span<const uint8_t> data) { int rv; auto path = ngtcp2_path{ @@ -1816,7 +1795,8 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, const_cast<UpstreamAddr *>(faddr), }; - rv = ngtcp2_conn_read_pkt(conn_, &path, &pi, data, datalen, quic_timestamp()); + rv = ngtcp2_conn_read_pkt(conn_, &path, &pi, data.data(), data.size(), + quic_timestamp()); if (rv != 0) { switch (rv) { case NGTCP2_ERR_DRAINING: @@ -1834,8 +1814,8 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, ngtcp2_version_cid vc; - rv = - ngtcp2_pkt_decode_version_cid(&vc, data, datalen, SHRPX_QUIC_SCIDLEN); + rv = ngtcp2_pkt_decode_version_cid(&vc, data.data(), data.size(), + SHRPX_QUIC_SCIDLEN); if (rv != 0) { return -1; } @@ -1843,9 +1823,9 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, // Overwrite error if any is set ngtcp2_ccerr_set_liberr(&last_error_, rv, nullptr, 0); - quic_conn_handler->send_retry(handler_->get_upstream_addr(), vc.version, - vc.dcid, vc.dcidlen, vc.scid, vc.scidlen, - remote_addr, local_addr, datalen * 3); + quic_conn_handler->send_retry( + handler_->get_upstream_addr(), vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, data.size() * 3); return -1; } @@ -1874,16 +1854,40 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, return 0; } -int Http3Upstream::send_packet(const UpstreamAddr *faddr, - const sockaddr *remote_sa, size_t remote_salen, - const sockaddr *local_sa, size_t local_salen, - const ngtcp2_pkt_info &pi, const uint8_t *data, - size_t datalen, size_t gso_size) { +std::pair<std::span<const uint8_t>, int> +Http3Upstream::send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, + size_t remote_salen, const sockaddr *local_sa, + size_t local_salen, const ngtcp2_pkt_info &pi, + std::span<const uint8_t> data, size_t gso_size) { + if (tx_.no_gso) { + for (; !data.empty();) { + auto len = std::min(gso_size, data.size()); + auto rv = + quic_send_packet(faddr, remote_sa, remote_salen, local_sa, + local_salen, pi, {std::begin(data), len}, gso_size); + if (rv != 0) { + switch (rv) { + case -EAGAIN: +#if EAGAIN != EWOULDBLOCK + case -EWOULDBLOCK: +#endif // EAGAIN != EWOULDBLOCK + return {data, SHRPX_ERR_SEND_BLOCKED}; + default: + return {data, -1}; + } + } + + data = data.subspan(len); + } + + return {{}, 0}; + } + auto rv = quic_send_packet(faddr, remote_sa, remote_salen, local_sa, - local_salen, pi, data, datalen, gso_size); + local_salen, pi, data, gso_size); switch (rv) { case 0: - return 0; + return {{}, 0}; // With GSO, sendmsg may fail with EINVAL if UDP payload is too // large. case -EINVAL: @@ -1894,22 +1898,32 @@ int Http3Upstream::send_packet(const UpstreamAddr *faddr, #if EAGAIN != EWOULDBLOCK case -EWOULDBLOCK: #endif // EAGAIN != EWOULDBLOCK - return SHRPX_ERR_SEND_BLOCKED; + return {data, SHRPX_ERR_SEND_BLOCKED}; + case -EIO: + if (tx_.no_gso) { + break; + } + + tx_.no_gso = true; + + return send_packet(faddr, remote_sa, remote_salen, local_sa, local_salen, + pi, data, gso_size); default: break; } - return -1; + return {{}, -1}; } void Http3Upstream::on_send_blocked(const UpstreamAddr *faddr, const ngtcp2_addr &remote_addr, const ngtcp2_addr &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen, + std::span<const uint8_t> data, size_t gso_size) { assert(tx_.num_blocked || !tx_.send_blocked); assert(tx_.num_blocked < 2); + assert(gso_size); tx_.send_blocked = true; @@ -1923,22 +1937,21 @@ void Http3Upstream::on_send_blocked(const UpstreamAddr *faddr, p.faddr = faddr; p.pi = pi; p.data = data; - p.datalen = datalen; p.gso_size = gso_size; } int Http3Upstream::send_blocked_packet() { - int rv; - assert(tx_.send_blocked); for (; tx_.num_blocked_sent < tx_.num_blocked; ++tx_.num_blocked_sent) { auto &p = tx_.blocked[tx_.num_blocked_sent]; - rv = send_packet(p.faddr, &p.remote_addr.su.sa, p.remote_addr.len, - &p.local_addr.su.sa, p.local_addr.len, p.pi, p.data, - p.datalen, p.gso_size); + auto [rest, rv] = send_packet(p.faddr, &p.remote_addr.su.sa, + p.remote_addr.len, &p.local_addr.su.sa, + p.local_addr.len, p.pi, p.data, p.gso_size); if (rv == SHRPX_ERR_SEND_BLOCKED) { + p.data = rest; + signal_write_upstream_addr(p.faddr); return 0; @@ -1998,7 +2011,7 @@ int Http3Upstream::handle_error() { send_packet(static_cast<UpstreamAddr *>(ps.path.user_data), ps.path.remote.addr, ps.path.remote.addrlen, ps.path.local.addr, - ps.path.local.addrlen, pi, conn_close_.data(), nwrite, 0); + ps.path.local.addrlen, pi, conn_close_, conn_close_.size()); return -1; } @@ -2185,22 +2198,20 @@ int Http3Upstream::http_recv_request_header(Downstream *downstream, return 0; } - auto token = http2::lookup_token(namebuf.base, namebuf.len); + auto nameref = StringRef{namebuf.base, namebuf.len}; + auto valueref = StringRef{valuebuf.base, valuebuf.len}; + auto token = http2::lookup_token(nameref); auto no_index = flags & NGHTTP3_NV_FLAG_NEVER_INDEX; downstream->add_rcbuf(name); downstream->add_rcbuf(value); if (trailer) { - req.fs.add_trailer_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + req.fs.add_trailer_token(nameref, valueref, no_index, token); return 0; } - req.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + req.fs.add_header_token(nameref, valueref, no_index, token); return 0; } @@ -2240,7 +2251,7 @@ int Http3Upstream::http_end_request_headers(Downstream *downstream, int fin) { if (LOG_ENABLED(INFO)) { std::stringstream ss; for (auto &nv : nva) { - if (nv.name == "authorization") { + if (nv.name == "authorization"_sr) { ss << TTY_HTTP_HD << nv.name << TTY_RST << ": <redacted>\n"; continue; } @@ -2254,7 +2265,8 @@ int Http3Upstream::http_end_request_headers(Downstream *downstream, int fin) { auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH); if (content_length) { // libnghttp3 guarantees this can be parsed - req.fs.content_length = util::parse_uint(content_length->value); + req.fs.content_length = + util::parse_uint(content_length->value).value_or(-1); } // presence of mandatory header fields are guaranteed by libnghttp3. @@ -2298,8 +2310,7 @@ int Http3Upstream::http_end_request_headers(Downstream *downstream, int fin) { } if (path) { - if (method_token == HTTP_OPTIONS && - path->value == StringRef::from_lit("*")) { + if (method_token == HTTP_OPTIONS && path->value == "*"_sr) { // Server-wide OPTIONS request. Path is empty. } else if (config->http2_proxy && faddr->alt_mode == UpstreamAltMode::NONE) { @@ -2312,7 +2323,7 @@ int Http3Upstream::http_end_request_headers(Downstream *downstream, int fin) { auto connect_proto = req.fs.header(http2::HD__PROTOCOL); if (connect_proto) { - if (connect_proto->value != "websocket") { + if (connect_proto->value != "websocket"_sr) { if (error_reply(downstream, 400) != 0) { return -1; } @@ -2452,7 +2463,7 @@ int http_recv_data(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data, auto upstream = static_cast<Http3Upstream *>(user_data); auto downstream = static_cast<Downstream *>(stream_user_data); - if (upstream->http_recv_data(downstream, data, datalen) != 0) { + if (upstream->http_recv_data(downstream, {data, datalen}) != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; } @@ -2460,16 +2471,16 @@ int http_recv_data(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data, } } // namespace -int Http3Upstream::http_recv_data(Downstream *downstream, const uint8_t *data, - size_t datalen) { +int Http3Upstream::http_recv_data(Downstream *downstream, + std::span<const uint8_t> data) { downstream->reset_upstream_rtimer(); - if (downstream->push_upload_data_chunk(data, datalen) != 0) { + if (downstream->push_upload_data_chunk(data.data(), data.size()) != 0) { if (downstream->get_response_state() != DownstreamState::MSG_COMPLETE) { shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR); } - consume(downstream->get_stream_id(), datalen); + consume(downstream->get_stream_id(), data.size()); return 0; } @@ -2724,12 +2735,21 @@ int Http3Upstream::error_reply(Downstream *downstream, auto html = http::create_error_html(balloc, status_code); resp.http_status = status_code; - auto body = downstream->get_response_buf(); - body->append(html); - downstream->set_response_state(DownstreamState::MSG_COMPLETE); - nghttp3_data_reader data_read; - data_read.read_data = downstream_read_data_callback; + nghttp3_data_reader data_read, *data_read_ptr = nullptr; + + const auto &req = downstream->request(); + + if (req.method != HTTP_HEAD) { + data_read.read_data = downstream_read_data_callback; + data_read_ptr = &data_read; + + auto body = downstream->get_response_buf(); + + body->append(html); + } + + downstream->set_response_state(DownstreamState::MSG_COMPLETE); auto lgconf = log_config(); lgconf->update_tstamp(std::chrono::system_clock::now()); @@ -2738,15 +2758,15 @@ int Http3Upstream::error_reply(Downstream *downstream, auto content_length = util::make_string_ref_uint(balloc, html.size()); auto date = make_string_ref(balloc, lgconf->tstamp->time_http); - auto nva = std::array<nghttp3_nv, 5>{ - {http3::make_nv_ls_nocopy(":status", response_status), - http3::make_nv_ll("content-type", "text/html; charset=UTF-8"), - http3::make_nv_ls_nocopy("server", get_config()->http.server_name), - http3::make_nv_ls_nocopy("content-length", content_length), - http3::make_nv_ls_nocopy("date", date)}}; + auto nva = std::to_array( + {http3::make_field(":status"_sr, response_status), + http3::make_field("content-type"_sr, "text/html; charset=UTF-8"_sr), + http3::make_field("server"_sr, get_config()->http.server_name), + http3::make_field("content-length"_sr, content_length), + http3::make_field("date"_sr, date)}); rv = nghttp3_conn_submit_response(httpconn_, downstream->get_stream_id(), - nva.data(), nva.size(), &data_read); + nva.data(), nva.size(), data_read_ptr); if (nghttp3_err_is_fatal(rv)) { ULOG(FATAL, this) << "nghttp3_conn_submit_response() failed: " << nghttp3_strerror(rv); @@ -2891,12 +2911,12 @@ int Http3Upstream::open_qlog_file(const StringRef &dir, const ngtcp2_cid &scid) const { std::array<char, sizeof("20141115T125824.741+0900")> buf; - auto path = dir.str(); + auto path = std::string{dir}; path += '/'; path += util::format_iso8601_basic(buf.data(), std::chrono::system_clock::now()); path += '-'; - path += util::format_hex(scid.data, scid.datalen); + path += util::format_hex(std::span{scid.data, scid.datalen}); path += ".sqlog"; int fd; diff --git a/src/shrpx_http3_upstream.h b/src/shrpx_http3_upstream.h index 53c73ae..ef0fcb4 100644 --- a/src/shrpx_http3_upstream.h +++ b/src/shrpx_http3_upstream.h @@ -89,12 +89,12 @@ public: int init(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_hd &initial_hd, - const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, + const ngtcp2_cid *odcid, std::span<const uint8_t> token, ngtcp2_token_type token_type); int on_read(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen); + std::span<const uint8_t> data); int write_streams(); @@ -105,8 +105,8 @@ public: int setup_httpconn(); void add_pending_downstream(std::unique_ptr<Downstream> downstream); - int recv_stream_data(uint32_t flags, int64_t stream_id, const uint8_t *data, - size_t datalen); + int recv_stream_data(uint32_t flags, int64_t stream_id, + std::span<const uint8_t> data); int acked_stream_data_offset(int64_t stream_id, uint64_t datalen); int extend_max_stream_data(int64_t stream_id); void extend_max_remote_streams_bidi(uint64_t max_streams); @@ -131,16 +131,16 @@ public: int http_shutdown_stream_read(int64_t stream_id); int http_reset_stream(int64_t stream_id, uint64_t app_error_code); int http_stop_sending(int64_t stream_id, uint64_t app_error_code); - int http_recv_data(Downstream *downstream, const uint8_t *data, - size_t datalen); + int http_recv_data(Downstream *downstream, std::span<const uint8_t> data); int handshake_completed(); int check_shutdown(); int start_graceful_shutdown(); int submit_goaway(); - int send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, - size_t remote_salen, const sockaddr *local_sa, - size_t local_salen, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen, size_t gso_size); + std::pair<std::span<const uint8_t>, int> + send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, + size_t remote_salen, const sockaddr *local_sa, size_t local_salen, + const ngtcp2_pkt_info &pi, std::span<const uint8_t> data, + size_t gso_size); void qlog_write(const void *data, size_t datalen, bool fin); int open_qlog_file(const StringRef &dir, const ngtcp2_cid &scid) const; @@ -148,7 +148,7 @@ public: void on_send_blocked(const UpstreamAddr *faddr, const ngtcp2_addr &remote_addr, const ngtcp2_addr &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen, size_t gso_size); + std::span<const uint8_t> data, size_t gso_size); int send_blocked_packet(); void signal_write_upstream_addr(const UpstreamAddr *faddr); @@ -179,11 +179,11 @@ private: Address local_addr; Address remote_addr; ngtcp2_pkt_info pi; - const uint8_t *data; - size_t datalen; + std::span<const uint8_t> data; size_t gso_size; } blocked[2]; std::unique_ptr<uint8_t[]> data; + bool no_gso; } tx_; }; diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index 4164b8b..8031098 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -425,8 +425,8 @@ int HttpDownstreamConnection::initiate_connection() { auto sni_name = addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni}; - if (!util::numeric_host(sni_name.c_str())) { - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str()); + if (!util::numeric_host(sni_name.data())) { + SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.data()); } auto session = tls::reuse_tls_session(addr_->tls_session_cache); @@ -564,9 +564,10 @@ int HttpDownstreamConnection::push_request_headers() { return -1; } auto iov = make_byte_ref(balloc, base64::encode_length(nonce.size()) + 1); - auto p = base64::encode(std::begin(nonce), std::end(nonce), iov.base); + auto p = + base64::encode(std::begin(nonce), std::end(nonce), std::begin(iov)); *p = '\0'; - auto key = StringRef{iov.base, p}; + auto key = StringRef{std::span{std::begin(iov), p}}; downstream_->set_ws_key(key); buf->append("Sec-Websocket-Key: "); diff --git a/src/shrpx_http_test.cc b/src/shrpx_http_test.cc index f753ec8..8bc3e2e 100644 --- a/src/shrpx_http_test.cc +++ b/src/shrpx_http_test.cc @@ -36,6 +36,8 @@ #include "shrpx_config.h" #include "shrpx_log.h" +using namespace std::literals; + namespace shrpx { namespace { @@ -56,47 +58,34 @@ const MunitSuite http_suite{ void test_shrpx_http_create_forwarded(void) { BlockAllocator balloc(1024, 1024); - assert_stdstring_equal( + assert_stdsv_equal( "by=\"example.com:3000\";for=\"[::1]\";host=\"www.example.com\";" - "proto=https", + "proto=https"sv, http::create_forwarded( balloc, FORWARDED_BY | FORWARDED_FOR | FORWARDED_HOST | FORWARDED_PROTO, - StringRef::from_lit("example.com:3000"), StringRef::from_lit("[::1]"), - StringRef::from_lit("www.example.com"), StringRef::from_lit("https")) - .str()); - - assert_stdstring_equal( - "for=192.168.0.1", - http::create_forwarded( - balloc, FORWARDED_FOR, StringRef::from_lit("alpha"), - StringRef::from_lit("192.168.0.1"), StringRef::from_lit("bravo"), - StringRef::from_lit("charlie")) - .str()); - - assert_stdstring_equal( - "by=_hidden;for=\"[::1]\"", - http::create_forwarded(balloc, FORWARDED_BY | FORWARDED_FOR, - StringRef::from_lit("_hidden"), - StringRef::from_lit("[::1]"), - StringRef::from_lit(""), StringRef::from_lit("")) - .str()); - - assert_stdstring_equal( - "by=\"[::1]\";for=_hidden", - http::create_forwarded(balloc, FORWARDED_BY | FORWARDED_FOR, - StringRef::from_lit("[::1]"), - StringRef::from_lit("_hidden"), - StringRef::from_lit(""), StringRef::from_lit("")) - .str()); - - assert_stdstring_equal( - "", http::create_forwarded( - balloc, - FORWARDED_BY | FORWARDED_FOR | FORWARDED_HOST | FORWARDED_PROTO, - StringRef::from_lit(""), StringRef::from_lit(""), - StringRef::from_lit(""), StringRef::from_lit("")) - .str()); + "example.com:3000"_sr, "[::1]"_sr, "www.example.com"_sr, "https"_sr)); + + assert_stdsv_equal("for=192.168.0.1"sv, + http::create_forwarded(balloc, FORWARDED_FOR, "alpha"_sr, + "192.168.0.1"_sr, "bravo"_sr, + "charlie"_sr)); + + assert_stdsv_equal( + "by=_hidden;for=\"[::1]\""sv, + http::create_forwarded(balloc, FORWARDED_BY | FORWARDED_FOR, "_hidden"_sr, + "[::1]"_sr, ""_sr, ""_sr)); + + assert_stdsv_equal( + "by=\"[::1]\";for=_hidden"sv, + http::create_forwarded(balloc, FORWARDED_BY | FORWARDED_FOR, "[::1]"_sr, + "_hidden"_sr, ""_sr, ""_sr)); + + assert_stdsv_equal(""sv, http::create_forwarded(balloc, + FORWARDED_BY | FORWARDED_FOR | + FORWARDED_HOST | + FORWARDED_PROTO, + ""_sr, ""_sr, ""_sr, ""_sr)); } void test_shrpx_http_create_via_header_value(void) { @@ -117,27 +106,25 @@ void test_shrpx_http_create_affinity_cookie(void) { BlockAllocator balloc(1024, 1024); StringRef c; - c = http::create_affinity_cookie(balloc, StringRef::from_lit("cookie-val"), - 0xf1e2d3c4u, StringRef{}, false); + c = http::create_affinity_cookie(balloc, "cookie-val"_sr, 0xf1e2d3c4u, + StringRef{}, false); - assert_stdstring_equal("cookie-val=f1e2d3c4", c.str()); + assert_stdsv_equal("cookie-val=f1e2d3c4"sv, c); - c = http::create_affinity_cookie(balloc, StringRef::from_lit("alpha"), - 0x00000000u, StringRef{}, true); + c = http::create_affinity_cookie(balloc, "alpha"_sr, 0x00000000u, StringRef{}, + true); - assert_stdstring_equal("alpha=00000000; Secure", c.str()); + assert_stdsv_equal("alpha=00000000; Secure"sv, c); - c = http::create_affinity_cookie(balloc, StringRef::from_lit("bravo"), - 0x01111111u, StringRef::from_lit("bar"), + c = http::create_affinity_cookie(balloc, "bravo"_sr, 0x01111111u, "bar"_sr, false); - assert_stdstring_equal("bravo=01111111; Path=bar", c.str()); + assert_stdsv_equal("bravo=01111111; Path=bar"sv, c); - c = http::create_affinity_cookie(balloc, StringRef::from_lit("charlie"), - 0x01111111u, StringRef::from_lit("bar"), + c = http::create_affinity_cookie(balloc, "charlie"_sr, 0x01111111u, "bar"_sr, true); - assert_stdstring_equal("charlie=01111111; Path=bar; Secure", c.str()); + assert_stdsv_equal("charlie=01111111; Path=bar; Secure"sv, c); } void test_shrpx_http_create_altsvc_header_value(void) { @@ -145,46 +132,44 @@ void test_shrpx_http_create_altsvc_header_value(void) { BlockAllocator balloc(1024, 1024); std::vector<AltSvc> altsvcs{ AltSvc{ - .protocol_id = StringRef::from_lit("h3"), - .host = StringRef::from_lit("127.0.0.1"), - .service = StringRef::from_lit("443"), - .params = StringRef::from_lit("ma=3600"), + .protocol_id = "h3"_sr, + .host = "127.0.0.1"_sr, + .service = "443"_sr, + .params = "ma=3600"_sr, }, }; - assert_stdstring_equal( - R"(h3="127.0.0.1:443"; ma=3600)", - http::create_altsvc_header_value(balloc, altsvcs).str()); + assert_stdsv_equal(R"(h3="127.0.0.1:443"; ma=3600)"sv, + http::create_altsvc_header_value(balloc, altsvcs)); } { BlockAllocator balloc(1024, 1024); std::vector<AltSvc> altsvcs{ AltSvc{ - .protocol_id = StringRef::from_lit("h3"), - .service = StringRef::from_lit("443"), - .params = StringRef::from_lit("ma=3600"), + .protocol_id = "h3"_sr, + .service = "443"_sr, + .params = "ma=3600"_sr, }, AltSvc{ - .protocol_id = StringRef::from_lit("h3%"), - .host = StringRef::from_lit("\"foo\""), - .service = StringRef::from_lit("4433"), + .protocol_id = "h3%"_sr, + .host = "\"foo\""_sr, + .service = "4433"_sr, }, }; - assert_stdstring_equal( - R"(h3=":443"; ma=3600, h3%25="\"foo\":4433")", - http::create_altsvc_header_value(balloc, altsvcs).str()); + assert_stdsv_equal(R"(h3=":443"; ma=3600, h3%25="\"foo\":4433")"sv, + http::create_altsvc_header_value(balloc, altsvcs)); } } void test_shrpx_http_check_http_scheme(void) { - assert_true(http::check_http_scheme(StringRef::from_lit("https"), true)); - assert_false(http::check_http_scheme(StringRef::from_lit("https"), false)); - assert_false(http::check_http_scheme(StringRef::from_lit("http"), true)); - assert_true(http::check_http_scheme(StringRef::from_lit("http"), false)); - assert_false(http::check_http_scheme(StringRef::from_lit("foo"), true)); - assert_false(http::check_http_scheme(StringRef::from_lit("foo"), false)); + assert_true(http::check_http_scheme("https"_sr, true)); + assert_false(http::check_http_scheme("https"_sr, false)); + assert_false(http::check_http_scheme("http"_sr, true)); + assert_true(http::check_http_scheme("http"_sr, false)); + assert_false(http::check_http_scheme("foo"_sr, true)); + assert_false(http::check_http_scheme("foo"_sr, false)); assert_false(http::check_http_scheme(StringRef{}, true)); assert_false(http::check_http_scheme(StringRef{}, false)); } diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 0412384..aa54eb9 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -258,7 +258,7 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req, // As per https://tools.ietf.org/html/rfc7230#section-5.4, we // rewrite host header field with authority component. - auto authority = util::get_uri_field(uri.c_str(), u, UF_HOST); + auto authority = util::get_uri_field(uri.data(), u, UF_HOST); // TODO properly check IPv6 numeric address auto ipv6 = std::find(std::begin(authority), std::end(authority), ':') != std::end(authority); @@ -271,7 +271,7 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req, } if (authoritylen > authority.size()) { auto iovec = make_byte_ref(balloc, authoritylen + 1); - auto p = iovec.base; + auto p = std::begin(iovec); if (ipv6) { *p++ = '['; } @@ -286,16 +286,16 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req, } *p = '\0'; - req.authority = StringRef{iovec.base, p}; + req.authority = StringRef{std::span{std::begin(iovec), p}}; } else { req.authority = authority; } - req.scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); + req.scheme = util::get_uri_field(uri.data(), u, UF_SCHEMA); StringRef path; if (u.field_set & (1 << UF_PATH)) { - path = util::get_uri_field(uri.c_str(), u, UF_PATH); + path = util::get_uri_field(uri.data(), u, UF_PATH); } else if (req.method == HTTP_OPTIONS) { // Server-wide OPTIONS takes following form in proxy request: // @@ -303,21 +303,21 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req, // // Notice that no slash after authority. See // http://tools.ietf.org/html/rfc7230#section-5.3.4 - req.path = StringRef::from_lit(""); + req.path = ""_sr; // we ignore query component here return; } else { - path = StringRef::from_lit("/"); + path = "/"_sr; } if (u.field_set & (1 << UF_QUERY)) { auto &fdata = u.field_data[UF_QUERY]; if (u.field_set & (1 << UF_PATH)) { - auto q = util::get_uri_field(uri.c_str(), u, UF_QUERY); + auto q = util::get_uri_field(uri.data(), u, UF_QUERY); path = StringRef{std::begin(path), std::end(q)}; } else { - path = concat_string_ref(balloc, path, StringRef::from_lit("?"), + path = concat_string_ref(balloc, path, "?"_sr, StringRef{&uri[fdata.off], fdata.len}); } } @@ -369,7 +369,7 @@ int htp_hdrs_completecb(llhttp_t *htp) { << "HTTP/" << req.http_major << "." << req.http_minor << "\n"; for (const auto &kv : req.fs.headers()) { - if (kv.name == "authorization") { + if (kv.name == "authorization"_sr) { ss << TTY_HTTP_HD << kv.name << TTY_RST << ": <redacted>\n"; continue; } @@ -431,7 +431,7 @@ int htp_hdrs_completecb(llhttp_t *htp) { if (method != HTTP_CONNECT) { http_parser_url u{}; - rv = http_parser_parse_url(req.path.c_str(), req.path.size(), 0, &u); + rv = http_parser_parse_url(req.path.data(), req.path.size(), 0, &u); if (rv != 0) { // Expect to respond with 400 bad request return -1; @@ -440,7 +440,7 @@ int htp_hdrs_completecb(llhttp_t *htp) { if (!(u.field_set & (1 << UF_SCHEMA)) || !(u.field_set & (1 << UF_HOST))) { req.no_authority = true; - if (method == HTTP_OPTIONS && req.path == StringRef::from_lit("*")) { + if (method == HTTP_OPTIONS && req.path == "*"_sr) { req.path = StringRef{}; } else { req.path = http2::rewrite_clean_path(balloc, req.path); @@ -451,9 +451,9 @@ int htp_hdrs_completecb(llhttp_t *htp) { } if (handler->get_ssl()) { - req.scheme = StringRef::from_lit("https"); + req.scheme = "https"_sr; } else { - req.scheme = StringRef::from_lit("http"); + req.scheme = "http"_sr; } } else { rewrite_request_host_path_from_uri(balloc, req, req.path, u); @@ -544,7 +544,7 @@ int htp_hdrs_completecb(llhttp_t *htp) { // Continue here to make the client happy. if (downstream->get_expect_100_continue()) { auto output = downstream->get_response_buf(); - constexpr auto res = StringRef::from_lit("HTTP/1.1 100 Continue\r\n\r\n"); + constexpr auto res = "HTTP/1.1 100 Continue\r\n\r\n"_sr; output->append(res); handler->signal_write(); } @@ -982,8 +982,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body, if (httpconf.max_requests <= num_requests_ || worker->get_graceful_shutdown()) { - resp.fs.add_header_token(StringRef::from_lit("connection"), - StringRef::from_lit("close"), false, + resp.fs.add_header_token("connection"_sr, "close"_sr, false, http2::HD_CONNECTION); connection_close = true; } else if (req.http_major <= 0 || @@ -991,7 +990,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body, connection_close = true; } else { auto c = resp.fs.header(http2::HD_CONNECTION); - if (c && util::strieq_l("close", c->value)) { + if (c && util::strieq("close"_sr, c->value)) { connection_close = true; } } @@ -1034,9 +1033,12 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body, output->append("\r\n"); - output->append(body, bodylen); + if (req.method != HTTP_HEAD) { + output->append(body, bodylen); + + downstream->response_sent_body_length += bodylen; + } - downstream->response_sent_body_length += bodylen; downstream->set_response_state(DownstreamState::MSG_COMPLETE); return 0; @@ -1071,7 +1073,7 @@ void HttpsUpstream::error_reply(unsigned int status_code) { output->append("\r\nServer: "); output->append(get_config()->http.server_name); output->append("\r\nContent-Length: "); - std::array<uint8_t, NGHTTP2_MAX_UINT64_DIGITS> intbuf; + std::array<char, NGHTTP2_MAX_UINT64_DIGITS> intbuf; output->append(StringRef{std::begin(intbuf), util::utos(std::begin(intbuf), html.size())}); output->append("\r\nDate: "); @@ -1080,9 +1082,15 @@ void HttpsUpstream::error_reply(unsigned int status_code) { output->append(lgconf->tstamp->time_http); output->append("\r\nContent-Type: text/html; " "charset=UTF-8\r\nConnection: close\r\n\r\n"); - output->append(html); - downstream->response_sent_body_length += html.size(); + const auto &req = downstream->request(); + + if (req.method != HTTP_HEAD) { + output->append(html); + + downstream->response_sent_body_length += html.size(); + } + downstream->set_response_state(DownstreamState::MSG_COMPLETE); } @@ -1403,7 +1411,7 @@ int HttpsUpstream::on_downstream_abort_request_with_https_redirect( int HttpsUpstream::redirect_to_https(Downstream *downstream) { auto &req = downstream->request(); - if (req.method == HTTP_CONNECT || req.scheme != "http" || + if (req.method == HTTP_CONNECT || req.scheme != "http"_sr || req.authority.empty()) { error_reply(400); return 0; @@ -1420,21 +1428,17 @@ int HttpsUpstream::redirect_to_https(Downstream *downstream) { auto &httpconf = config->http; StringRef loc; - if (httpconf.redirect_https_port == StringRef::from_lit("443")) { - loc = concat_string_ref(balloc, StringRef::from_lit("https://"), authority, - req.path); + if (httpconf.redirect_https_port == "443"_sr) { + loc = concat_string_ref(balloc, "https://"_sr, authority, req.path); } else { - loc = concat_string_ref(balloc, StringRef::from_lit("https://"), authority, - StringRef::from_lit(":"), + loc = concat_string_ref(balloc, "https://"_sr, authority, ":"_sr, httpconf.redirect_https_port, req.path); } auto &resp = downstream->response(); resp.http_status = 308; - resp.fs.add_header_token(StringRef::from_lit("location"), loc, false, - http2::HD_LOCATION); - resp.fs.add_header_token(StringRef::from_lit("connection"), - StringRef::from_lit("close"), false, + resp.fs.add_header_token("location"_sr, loc, false, http2::HD_LOCATION); + resp.fs.add_header_token("connection"_sr, "close"_sr, false, http2::HD_CONNECTION); return send_reply(downstream, nullptr, 0); diff --git a/src/shrpx_live_check.cc b/src/shrpx_live_check.cc index 8e8d316..e59df5a 100644 --- a/src/shrpx_live_check.cc +++ b/src/shrpx_live_check.cc @@ -299,8 +299,8 @@ int LiveCheck::initiate_connection() { if (addr_->tls) { auto sni_name = addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni}; - if (!util::numeric_host(sni_name.c_str())) { - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str()); + if (!util::numeric_host(sni_name.data())) { + SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.data()); } auto session = tls::reuse_tls_session(addr_->tls_session_cache); @@ -411,7 +411,7 @@ int LiveCheck::tls_handshake() { switch (addr_->proto) { case Proto::HTTP1: - if (proto.empty() || proto == StringRef::from_lit("http/1.1")) { + if (proto.empty() || proto == "http/1.1"_sr) { break; } return -1; diff --git a/src/shrpx_log.cc b/src/shrpx_log.cc index de5e09f..386b33f 100644 --- a/src/shrpx_log.cc +++ b/src/shrpx_log.cc @@ -58,10 +58,8 @@ using namespace nghttp2; namespace shrpx { namespace { -constexpr StringRef SEVERITY_STR[] = { - StringRef::from_lit("INFO"), StringRef::from_lit("NOTICE"), - StringRef::from_lit("WARN"), StringRef::from_lit("ERROR"), - StringRef::from_lit("FATAL")}; +constexpr StringRef SEVERITY_STR[] = {"INFO"_sr, "NOTICE"_sr, "WARN"_sr, + "ERROR"_sr, "FATAL"_sr}; } // namespace namespace { @@ -173,11 +171,10 @@ Log::~Log() { if (errorconf.syslog) { if (severity_ == NOTICE) { syslog(severity_to_syslog_level(severity_), "[%s] %.*s", - SEVERITY_STR[severity_].c_str(), static_cast<int>(rleft()), - begin_); + SEVERITY_STR[severity_].data(), static_cast<int>(rleft()), begin_); } else { syslog(severity_to_syslog_level(severity_), "[%s] %.*s (%s:%d)", - SEVERITY_STR[severity_].c_str(), static_cast<int>(rleft()), begin_, + SEVERITY_STR[severity_].data(), static_cast<int>(rleft()), begin_, filename_, linenum_); } @@ -192,10 +189,10 @@ Log::~Log() { // Error log format: <datetime> <main-pid> <current-pid> // <thread-id> <level> (<filename>:<line>) <msg> rv = snprintf(buf, sizeof(buf), "%s %d %d %s %s%s%s (%s:%d) %.*s\n", - lgconf->tstamp->time_iso8601.c_str(), config->pid, lgconf->pid, + lgconf->tstamp->time_iso8601.data(), config->pid, lgconf->pid, lgconf->thread_id.c_str(), tty ? SEVERITY_COLOR[severity_] : "", - SEVERITY_STR[severity_].c_str(), tty ? "\033[0m" : "", - filename_, linenum_, static_cast<int>(rleft()), begin_); + SEVERITY_STR[severity_].data(), tty ? "\033[0m" : "", filename_, + linenum_, static_cast<int>(rleft()), begin_); if (rv < 0) { return; @@ -380,7 +377,7 @@ namespace { template <typename OutputIterator> std::pair<OutputIterator, OutputIterator> copy(const StringRef &src, OutputIterator d_first, OutputIterator d_last) { - return copy(src.c_str(), src.size(), d_first, d_last); + return copy(src.data(), src.size(), d_first, d_last); } } // namespace @@ -531,7 +528,7 @@ template <typename OutputIterator> std::pair<OutputIterator, OutputIterator> copy_escape(const StringRef &src, OutputIterator d_first, OutputIterator d_last) { - return copy_escape(src.c_str(), src.size(), d_first, d_last); + return copy_escape(src.data(), src.size(), d_first, d_last); } } // namespace @@ -555,7 +552,7 @@ StringRef construct_absolute_request_uri(BlockAllocator &balloc, } auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; + auto p = std::begin(iov); if (req.scheme.empty()) { // We may have to log the request which lacks scheme (e.g., @@ -569,7 +566,7 @@ StringRef construct_absolute_request_uri(BlockAllocator &balloc, p = std::copy(std::begin(req.path), std::end(req.path), p); *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } } // namespace @@ -593,14 +590,13 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv, auto &balloc = downstream->get_block_allocator(); auto downstream_addr = downstream->get_addr(); - auto method = req.method == -1 ? StringRef::from_lit("<unknown>") - : http2::to_method_string(req.method); - auto path = - req.method == HTTP_CONNECT ? req.authority - : config->http2_proxy ? construct_absolute_request_uri(balloc, req) - : req.path.empty() ? req.method == HTTP_OPTIONS ? StringRef::from_lit("*") - : StringRef::from_lit("-") - : req.path; + auto method = + req.method == -1 ? "<unknown>"_sr : http2::to_method_string(req.method); + auto path = req.method == HTTP_CONNECT ? req.authority + : config->http2_proxy + ? construct_absolute_request_uri(balloc, req) + : req.path.empty() ? req.method == HTTP_OPTIONS ? "*"_sr : "-"_sr + : req.path; auto path_without_query = req.method == HTTP_CONNECT ? path @@ -880,7 +876,7 @@ int reopen_log_files(const LoggingConfig &loggingconf) { auto &errorconf = loggingconf.error; if (!accessconf.syslog && !accessconf.file.empty()) { - new_accesslog_fd = open_log_file(accessconf.file.c_str()); + new_accesslog_fd = open_log_file(accessconf.file.data()); if (new_accesslog_fd == -1) { LOG(ERROR) << "Failed to open accesslog file " << accessconf.file; @@ -889,7 +885,7 @@ int reopen_log_files(const LoggingConfig &loggingconf) { } if (!errorconf.syslog && !errorconf.file.empty()) { - new_errorlog_fd = open_log_file(errorconf.file.c_str()); + new_errorlog_fd = open_log_file(errorconf.file.data()); if (new_errorlog_fd == -1) { if (lgconf->errorlog_fd != -1) { diff --git a/src/shrpx_log.h b/src/shrpx_log.h index bc30097..7a334ca 100644 --- a/src/shrpx_log.h +++ b/src/shrpx_log.h @@ -33,7 +33,6 @@ #include <vector> #include <chrono> -#include "shrpx_config.h" #include "shrpx_log_config.h" #include "tls.h" #include "template.h" @@ -97,6 +96,7 @@ namespace shrpx { class Downstream; struct DownstreamAddr; +struct LoggingConfig; enum SeverityLevel { INFO, NOTICE, WARN, ERROR, FATAL }; @@ -266,7 +266,7 @@ enum class LogFragmentType { }; struct LogFragment { - LogFragment(LogFragmentType type, StringRef value = StringRef::from_lit("")) + LogFragment(LogFragmentType type, StringRef value = ""_sr) : type(type), value(std::move(value)) {} LogFragmentType type; StringRef value; diff --git a/src/shrpx_log_config.cc b/src/shrpx_log_config.cc index 92eb055..9d066f2 100644 --- a/src/shrpx_log_config.cc +++ b/src/shrpx_log_config.cc @@ -50,10 +50,8 @@ LogConfig::LogConfig() errorlog_tty(false) { auto tid = std::this_thread::get_id(); auto tid_hash = - util::hash32(StringRef{reinterpret_cast<uint8_t *>(&tid), - reinterpret_cast<uint8_t *>(&tid) + sizeof(tid)}); - thread_id = util::format_hex(reinterpret_cast<uint8_t *>(&tid_hash), - sizeof(tid_hash)); + util::hash32(StringRef{reinterpret_cast<char *>(&tid), sizeof(tid)}); + thread_id = util::format_hex(std::span{&tid_hash, 1}); } #ifndef NOTHREADS diff --git a/src/shrpx_memcached_connection.cc b/src/shrpx_memcached_connection.cc index f72cb11..472df43 100644 --- a/src/shrpx_memcached_connection.cc +++ b/src/shrpx_memcached_connection.cc @@ -182,8 +182,8 @@ int MemcachedConnection::initiate_connection() { } if (ssl_ctx_) { - if (!util::numeric_host(sni_name_.c_str())) { - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name_.c_str()); + if (!util::numeric_host(sni_name_.data())) { + SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name_.data()); } auto session = tls::reuse_tls_session(tls_session_cache_); diff --git a/src/shrpx_mruby.cc b/src/shrpx_mruby.cc index 4d412ef..cfa10fd 100644 --- a/src/shrpx_mruby.cc +++ b/src/shrpx_mruby.cc @@ -144,7 +144,7 @@ RProc *compile(mrb_state *mrb, const StringRef &filename) { return nullptr; } - auto infile = fopen(filename.c_str(), "rb"); + auto infile = fopen(filename.data(), "rb"); if (infile == nullptr) { LOG(ERROR) << "Could not open mruby file " << filename; return nullptr; diff --git a/src/shrpx_mruby_module.cc b/src/shrpx_mruby_module.cc index 27b7769..0159ba2 100644 --- a/src/shrpx_mruby_module.cc +++ b/src/shrpx_mruby_module.cc @@ -94,13 +94,13 @@ mrb_value create_headers_hash(mrb_state *mrb, const HeaderRefs &headers) { } auto ai = mrb_gc_arena_save(mrb); - auto key = mrb_str_new(mrb, hd.name.c_str(), hd.name.size()); + auto key = mrb_str_new(mrb, hd.name.data(), hd.name.size()); auto ary = mrb_hash_get(mrb, hash, key); if (mrb_nil_p(ary)) { ary = mrb_ary_new(mrb); mrb_hash_set(mrb, hash, key, ary); } - mrb_ary_push(mrb, ary, mrb_str_new(mrb, hd.value.c_str(), hd.value.size())); + mrb_ary_push(mrb, ary, mrb_str_new(mrb, hd.value.data(), hd.value.size())); mrb_gc_arena_restore(mrb, ai); } diff --git a/src/shrpx_mruby_module_env.cc b/src/shrpx_mruby_module_env.cc index 5ebd9c0..9b63c51 100644 --- a/src/shrpx_mruby_module_env.cc +++ b/src/shrpx_mruby_module_env.cc @@ -90,7 +90,7 @@ mrb_value env_get_remote_addr(mrb_state *mrb, mrb_value self) { auto &ipaddr = handler->get_ipaddr(); - return mrb_str_new(mrb, ipaddr.c_str(), ipaddr.size()); + return mrb_str_new(mrb, ipaddr.data(), ipaddr.size()); } } // namespace @@ -114,7 +114,7 @@ mrb_value env_get_server_addr(mrb_state *mrb, mrb_value self) { auto handler = upstream->get_client_handler(); auto faddr = handler->get_upstream_addr(); - return mrb_str_new(mrb, faddr->host.c_str(), faddr->host.size()); + return mrb_str_new(mrb, faddr->host.data(), faddr->host.size()); } } // namespace @@ -137,7 +137,7 @@ mrb_value env_get_tls_sni(mrb_state *mrb, mrb_value self) { auto handler = upstream->get_client_handler(); auto sni = handler->get_tls_sni(); - return mrb_str_new(mrb, sni.c_str(), sni.size()); + return mrb_str_new(mrb, sni.data(), sni.size()); } } // namespace @@ -172,11 +172,10 @@ mrb_value env_get_tls_client_fingerprint_md(mrb_state *mrb, const EVP_MD *md) { mrb_raise(mrb, E_RUNTIME_ERROR, "could not compute client fingerprint"); } - // TODO Use template version of format_hex auto &balloc = downstream->get_block_allocator(); auto f = util::format_hex(balloc, - StringRef{std::begin(buf), std::begin(buf) + slen}); - return mrb_str_new(mrb, f.c_str(), f.size()); + std::span{buf.data(), static_cast<size_t>(slen)}); + return mrb_str_new(mrb, f.data(), f.size()); } } // namespace @@ -219,7 +218,7 @@ mrb_value env_get_tls_client_subject_name(mrb_state *mrb, mrb_value self) { #if !OPENSSL_3_0_0_API X509_free(x); #endif // !OPENSSL_3_0_0_API - return mrb_str_new(mrb, name.c_str(), name.size()); + return mrb_str_new(mrb, name.data(), name.size()); } } // namespace @@ -249,7 +248,7 @@ mrb_value env_get_tls_client_issuer_name(mrb_state *mrb, mrb_value self) { #if !OPENSSL_3_0_0_API X509_free(x); #endif // !OPENSSL_3_0_0_API - return mrb_str_new(mrb, name.c_str(), name.size()); + return mrb_str_new(mrb, name.data(), name.size()); } } // namespace @@ -279,7 +278,7 @@ mrb_value env_get_tls_client_serial(mrb_state *mrb, mrb_value self) { #if !OPENSSL_3_0_0_API X509_free(x); #endif // !OPENSSL_3_0_0_API - return mrb_str_new(mrb, sn.c_str(), sn.size()); + return mrb_str_new(mrb, sn.data(), sn.size()); } } // namespace @@ -403,10 +402,9 @@ mrb_value env_get_tls_session_id(mrb_state *mrb, mrb_value self) { unsigned int session_id_length = 0; auto session_id = SSL_SESSION_get_id(session, &session_id_length); - // TODO Use template version of util::format_hex. auto &balloc = downstream->get_block_allocator(); - auto id = util::format_hex(balloc, StringRef{session_id, session_id_length}); - return mrb_str_new(mrb, id.c_str(), id.size()); + auto id = util::format_hex(balloc, std::span{session_id, session_id_length}); + return mrb_str_new(mrb, id.data(), id.size()); } } // namespace @@ -433,7 +431,7 @@ mrb_value env_get_alpn(mrb_state *mrb, mrb_value self) { auto upstream = downstream->get_upstream(); auto handler = upstream->get_client_handler(); auto alpn = handler->get_alpn(); - return mrb_str_new(mrb, alpn.c_str(), alpn.size()); + return mrb_str_new(mrb, alpn.data(), alpn.size()); } } // namespace diff --git a/src/shrpx_mruby_module_request.cc b/src/shrpx_mruby_module_request.cc index 1ed3aa9..84b39fa 100644 --- a/src/shrpx_mruby_module_request.cc +++ b/src/shrpx_mruby_module_request.cc @@ -71,7 +71,7 @@ mrb_value request_get_method(mrb_state *mrb, mrb_value self) { const auto &req = downstream->request(); auto method = http2::to_method_string(req.method); - return mrb_str_new(mrb, method.c_str(), method.size()); + return mrb_str_new(mrb, method.data(), method.size()); } } // namespace @@ -90,7 +90,7 @@ mrb_value request_set_method(mrb_state *mrb, mrb_value self) { mrb_raise(mrb, E_RUNTIME_ERROR, "method must not be empty string"); } auto token = - http2::lookup_method_token(reinterpret_cast<const uint8_t *>(method), n); + http2::lookup_method_token(StringRef{method, static_cast<size_t>(n)}); if (token == -1) { mrb_raise(mrb, E_RUNTIME_ERROR, "method not supported"); } @@ -107,7 +107,7 @@ mrb_value request_get_authority(mrb_state *mrb, mrb_value self) { auto downstream = data->downstream; const auto &req = downstream->request(); - return mrb_str_new(mrb, req.authority.c_str(), req.authority.size()); + return mrb_str_new(mrb, req.authority.data(), req.authority.size()); } } // namespace @@ -141,7 +141,7 @@ mrb_value request_get_scheme(mrb_state *mrb, mrb_value self) { auto downstream = data->downstream; const auto &req = downstream->request(); - return mrb_str_new(mrb, req.scheme.c_str(), req.scheme.size()); + return mrb_str_new(mrb, req.scheme.data(), req.scheme.size()); } } // namespace @@ -175,7 +175,7 @@ mrb_value request_get_path(mrb_state *mrb, mrb_value self) { auto downstream = data->downstream; const auto &req = downstream->request(); - return mrb_str_new(mrb, req.path.c_str(), req.path.size()); + return mrb_str_new(mrb, req.path.data(), req.path.size()); } } // namespace @@ -235,7 +235,7 @@ mrb_value request_mod_header(mrb_state *mrb, mrb_value self, bool repl) { mrb_gc_arena_restore(mrb, ai); - auto token = http2::lookup_token(keyref.byte(), keyref.size()); + auto token = http2::lookup_token(keyref); if (repl) { size_t p = 0; diff --git a/src/shrpx_mruby_module_response.cc b/src/shrpx_mruby_module_response.cc index 1de1d5f..5d02d83 100644 --- a/src/shrpx_mruby_module_response.cc +++ b/src/shrpx_mruby_module_response.cc @@ -127,7 +127,7 @@ mrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) { mrb_gc_arena_restore(mrb, ai); - auto token = http2::lookup_token(keyref.byte(), keyref.size()); + auto token = http2::lookup_token(keyref); if (repl) { size_t p = 0; @@ -245,8 +245,8 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) { if (cl) { cl->value = content_length; } else { - resp.fs.add_header_token(StringRef::from_lit("content-length"), - content_length, false, http2::HD_CONTENT_LENGTH); + resp.fs.add_header_token("content-length"_sr, content_length, false, + http2::HD_CONTENT_LENGTH); } resp.fs.content_length = vallen; @@ -256,7 +256,7 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) { if (!date) { auto lgconf = log_config(); lgconf->update_tstamp(std::chrono::system_clock::now()); - resp.fs.add_header_token(StringRef::from_lit("date"), + resp.fs.add_header_token("date"_sr, make_string_ref(balloc, lgconf->tstamp->time_http), false, http2::HD_DATE); } @@ -319,7 +319,7 @@ mrb_value response_send_info(mrb_state *mrb, mrb_value self) { mrb_gc_arena_restore(mrb, ai); - auto token = http2::lookup_token(keyref.byte(), keyref.size()); + auto token = http2::lookup_token(keyref); if (mrb_array_p(values)) { auto n = RARRAY_LEN(values); diff --git a/src/shrpx_quic.cc b/src/shrpx_quic.cc index c52eee4..1ffd217 100644 --- a/src/shrpx_quic.cc +++ b/src/shrpx_quic.cc @@ -58,8 +58,10 @@ ngtcp2_tstamp quic_timestamp() { int quic_send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, size_t remote_salen, const sockaddr *local_sa, size_t local_salen, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen, size_t gso_size) { - iovec msg_iov = {const_cast<uint8_t *>(data), datalen}; + std::span<const uint8_t> data, size_t gso_size) { + assert(gso_size); + + iovec msg_iov = {const_cast<uint8_t *>(data.data()), data.size()}; msghdr msg{}; msg.msg_name = const_cast<sockaddr *>(remote_sa); msg.msg_namelen = remote_salen; @@ -113,7 +115,7 @@ int quic_send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, } #ifdef UDP_SEGMENT - if (gso_size && datalen > gso_size) { + if (data.size() > gso_size) { controllen += CMSG_SPACE(sizeof(uint16_t)); cm = CMSG_NXTHDR(&msg, cm); cm->cmsg_level = SOL_UDP; @@ -170,6 +172,8 @@ int quic_send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, << " bytes"; } + assert(static_cast<size_t>(nwrite) == data.size()); + return 0; } @@ -267,87 +271,90 @@ int generate_quic_stateless_reset_token(uint8_t *token, const ngtcp2_cid &cid, return 0; } -int generate_retry_token(uint8_t *token, size_t &tokenlen, uint32_t version, - const sockaddr *sa, socklen_t salen, - const ngtcp2_cid &retry_scid, const ngtcp2_cid &odcid, - const uint8_t *secret, size_t secretlen) { +std::optional<std::span<const uint8_t>> +generate_retry_token(std::span<uint8_t> token, uint32_t version, + const sockaddr *sa, socklen_t salen, + const ngtcp2_cid &retry_scid, const ngtcp2_cid &odcid, + std::span<const uint8_t> secret) { auto t = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::system_clock::now().time_since_epoch()) .count(); - auto stokenlen = ngtcp2_crypto_generate_retry_token( - token, secret, secretlen, version, sa, salen, &retry_scid, &odcid, t); - if (stokenlen < 0) { - return -1; + auto tokenlen = ngtcp2_crypto_generate_retry_token( + token.data(), secret.data(), secret.size(), version, sa, salen, + &retry_scid, &odcid, t); + if (tokenlen < 0) { + return {}; } - tokenlen = stokenlen; - - return 0; + return {{std::begin(token), static_cast<size_t>(tokenlen)}}; } -int verify_retry_token(ngtcp2_cid &odcid, const uint8_t *token, size_t tokenlen, +int verify_retry_token(ngtcp2_cid &odcid, std::span<const uint8_t> token, uint32_t version, const ngtcp2_cid &dcid, const sockaddr *sa, socklen_t salen, - const uint8_t *secret, size_t secretlen) { - + std::span<const uint8_t> secret) { auto t = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::system_clock::now().time_since_epoch()) .count(); - if (ngtcp2_crypto_verify_retry_token(&odcid, token, tokenlen, secret, - secretlen, version, sa, salen, &dcid, - 10 * NGTCP2_SECONDS, t) != 0) { + if (ngtcp2_crypto_verify_retry_token( + &odcid, token.data(), token.size(), secret.data(), secret.size(), + version, sa, salen, &dcid, 10 * NGTCP2_SECONDS, t) != 0) { return -1; } return 0; } -int generate_token(uint8_t *token, size_t &tokenlen, const sockaddr *sa, - size_t salen, const uint8_t *secret, size_t secretlen) { +std::optional<std::span<const uint8_t>> +generate_token(std::span<uint8_t> token, const sockaddr *sa, size_t salen, + std::span<const uint8_t> secret, uint8_t km_id) { auto t = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::system_clock::now().time_since_epoch()) .count(); - auto stokenlen = ngtcp2_crypto_generate_regular_token( - token, secret, secretlen, sa, salen, t); - if (stokenlen < 0) { - return -1; + auto tokenlen = ngtcp2_crypto_generate_regular_token( + token.data(), secret.data(), secret.size(), sa, salen, t); + if (tokenlen < 0) { + return {}; } - tokenlen = stokenlen; + token[tokenlen++] = km_id; - return 0; + return {{std::begin(token), static_cast<size_t>(tokenlen)}}; } -int verify_token(const uint8_t *token, size_t tokenlen, const sockaddr *sa, - socklen_t salen, const uint8_t *secret, size_t secretlen) { +int verify_token(std::span<const uint8_t> token, const sockaddr *sa, + socklen_t salen, std::span<const uint8_t> secret) { + if (token.empty()) { + return -1; + } + auto t = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::system_clock::now().time_since_epoch()) .count(); - if (ngtcp2_crypto_verify_regular_token(token, tokenlen, secret, secretlen, sa, - salen, 3600 * NGTCP2_SECONDS, - t) != 0) { + if (ngtcp2_crypto_verify_regular_token( + token.data(), token.size() - 1, secret.data(), secret.size(), sa, + salen, 3600 * NGTCP2_SECONDS, t) != 0) { return -1; } return 0; } -int generate_quic_connection_id_encryption_key(uint8_t *key, size_t keylen, - const uint8_t *secret, - size_t secretlen, - const uint8_t *salt, - size_t saltlen) { +int generate_quic_connection_id_encryption_key(std::span<uint8_t> key, + std::span<const uint8_t> secret, + std::span<const uint8_t> salt) { constexpr uint8_t info[] = "connection id encryption key"; ngtcp2_crypto_md sha256; ngtcp2_crypto_md_init( &sha256, reinterpret_cast<void *>(const_cast<EVP_MD *>(EVP_sha256()))); - if (ngtcp2_crypto_hkdf(key, keylen, &sha256, secret, secretlen, salt, saltlen, - info, str_size(info)) != 0) { + if (ngtcp2_crypto_hkdf(key.data(), key.size(), &sha256, secret.data(), + secret.size(), salt.data(), salt.size(), info, + str_size(info)) != 0) { return -1; } diff --git a/src/shrpx_quic.h b/src/shrpx_quic.h index dae6e31..bc7f729 100644 --- a/src/shrpx_quic.h +++ b/src/shrpx_quic.h @@ -30,6 +30,8 @@ #include <stdint.h> #include <functional> +#include <optional> +#include <span> #include <openssl/evp.h> @@ -115,7 +117,7 @@ ngtcp2_tstamp quic_timestamp(); int quic_send_packet(const UpstreamAddr *faddr, const sockaddr *remote_sa, size_t remote_salen, const sockaddr *local_sa, size_t local_salen, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen, size_t gso_size); + std::span<const uint8_t> data, size_t gso_size); int generate_quic_retry_connection_id(ngtcp2_cid &cid, uint32_t server_id, uint8_t km_id, EVP_CIPHER_CTX *ctx); @@ -138,27 +140,27 @@ int generate_quic_stateless_reset_token(uint8_t *token, const ngtcp2_cid &cid, const uint8_t *secret, size_t secretlen); -int generate_retry_token(uint8_t *token, size_t &tokenlen, uint32_t version, - const sockaddr *sa, socklen_t salen, - const ngtcp2_cid &retry_scid, const ngtcp2_cid &odcid, - const uint8_t *secret, size_t secretlen); +std::optional<std::span<const uint8_t>> +generate_retry_token(std::span<uint8_t> token, uint32_t version, + const sockaddr *sa, socklen_t salen, + const ngtcp2_cid &retry_scid, const ngtcp2_cid &odcid, + std::span<const uint8_t> secret); -int verify_retry_token(ngtcp2_cid &odcid, const uint8_t *token, size_t tokenlen, +int verify_retry_token(ngtcp2_cid &odcid, std::span<const uint8_t> token, uint32_t version, const ngtcp2_cid &dcid, const sockaddr *sa, socklen_t salen, - const uint8_t *secret, size_t secretlen); + std::span<const uint8_t> secret); -int generate_token(uint8_t *token, size_t &tokenlen, const sockaddr *sa, - size_t salen, const uint8_t *secret, size_t secretlen); +std::optional<std::span<const uint8_t>> +generate_token(std::span<uint8_t> token, const sockaddr *sa, size_t salen, + std::span<const uint8_t> secret, uint8_t km_id); -int verify_token(const uint8_t *token, size_t tokenlen, const sockaddr *sa, - socklen_t salen, const uint8_t *secret, size_t secretlen); +int verify_token(std::span<const uint8_t> token, const sockaddr *sa, + socklen_t salen, std::span<const uint8_t> secret); -int generate_quic_connection_id_encryption_key(uint8_t *key, size_t keylen, - const uint8_t *secret, - size_t secretlen, - const uint8_t *salt, - size_t saltlen); +int generate_quic_connection_id_encryption_key(std::span<uint8_t> key, + std::span<const uint8_t> secret, + std::span<const uint8_t> salt); const QUICKeyingMaterial * select_quic_keying_material(const QUICKeyingMaterials &qkms, uint8_t km_id); diff --git a/src/shrpx_quic_connection_handler.cc b/src/shrpx_quic_connection_handler.cc index b810aa6..f10cc83 100644 --- a/src/shrpx_quic_connection_handler.cc +++ b/src/shrpx_quic_connection_handler.cc @@ -63,17 +63,18 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen) { + std::span<const uint8_t> data) { int rv; ngtcp2_version_cid vc; - rv = ngtcp2_pkt_decode_version_cid(&vc, data, datalen, SHRPX_QUIC_SCIDLEN); + rv = ngtcp2_pkt_decode_version_cid(&vc, data.data(), data.size(), + SHRPX_QUIC_SCIDLEN); switch (rv) { case 0: break; case NGTCP2_ERR_VERSION_NEGOTIATION: - send_version_negotiation(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr); + send_version_negotiation(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr); return 0; default: @@ -97,7 +98,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (cwit != std::end(close_waits_)) { auto cw = (*cwit).second; - cw->handle_packet(faddr, remote_addr, local_addr, pi, data, datalen); + cw->handle_packet(faddr, remote_addr, local_addr, pi, data); return 0; } @@ -114,7 +115,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (cwit != std::end(close_waits_)) { auto cw = (*cwit).second; - cw->handle_packet(faddr, remote_addr, local_addr, pi, data, datalen); + cw->handle_packet(faddr, remote_addr, local_addr, pi, data); return 0; } @@ -145,7 +146,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, decrypted_dcid.worker); if (quic_lwp) { if (conn_handler->forward_quic_packet_to_lingering_worker_process( - quic_lwp, remote_addr, local_addr, pi, data, datalen) == 0) { + quic_lwp, remote_addr, local_addr, pi, data) == 0) { return 0; } @@ -169,11 +170,10 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, ngtcp2_pkt_hd hd; ngtcp2_cid odcid, *podcid = nullptr; - const uint8_t *token = nullptr; - size_t tokenlen = 0; + std::span<const uint8_t> token; ngtcp2_token_type token_type = NGTCP2_TOKEN_TYPE_UNKNOWN; - switch (ngtcp2_accept(&hd, data, datalen)) { + switch (ngtcp2_accept(&hd, data.data(), data.size())) { case 0: { // If we get Initial and it has the Worker ID of this worker, it // is likely that client is intentionally use the prefix. Just @@ -197,14 +197,15 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (worker_->get_graceful_shutdown()) { send_connection_close(faddr, hd.version, hd.dcid, hd.scid, remote_addr, local_addr, NGTCP2_CONNECTION_REFUSED, - datalen * 3); + data.size() * 3); return 0; } if (hd.tokenlen == 0) { if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -223,9 +224,9 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, auto qkm = select_quic_keying_material( *qkms.get(), vc.dcid[0] & SHRPX_QUIC_DCID_KM_ID_MASK); - if (verify_retry_token(odcid, hd.token, hd.tokenlen, hd.version, + if (verify_retry_token(odcid, {hd.token, hd.tokenlen}, hd.version, hd.dcid, &remote_addr.su.sa, remote_addr.len, - qkm->secret.data(), qkm->secret.size()) != 0) { + qkm->secret) != 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Failed to validate Retry token from remote=" << util::to_numeric_addr(&remote_addr); @@ -235,7 +236,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, // with INVALID_TOKEN. send_connection_close(faddr, hd.version, hd.dcid, hd.scid, remote_addr, local_addr, NGTCP2_INVALID_TOKEN, - datalen * 3); + data.size() * 3); return 0; } @@ -245,8 +246,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } podcid = &odcid; - token = hd.token; - tokenlen = hd.tokenlen; + token = {hd.token, hd.tokenlen}; token_type = NGTCP2_TOKEN_TYPE_RETRY; break; @@ -265,8 +265,9 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -277,17 +278,17 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, auto qkm = select_quic_keying_material( *qkms.get(), hd.token[NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN]); - if (verify_token(hd.token, hd.tokenlen - 1, &remote_addr.su.sa, - remote_addr.len, qkm->secret.data(), - qkm->secret.size()) != 0) { + if (verify_token({hd.token, hd.tokenlen}, &remote_addr.su.sa, + remote_addr.len, qkm->secret) != 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Failed to validate token from remote=" << util::to_numeric_addr(&remote_addr); } if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -300,16 +301,16 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, << util::to_numeric_addr(&remote_addr); } - token = hd.token; - tokenlen = hd.tokenlen; + token = {hd.token, hd.tokenlen}; token_type = NGTCP2_TOKEN_TYPE_NEW_TOKEN; break; } default: if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -322,16 +323,15 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, default: if (!(data[0] & 0x80) && vc.dcidlen == SHRPX_QUIC_SCIDLEN && decrypted_dcid.worker != worker_->get_worker_id()) { - if (!config->single_thread && - conn_handler->forward_quic_packet(faddr, remote_addr, local_addr, - pi, decrypted_dcid.worker, data, - datalen) == 0) { + if (!config->single_thread && conn_handler->forward_quic_packet( + faddr, remote_addr, local_addr, pi, + decrypted_dcid.worker, data) == 0) { return 0; } - if (datalen >= SHRPX_QUIC_SCIDLEN + 22) { - send_stateless_reset(faddr, datalen, vc.dcid, vc.dcidlen, remote_addr, - local_addr); + if (data.size() >= SHRPX_QUIC_SCIDLEN + 22) { + send_stateless_reset(faddr, data.size(), {vc.dcid, vc.dcidlen}, + remote_addr, local_addr); } } @@ -339,7 +339,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } handler = handle_new_connection(faddr, remote_addr, local_addr, hd, podcid, - token, tokenlen, token_type); + token, token_type); if (handler == nullptr) { return 0; } @@ -347,8 +347,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, handler = (*it).second; } - if (handler->read_quic(faddr, remote_addr, local_addr, pi, data, datalen) != - 0) { + if (handler->read_quic(faddr, remote_addr, local_addr, pi, data) != 0) { delete handler; return 0; } @@ -361,7 +360,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, ClientHandler *QUICConnectionHandler::handle_new_connection( const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_hd &hd, const ngtcp2_cid *odcid, - const uint8_t *token, size_t tokenlen, ngtcp2_token_type token_type) { + std::span<const uint8_t> token, ngtcp2_token_type token_type) { std::array<char, NI_MAXHOST> host; std::array<char, NI_MAXSERV> service; int rv; @@ -412,7 +411,7 @@ ClientHandler *QUICConnectionHandler::handle_new_connection( StringRef{service.data()}, remote_addr.su.sa.sa_family, faddr); auto upstream = std::make_unique<Http3Upstream>(handler.get()); - if (upstream->init(faddr, remote_addr, local_addr, hd, odcid, token, tokenlen, + if (upstream->init(faddr, remote_addr, local_addr, hd, odcid, token, token_type) != 0) { return nullptr; } @@ -450,8 +449,8 @@ uint32_t generate_reserved_version(const Address &addr, uint32_t version) { } // namespace int QUICConnectionHandler::send_retry( - const UpstreamAddr *faddr, uint32_t version, const uint8_t *ini_dcid, - size_t ini_dcidlen, const uint8_t *ini_scid, size_t ini_scidlen, + const UpstreamAddr *faddr, uint32_t version, + std::span<const uint8_t> ini_dcid, std::span<const uint8_t> ini_scid, const Address &remote_addr, const Address &local_addr, size_t max_pktlen) { std::array<char, NI_MAXHOST> host; std::array<char, NI_MAXSERV> port; @@ -476,25 +475,25 @@ int QUICConnectionHandler::send_retry( return -1; } - std::array<uint8_t, NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN> token; - size_t tokenlen; - ngtcp2_cid idcid, iscid; - ngtcp2_cid_init(&idcid, ini_dcid, ini_dcidlen); - ngtcp2_cid_init(&iscid, ini_scid, ini_scidlen); + ngtcp2_cid_init(&idcid, ini_dcid.data(), ini_dcid.size()); + ngtcp2_cid_init(&iscid, ini_scid.data(), ini_scid.size()); + + std::array<uint8_t, NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN> tokenbuf; - if (generate_retry_token(token.data(), tokenlen, version, &remote_addr.su.sa, - remote_addr.len, retry_scid, idcid, - qkm.secret.data(), qkm.secret.size()) != 0) { + auto token = + generate_retry_token(tokenbuf, version, &remote_addr.su.sa, + remote_addr.len, retry_scid, idcid, qkm.secret); + if (!token) { return -1; } std::vector<uint8_t> buf; buf.resize(std::min(max_pktlen, static_cast<size_t>(256))); - auto nwrite = - ngtcp2_crypto_write_retry(buf.data(), buf.size(), version, &iscid, - &retry_scid, &idcid, token.data(), tokenlen); + auto nwrite = ngtcp2_crypto_write_retry(buf.data(), buf.size(), version, + &iscid, &retry_scid, &idcid, + token->data(), token->size()); if (nwrite < 0) { LOG(ERROR) << "ngtcp2_crypto_write_retry: " << ngtcp2_strerror(nwrite); return -1; @@ -503,8 +502,8 @@ int QUICConnectionHandler::send_retry( buf.resize(nwrite); quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, - &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), buf.size(), 0); + &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, buf, + buf.size()); if (generate_quic_hashed_connection_id(idcid, remote_addr, local_addr, idcid) != 0) { @@ -528,13 +527,13 @@ int QUICConnectionHandler::send_retry( } int QUICConnectionHandler::send_version_negotiation( - const UpstreamAddr *faddr, uint32_t version, const uint8_t *ini_dcid, - size_t ini_dcidlen, const uint8_t *ini_scid, size_t ini_scidlen, + const UpstreamAddr *faddr, uint32_t version, + std::span<const uint8_t> ini_dcid, std::span<const uint8_t> ini_scid, const Address &remote_addr, const Address &local_addr) { - std::array<uint32_t, 2> sv{ + auto sv = std::to_array({ generate_reserved_version(remote_addr, version), NGTCP2_PROTO_VER_V1, - }; + }); std::array<uint8_t, NGTCP2_MAX_UDP_PAYLOAD_SIZE> buf; @@ -542,22 +541,25 @@ int QUICConnectionHandler::send_version_negotiation( util::random_bytes(&rand_byte, &rand_byte + 1, worker_->get_randgen()); auto nwrite = ngtcp2_pkt_write_version_negotiation( - buf.data(), buf.size(), rand_byte, ini_scid, ini_scidlen, ini_dcid, - ini_dcidlen, sv.data(), sv.size()); + buf.data(), buf.size(), rand_byte, ini_scid.data(), ini_scid.size(), + ini_dcid.data(), ini_dcid.size(), sv.data(), sv.size()); if (nwrite < 0) { LOG(ERROR) << "ngtcp2_pkt_write_version_negotiation: " << ngtcp2_strerror(nwrite); return -1; } + auto pkt = std::span{std::begin(buf), static_cast<size_t>(nwrite)}; return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), nwrite, 0); + pkt, pkt.size()); } -int QUICConnectionHandler::send_stateless_reset( - const UpstreamAddr *faddr, size_t pktlen, const uint8_t *dcid, - size_t dcidlen, const Address &remote_addr, const Address &local_addr) { +int QUICConnectionHandler::send_stateless_reset(const UpstreamAddr *faddr, + size_t pktlen, + std::span<const uint8_t> dcid, + const Address &remote_addr, + const Address &local_addr) { if (stateless_reset_bucket_ == 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Stateless Reset bucket has been depleted"; @@ -572,25 +574,24 @@ int QUICConnectionHandler::send_stateless_reset( ev_timer_again(worker_->get_loop(), &stateless_reset_bucket_regen_timer_); } - int rv; std::array<uint8_t, NGTCP2_STATELESS_RESET_TOKENLEN> token; ngtcp2_cid cid; - ngtcp2_cid_init(&cid, dcid, dcidlen); + ngtcp2_cid_init(&cid, dcid.data(), dcid.size()); auto conn_handler = worker_->get_connection_handler(); auto &qkms = conn_handler->get_quic_keying_materials(); auto &qkm = qkms->keying_materials.front(); - rv = generate_quic_stateless_reset_token(token.data(), cid, qkm.secret.data(), - qkm.secret.size()); - if (rv != 0) { + if (auto rv = generate_quic_stateless_reset_token( + token.data(), cid, qkm.secret.data(), qkm.secret.size()); + rv != 0) { return -1; } // SCID + minimum expansion - NGTCP2_STATELESS_RESET_TOKENLEN constexpr size_t max_rand_byteslen = - SHRPX_QUIC_SCIDLEN + 22 - NGTCP2_STATELESS_RESET_TOKENLEN; + NGTCP2_MAX_CIDLEN + 22 - NGTCP2_STATELESS_RESET_TOKENLEN; size_t rand_byteslen; @@ -621,12 +622,13 @@ int QUICConnectionHandler::send_stateless_reset( if (LOG_ENABLED(INFO)) { LOG(INFO) << "Send stateless_reset to remote=" << util::to_numeric_addr(&remote_addr) - << " dcid=" << util::format_hex(dcid, dcidlen); + << " dcid=" << util::format_hex(dcid); } + auto pkt = std::span{std::begin(buf), static_cast<size_t>(nwrite)}; return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), nwrite, 0); + pkt, pkt.size()); } int QUICConnectionHandler::send_connection_close( @@ -649,13 +651,16 @@ int QUICConnectionHandler::send_connection_close( LOG(INFO) << "Send Initial CONNECTION_CLOSE with error_code=" << log::hex << error_code << log::dec << " to remote=" << util::to_numeric_addr(&remote_addr) - << " dcid=" << util::format_hex(ini_scid.data, ini_scid.datalen) - << " scid=" << util::format_hex(ini_dcid.data, ini_dcid.datalen); + << " dcid=" + << util::format_hex(std::span{ini_scid.data, ini_scid.datalen}) + << " scid=" + << util::format_hex(std::span{ini_dcid.data, ini_dcid.datalen}); } + auto pkt = std::span{std::begin(buf), static_cast<size_t>(nwrite)}; return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), nwrite, 0); + pkt, pkt.size()); } void QUICConnectionHandler::add_connection_id(const ngtcp2_cid &cid, @@ -735,23 +740,24 @@ CloseWait::~CloseWait() { int CloseWait::handle_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, - const ngtcp2_pkt_info &pi, const uint8_t *data, - size_t datalen) { + const ngtcp2_pkt_info &pi, + std::span<const uint8_t> data) { if (pkt.empty()) { return 0; } ++num_pkts_recv; - bytes_recv += datalen; + bytes_recv += data.size(); if (bytes_sent + pkt.size() > 3 * bytes_recv || next_pkts_recv > num_pkts_recv) { return 0; } - if (quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, - &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - pkt.data(), pkt.size(), 0) != 0) { + auto rv = quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, + &local_addr.su.sa, local_addr.len, + ngtcp2_pkt_info{}, pkt, pkt.size()); + if (rv != 0) { return -1; } diff --git a/src/shrpx_quic_connection_handler.h b/src/shrpx_quic_connection_handler.h index 7f65370..374d84b 100644 --- a/src/shrpx_quic_connection_handler.h +++ b/src/shrpx_quic_connection_handler.h @@ -56,7 +56,7 @@ struct CloseWait { int handle_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen); + std::span<const uint8_t> data); Worker *worker; // Source Connection IDs of the connection. @@ -83,28 +83,25 @@ public: ~QUICConnectionHandler(); int handle_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen); + std::span<const uint8_t> data); // Send Retry packet. |ini_dcid| is the destination Connection ID - // which appeared in Client Initial packet and its length is - // |dcidlen|. |ini_scid| is the source Connection ID which appeared - // in Client Initial packet and its length is |scidlen|. + // which appeared in Client Initial packet. |ini_scid| is the + // source Connection ID which appeared in Client Initial packet. int send_retry(const UpstreamAddr *faddr, uint32_t version, - const uint8_t *ini_dcid, size_t ini_dcidlen, - const uint8_t *ini_scid, size_t ini_scidlen, - const Address &remote_addr, const Address &local_addr, - size_t max_pktlen); + std::span<const uint8_t> ini_dcid, + std::span<const uint8_t> ini_scid, const Address &remote_addr, + const Address &local_addr, size_t max_pktlen); // Send Version Negotiation packet. |ini_dcid| is the destination - // Connection ID which appeared in Client Initial packet and its - // length is |dcidlen|. |ini_scid| is the source Connection ID - // which appeared in Client Initial packet and its length is - // |scidlen|. + // Connection ID which appeared in Client Initial packet. + // |ini_scid| is the source Connection ID which appeared in Client + // Initial packet. int send_version_negotiation(const UpstreamAddr *faddr, uint32_t version, - const uint8_t *ini_dcid, size_t ini_dcidlen, - const uint8_t *ini_scid, size_t ini_scidlen, + std::span<const uint8_t> ini_dcid, + std::span<const uint8_t> ini_scid, const Address &remote_addr, const Address &local_addr); int send_stateless_reset(const UpstreamAddr *faddr, size_t pktlen, - const uint8_t *dcid, size_t dcidlen, + std::span<const uint8_t> dcid, const Address &remote_addr, const Address &local_addr); // Send Initial CONNECTION_CLOSE. |ini_dcid| is the destination @@ -120,8 +117,8 @@ public: ClientHandler * handle_new_connection(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_hd &hd, - const ngtcp2_cid *odcid, const uint8_t *token, - size_t tokenlen, ngtcp2_token_type token_type); + const ngtcp2_cid *odcid, std::span<const uint8_t> token, + ngtcp2_token_type token_type); void add_connection_id(const ngtcp2_cid &cid, ClientHandler *handler); void remove_connection_id(const ngtcp2_cid &cid); diff --git a/src/shrpx_quic_listener.cc b/src/shrpx_quic_listener.cc index 681f605..cf15e2f 100644 --- a/src/shrpx_quic_listener.cc +++ b/src/shrpx_quic_listener.cc @@ -106,10 +106,10 @@ void QUICListener::on_read() { gso_size = static_cast<size_t>(nread); } - auto data = buf.data(); + auto data = std::span{std::begin(buf), static_cast<size_t>(nread)}; for (;;) { - auto datalen = std::min(static_cast<size_t>(nread), gso_size); + auto datalen = std::min(data.size(), gso_size); ++pktcnt; @@ -131,14 +131,12 @@ void QUICListener::on_read() { remote_addr.len = msg.msg_namelen; quic_conn_handler->handle_packet(faddr_, remote_addr, local_addr, pi, - data, datalen); + {std::begin(data), datalen}); - nread -= datalen; - if (nread == 0) { + data = data.subspan(datalen); + if (data.empty()) { break; } - - data += datalen; } } } diff --git a/src/shrpx_router.cc b/src/shrpx_router.cc index d3565db..559b236 100644 --- a/src/shrpx_router.cc +++ b/src/shrpx_router.cc @@ -67,7 +67,7 @@ void Router::add_node(RNode *node, const char *pattern, size_t patlen, ssize_t index, ssize_t wildcard_index) { auto pat = make_string_ref(balloc_, StringRef{pattern, patlen}); auto new_node = - std::make_unique<RNode>(pat.c_str(), pat.size(), index, wildcard_index); + std::make_unique<RNode>(pat.data(), pat.size(), index, wildcard_index); add_next_node(node, std::move(new_node)); } @@ -85,7 +85,7 @@ size_t Router::add_route(const StringRef &pattern, size_t idx, bool wildcard) { for (;;) { auto next_node = find_next_node(node, pattern[i]); if (next_node == nullptr) { - add_node(node, pattern.c_str() + i, pattern.size() - i, index, + add_node(node, pattern.data() + i, pattern.size() - i, index, wildcard_index); return idx; } @@ -93,7 +93,7 @@ size_t Router::add_route(const StringRef &pattern, size_t idx, bool wildcard) { node = next_node; auto slen = pattern.size() - i; - auto s = pattern.c_str() + i; + auto s = pattern.data() + i; auto n = std::min(node->len, slen); size_t j; for (j = 0; j < n && node->s[j] == s[j]; ++j) @@ -151,7 +151,7 @@ size_t Router::add_route(const StringRef &pattern, size_t idx, bool wildcard) { i += j; assert(pattern.size() > i); - add_node(node, pattern.c_str() + i, pattern.size() - i, index, + add_node(node, pattern.data() + i, pattern.size() - i, index, wildcard_index); return idx; diff --git a/src/shrpx_router_test.cc b/src/shrpx_router_test.cc index a9625a0..0fc4a3a 100644 --- a/src/shrpx_router_test.cc +++ b/src/shrpx_router_test.cc @@ -51,16 +51,16 @@ struct Pattern { void test_shrpx_router_match(void) { auto patterns = std::vector<Pattern>{ - {StringRef::from_lit("nghttp2.org/"), 0}, - {StringRef::from_lit("nghttp2.org/alpha"), 1}, - {StringRef::from_lit("nghttp2.org/alpha/"), 2}, - {StringRef::from_lit("nghttp2.org/alpha/bravo/"), 3}, - {StringRef::from_lit("www.nghttp2.org/alpha/"), 4}, - {StringRef::from_lit("/alpha"), 5}, - {StringRef::from_lit("example.com/alpha/"), 6}, - {StringRef::from_lit("nghttp2.org/alpha/bravo2/"), 7}, - {StringRef::from_lit("www2.nghttp2.org/alpha/"), 8}, - {StringRef::from_lit("www2.nghttp2.org/alpha2/"), 9}, + {"nghttp2.org/"_sr, 0}, + {"nghttp2.org/alpha"_sr, 1}, + {"nghttp2.org/alpha/"_sr, 2}, + {"nghttp2.org/alpha/bravo/"_sr, 3}, + {"www.nghttp2.org/alpha/"_sr, 4}, + {"/alpha"_sr, 5}, + {"example.com/alpha/"_sr, 6}, + {"nghttp2.org/alpha/bravo2/"_sr, 7}, + {"www2.nghttp2.org/alpha/"_sr, 8}, + {"www2.nghttp2.org/alpha2/"_sr, 9}, }; Router router; @@ -71,56 +71,49 @@ void test_shrpx_router_match(void) { ssize_t idx; - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/")); + idx = router.match("nghttp2.org"_sr, "/"_sr); assert_ssize(0, ==, idx); - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha")); + idx = router.match("nghttp2.org"_sr, "/alpha"_sr); assert_ssize(1, ==, idx); - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/")); + idx = router.match("nghttp2.org"_sr, "/alpha/"_sr); assert_ssize(2, ==, idx); - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie")); + idx = router.match("nghttp2.org"_sr, "/alpha/charlie"_sr); assert_ssize(2, ==, idx); - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/")); + idx = router.match("nghttp2.org"_sr, "/alpha/bravo/"_sr); assert_ssize(3, ==, idx); // matches pattern when last '/' is missing in path - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo")); + idx = router.match("nghttp2.org"_sr, "/alpha/bravo"_sr); assert_ssize(3, ==, idx); - idx = router.match(StringRef::from_lit("www2.nghttp2.org"), - StringRef::from_lit("/alpha")); + idx = router.match("www2.nghttp2.org"_sr, "/alpha"_sr); assert_ssize(8, ==, idx); - idx = router.match(StringRef{}, StringRef::from_lit("/alpha")); + idx = router.match(StringRef{}, "/alpha"_sr); assert_ssize(5, ==, idx); } void test_shrpx_router_match_wildcard(void) { - constexpr auto patterns = std::array<Pattern, 6>{{ - {StringRef::from_lit("nghttp2.org/"), 0}, - {StringRef::from_lit("nghttp2.org/"), 1, true}, - {StringRef::from_lit("nghttp2.org/alpha/"), 2}, - {StringRef::from_lit("nghttp2.org/alpha/"), 3, true}, - {StringRef::from_lit("nghttp2.org/bravo"), 4}, - {StringRef::from_lit("nghttp2.org/bravo"), 5, true}, - }}; + constexpr auto patterns = std::to_array<Pattern>({ + {"nghttp2.org/"_sr, 0}, + {"nghttp2.org/"_sr, 1, true}, + {"nghttp2.org/alpha/"_sr, 2}, + {"nghttp2.org/alpha/"_sr, 3, true}, + {"nghttp2.org/bravo"_sr, 4}, + {"nghttp2.org/bravo"_sr, 5, true}, + }); Router router; @@ -128,49 +121,31 @@ void test_shrpx_router_match_wildcard(void) { router.add_route(p.pattern, p.idx, p.wildcard); } - assert_ssize(0, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/"))); + assert_ssize(0, ==, router.match("nghttp2.org"_sr, "/"_sr)); - assert_ssize(1, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/a"))); + assert_ssize(1, ==, router.match("nghttp2.org"_sr, "/a"_sr)); - assert_ssize(1, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/charlie"))); + assert_ssize(1, ==, router.match("nghttp2.org"_sr, "/charlie"_sr)); - assert_ssize(2, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha"))); + assert_ssize(2, ==, router.match("nghttp2.org"_sr, "/alpha"_sr)); - assert_ssize(2, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/"))); + assert_ssize(2, ==, router.match("nghttp2.org"_sr, "/alpha/"_sr)); - assert_ssize(3, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/b"))); + assert_ssize(3, ==, router.match("nghttp2.org"_sr, "/alpha/b"_sr)); - assert_ssize(4, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/bravo"))); + assert_ssize(4, ==, router.match("nghttp2.org"_sr, "/bravo"_sr)); - assert_ssize(5, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/bravocharlie"))); + assert_ssize(5, ==, router.match("nghttp2.org"_sr, "/bravocharlie"_sr)); - assert_ssize(5, ==, - router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/bravo/"))); + assert_ssize(5, ==, router.match("nghttp2.org"_sr, "/bravo/"_sr)); } void test_shrpx_router_match_prefix(void) { auto patterns = std::vector<Pattern>{ - {StringRef::from_lit("gro.2ptthgn."), 0}, - {StringRef::from_lit("gro.2ptthgn.www."), 1}, - {StringRef::from_lit("gro.2ptthgn.gmi."), 2}, - {StringRef::from_lit("gro.2ptthgn.gmi.ahpla."), 3}, + {"gro.2ptthgn."_sr, 0}, + {"gro.2ptthgn.www."_sr, 1}, + {"gro.2ptthgn.gmi."_sr, 2}, + {"gro.2ptthgn.gmi.ahpla."_sr, 3}, }; Router router; @@ -185,19 +160,17 @@ void test_shrpx_router_match_prefix(void) { node = nullptr; - idx = router.match_prefix(&nread, &node, - StringRef::from_lit("gro.2ptthgn.gmi.ahpla.ovarb")); + idx = router.match_prefix(&nread, &node, "gro.2ptthgn.gmi.ahpla.ovarb"_sr); assert_ssize(0, ==, idx); assert_size(12, ==, nread); - idx = router.match_prefix(&nread, &node, - StringRef::from_lit("gmi.ahpla.ovarb")); + idx = router.match_prefix(&nread, &node, "gmi.ahpla.ovarb"_sr); assert_ssize(2, ==, idx); assert_size(4, ==, nread); - idx = router.match_prefix(&nread, &node, StringRef::from_lit("ahpla.ovarb")); + idx = router.match_prefix(&nread, &node, "ahpla.ovarb"_sr); assert_ssize(3, ==, idx); assert_ssize(6, ==, nread); diff --git a/src/shrpx_signal.cc b/src/shrpx_signal.cc index 63fcc07..cfc4fc1 100644 --- a/src/shrpx_signal.cc +++ b/src/shrpx_signal.cc @@ -110,13 +110,13 @@ int signal_set_handler(void (*handler)(int), Signals &&sigs) { } // namespace namespace { -constexpr auto main_proc_ign_signals = std::array<int, 1>{SIGPIPE}; +constexpr auto main_proc_ign_signals = std::to_array({SIGPIPE}); } // namespace namespace { constexpr auto worker_proc_ign_signals = - std::array<int, 5>{REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL, - GRACEFUL_SHUTDOWN_SIGNAL, RELOAD_SIGNAL, SIGPIPE}; + std::to_array({REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL, + GRACEFUL_SHUTDOWN_SIGNAL, RELOAD_SIGNAL, SIGPIPE}); } // namespace int shrpx_signal_set_main_proc_ign_handler() { diff --git a/src/shrpx_tls.cc b/src/shrpx_tls.cc index 10bbbf2..00cf1ca 100644 --- a/src/shrpx_tls.cc +++ b/src/shrpx_tls.cc @@ -157,7 +157,7 @@ int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) { return 0; } // Copy string including last '\0'. - memcpy(buf, config->tls.private_key_passwd.c_str(), len + 1); + memcpy(buf, config->tls.private_key_passwd.data(), len + 1); return len; } } // namespace @@ -166,8 +166,7 @@ namespace { std::shared_ptr<std::vector<uint8_t>> get_ocsp_data(TLSContextData *tls_ctx_data) { #ifdef HAVE_ATOMIC_STD_SHARED_PTR - return std::atomic_load_explicit(&tls_ctx_data->ocsp_data, - std::memory_order_acquire); + return tls_ctx_data->ocsp_data.load(std::memory_order_acquire); #else // !HAVE_ATOMIC_STD_SHARED_PTR std::lock_guard<std::mutex> g(tls_ctx_data->mu); return tls_ctx_data->ocsp_data; @@ -214,7 +213,7 @@ int servername_callback(SSL *ssl, int *al, void *arg) { return SSL_TLSEXT_ERR_NOACK; } - std::array<uint8_t, NI_MAXHOST> buf; + std::array<char, NI_MAXHOST> buf; auto end_buf = std::copy_n(rawhost, len, std::begin(buf)); @@ -366,7 +365,7 @@ int ocsp_resp_cb(SSL *ssl, void *arg) { #endif // NGHTTP2_OPENSSL_IS_BORINGSSL constexpr auto MEMCACHED_SESSION_CACHE_KEY_PREFIX = - StringRef::from_lit("nghttpx:tls-session-cache:"); + "nghttpx:tls-session-cache:"_sr; namespace { int tls_session_client_new_cb(SSL *ssl, SSL_SESSION *session) { @@ -402,14 +401,15 @@ int tls_session_new_cb(SSL *ssl, SSL_SESSION *session) { id = SSL_SESSION_get_id(session, &idlen); if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memcached: cache session, id=" << util::format_hex(id, idlen); + LOG(INFO) << "Memcached: cache session, id=" + << util::format_hex(std::span{id, idlen}); } auto req = std::make_unique<MemcachedRequest>(); req->op = MemcachedOp::ADD; - req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str(); + req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX; req->key += - util::format_hex(balloc, StringRef{id, static_cast<size_t>(idlen)}); + util::format_hex(balloc, std::span{id, static_cast<size_t>(idlen)}); auto sessionlen = i2d_SSL_SESSION(session, nullptr); req->value.resize(sessionlen); @@ -454,7 +454,7 @@ SSL_SESSION *tls_session_get_cb(SSL *ssl, const unsigned char *id, int idlen, if (conn->tls.cached_session) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Memcached: found cached session, id=" - << util::format_hex(id, idlen); + << util::format_hex(std::span{id, static_cast<size_t>(idlen)}); } // This is required, without this, memory leak occurs. @@ -467,14 +467,14 @@ SSL_SESSION *tls_session_get_cb(SSL *ssl, const unsigned char *id, int idlen, if (LOG_ENABLED(INFO)) { LOG(INFO) << "Memcached: get cached session, id=" - << util::format_hex(id, idlen); + << util::format_hex(std::span{id, static_cast<size_t>(idlen)}); } auto req = std::make_unique<MemcachedRequest>(); req->op = MemcachedOp::GET; - req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str(); + req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX; req->key += - util::format_hex(balloc, StringRef{id, static_cast<size_t>(idlen)}); + util::format_hex(balloc, std::span{id, static_cast<size_t>(idlen)}); req->cb = [conn](MemcachedRequest *, MemcachedResult res) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Memcached: returned status code " @@ -560,14 +560,14 @@ int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv, EVP_EncryptInit_ex(ctx, get_config()->tls.ticket.cipher, nullptr, key.data.enc_key.data(), iv); #if OPENSSL_3_0_0_API - std::array<OSSL_PARAM, 3> params{ + auto params = std::to_array({ OSSL_PARAM_construct_octet_string( OSSL_MAC_PARAM_KEY, key.data.hmac_key.data(), key.hmac_keylen), OSSL_PARAM_construct_utf8_string( OSSL_MAC_PARAM_DIGEST, const_cast<char *>(EVP_MD_get0_name(key.hmac)), 0), OSSL_PARAM_construct_end(), - }; + }); if (!EVP_MAC_CTX_set_params(hctx, params.data())) { if (LOG_ENABLED(INFO)) { CLOG(INFO, handler) << "EVP_MAC_CTX_set_params failed"; @@ -593,26 +593,27 @@ int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv, if (i == keys.size()) { if (LOG_ENABLED(INFO)) { CLOG(INFO, handler) << "session ticket key " - << util::format_hex(key_name, 16) << " not found"; + << util::format_hex(std::span{key_name, 16}) + << " not found"; } return 0; } if (LOG_ENABLED(INFO)) { CLOG(INFO, handler) << "decrypt session ticket key: " - << util::format_hex(key_name, 16); + << util::format_hex(std::span{key_name, 16}); } auto &key = keys[i]; #if OPENSSL_3_0_0_API - std::array<OSSL_PARAM, 3> params{ + auto params = std::to_array({ OSSL_PARAM_construct_octet_string( OSSL_MAC_PARAM_KEY, key.data.hmac_key.data(), key.hmac_keylen), OSSL_PARAM_construct_utf8_string( OSSL_MAC_PARAM_DIGEST, const_cast<char *>(EVP_MD_get0_name(key.hmac)), 0), OSSL_PARAM_construct_end(), - }; + }); if (!EVP_MAC_CTX_set_params(hctx, params.data())) { if (LOG_ENABLED(INFO)) { CLOG(INFO, handler) << "EVP_MAC_CTX_set_params failed"; @@ -676,7 +677,7 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out, auto proto_len = *p; if (proto_id + proto_len <= end && - util::streq(target_proto_id, StringRef{proto_id, proto_len})) { + target_proto_id == StringRef{proto_id, proto_len}) { *out = reinterpret_cast<const unsigned char *>(proto_id); *outlen = proto_len; @@ -698,8 +699,8 @@ int quic_alpn_select_proto_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { constexpr StringRef alpnlist[] = { - StringRef::from_lit("h3"), - StringRef::from_lit("h3-29"), + "h3"_sr, + "h3-29"_sr, }; for (auto &alpn : alpnlist) { @@ -929,9 +930,9 @@ struct TLSProtocol { }; constexpr TLSProtocol TLS_PROTOS[] = { - TLSProtocol{StringRef::from_lit("TLSv1.2"), SSL_OP_NO_TLSv1_2}, - TLSProtocol{StringRef::from_lit("TLSv1.1"), SSL_OP_NO_TLSv1_1}, - TLSProtocol{StringRef::from_lit("TLSv1.0"), SSL_OP_NO_TLSv1}}; + TLSProtocol{"TLSv1.2"_sr, SSL_OP_NO_TLSv1_2}, + TLSProtocol{"TLSv1.1"_sr, SSL_OP_NO_TLSv1_1}, + TLSProtocol{"TLSv1.0"_sr, SSL_OP_NO_TLSv1}}; long int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list) { long int res = 0; @@ -1008,14 +1009,14 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count()); - if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.c_str()) == 0) { + if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.data()) == 0) { LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } #if defined(NGHTTP2_GENUINE_OPENSSL) || defined(NGHTTP2_OPENSSL_IS_LIBRESSL) - if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) { + if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.data()) == 0) { LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); DIE(); @@ -1023,7 +1024,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_LIBRESSL #ifndef OPENSSL_NO_EC - if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) { + if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.data()) != 1) { LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves << " failed"; DIE(); @@ -1032,7 +1033,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, if (!tlsconf.dh_param_file.empty()) { // Read DH parameters from file - auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "rb"); + auto bio = BIO_new_file(tlsconf.dh_param_file.data(), "rb"); if (bio == nullptr) { LOG(FATAL) << "BIO_new_file() failed: " << ERR_error_string(ERR_get_error(), nullptr); @@ -1076,7 +1077,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, } if (!tlsconf.cacert.empty()) { - if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.c_str(), + if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.data(), nullptr) != 1) { LOG(FATAL) << "Could not load trusted ca certificates from " << tlsconf.cacert << ": " @@ -1119,7 +1120,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, if (tlsconf.client_verify.enabled) { if (!tlsconf.client_verify.cacert.empty()) { if (SSL_CTX_load_verify_locations( - ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) { + ssl_ctx, tlsconf.client_verify.cacert.data(), nullptr) != 1) { LOG(FATAL) << "Could not load trusted ca certificates from " << tlsconf.client_verify.cacert << ": " @@ -1130,7 +1131,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, // error even though it returns success. See // http://forum.nginx.org/read.php?29,242540 ERR_clear_error(); - auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str()); + auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.data()); if (!list) { LOG(FATAL) << "Could not load ca certificates from " << tlsconf.client_verify.cacert << ": " @@ -1282,14 +1283,14 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count()); - if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.c_str()) == 0) { + if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.data()) == 0) { LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } # if defined(NGHTTP2_GENUINE_OPENSSL) || defined(NGHTTP2_OPENSSL_IS_LIBRESSL) - if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) { + if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.data()) == 0) { LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); DIE(); @@ -1297,7 +1298,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, # endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_LIBRESSL # ifndef OPENSSL_NO_EC - if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) { + if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.data()) != 1) { LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves << " failed"; DIE(); @@ -1306,7 +1307,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, if (!tlsconf.dh_param_file.empty()) { // Read DH parameters from file - auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "rb"); + auto bio = BIO_new_file(tlsconf.dh_param_file.data(), "rb"); if (bio == nullptr) { LOG(FATAL) << "BIO_new_file() failed: " << ERR_error_string(ERR_get_error(), nullptr); @@ -1350,7 +1351,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, } if (!tlsconf.cacert.empty()) { - if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.c_str(), + if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.data(), nullptr) != 1) { LOG(FATAL) << "Could not load trusted ca certificates from " << tlsconf.cacert << ": " @@ -1393,7 +1394,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, if (tlsconf.client_verify.enabled) { if (!tlsconf.client_verify.cacert.empty()) { if (SSL_CTX_load_verify_locations( - ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) { + ssl_ctx, tlsconf.client_verify.cacert.data(), nullptr) != 1) { LOG(FATAL) << "Could not load trusted ca certificates from " << tlsconf.client_verify.cacert << ": " @@ -1404,7 +1405,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, // error even though it returns success. See // http://forum.nginx.org/read.php?29,242540 ERR_clear_error(); - auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str()); + auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.data()); if (!list) { LOG(FATAL) << "Could not load ca certificates from " << tlsconf.client_verify.cacert << ": " @@ -1533,14 +1534,14 @@ SSL_CTX *create_ssl_client_context( DIE(); } - if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.client.ciphers.c_str()) == 0) { + if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.client.ciphers.data()) == 0) { LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.client.ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } #if defined(NGHTTP2_GENUINE_OPENSSL) || defined(NGHTTP2_OPENSSL_IS_LIBRESSL) - if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.client.tls13_ciphers.c_str()) == + if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.client.tls13_ciphers.data()) == 0) { LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.client.tls13_ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); @@ -1556,7 +1557,7 @@ SSL_CTX *create_ssl_client_context( } if (!cacert.empty()) { - if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.c_str(), nullptr) != 1) { + if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.data(), nullptr) != 1) { LOG(FATAL) << "Could not load trusted ca certificates from " << cacert << ": " << ERR_error_string(ERR_get_error(), nullptr); @@ -1569,7 +1570,7 @@ SSL_CTX *create_ssl_client_context( } if (!cert_file.empty()) { - if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.c_str()) != 1) { + if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.data()) != 1) { LOG(FATAL) << "Could not load client certificate from " << cert_file << ": " << ERR_error_string(ERR_get_error(), nullptr); @@ -1579,7 +1580,7 @@ SSL_CTX *create_ssl_client_context( if (!private_key_file.empty()) { #ifndef HAVE_NEVERBLEED - if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.c_str(), + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.data(), SSL_FILETYPE_PEM) != 1) { LOG(FATAL) << "Could not load client private key from " << private_key_file << ": " @@ -1588,7 +1589,7 @@ SSL_CTX *create_ssl_client_context( } #else // HAVE_NEVERBLEED std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf; - if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.c_str(), + if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.data(), errbuf.data()) != 1) { LOG(FATAL) << "neverbleed_load_private_key_file: could not load client " "private key from " @@ -1684,7 +1685,7 @@ bool tls_hostname_match(const StringRef &pattern, const StringRef &hostname) { if (ptLeftLabelEnd == std::end(pattern) || std::find(ptLeftLabelEnd + 1, std::end(pattern), '.') == std::end(pattern) || - ptLeftLabelEnd < ptWildcard || util::istarts_with_l(pattern, "xn--")) { + ptLeftLabelEnd < ptWildcard || util::istarts_with(pattern, "xn--"_sr)) { wildcardEnabled = false; } @@ -1801,8 +1802,8 @@ int verify_numeric_hostname(X509 *cert, const StringRef &hostname, } // cn is not NULL terminated - auto rv = util::streq(hostname, cn); - OPENSSL_free(const_cast<char *>(cn.c_str())); + auto rv = hostname == cn; + OPENSSL_free(const_cast<char *>(cn.data())); if (rv) { return 0; @@ -1867,15 +1868,15 @@ int verify_dns_hostname(X509 *cert, const StringRef &hostname) { if (cn[cn.size() - 1] == '.') { if (cn.size() == 1) { - OPENSSL_free(const_cast<char *>(cn.c_str())); + OPENSSL_free(const_cast<char *>(cn.data())); return -1; } - cn = StringRef{cn.c_str(), cn.size() - 1}; + cn = StringRef{cn.data(), cn.size() - 1}; } auto rv = tls_hostname_match(cn, hostname); - OPENSSL_free(const_cast<char *>(cn.c_str())); + OPENSSL_free(const_cast<char *>(cn.data())); return rv ? 0 : -1; } @@ -1883,7 +1884,7 @@ int verify_dns_hostname(X509 *cert, const StringRef &hostname) { namespace { int verify_hostname(X509 *cert, const StringRef &hostname, const Address *addr) { - if (util::numeric_host(hostname.c_str())) { + if (util::numeric_host(hostname.data())) { return verify_numeric_hostname(cert, hostname, addr); } @@ -1923,7 +1924,7 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr) { CertLookupTree::CertLookupTree() {} ssize_t CertLookupTree::add_cert(const StringRef &hostname, size_t idx) { - std::array<uint8_t, NI_MAXHOST> buf; + std::array<char, NI_MAXHOST> buf; // NI_MAXHOST includes terminal NULL byte if (hostname.empty() || hostname.size() + 1 > buf.size()) { @@ -1975,7 +1976,7 @@ ssize_t CertLookupTree::add_cert(const StringRef &hostname, size_t idx) { } ssize_t CertLookupTree::lookup(const StringRef &hostname) { - std::array<uint8_t, NI_MAXHOST> buf; + std::array<char, NI_MAXHOST> buf; // NI_MAXHOST includes terminal NULL byte if (hostname.empty() || hostname.size() + 1 > buf.size()) { @@ -2024,9 +2025,7 @@ ssize_t CertLookupTree::lookup(const StringRef &hostname) { continue; } - auto prefixlen = - wprefix.prefix.size() + - (reinterpret_cast<const uint8_t *>(&rev_host[0]) - &buf[0]); + auto prefixlen = wprefix.prefix.size() + (&rev_host[0] - &buf[0]); // Breaking a tie with longer suffix if (prefixlen < best_prefixlen) { @@ -2049,7 +2048,7 @@ void CertLookupTree::dump() const { int cert_lookup_tree_add_ssl_ctx( CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, SSL_CTX *ssl_ctx) { - std::array<uint8_t, NI_MAXHOST> buf; + std::array<char, NI_MAXHOST> buf; auto cert = SSL_CTX_get0_certificate(ssl_ctx); auto altnames = static_cast<GENERAL_NAMES *>( @@ -2121,17 +2120,17 @@ int cert_lookup_tree_add_ssl_ctx( if (cn[cn.size() - 1] == '.') { if (cn.size() == 1) { - OPENSSL_free(const_cast<char *>(cn.c_str())); + OPENSSL_free(const_cast<char *>(cn.data())); return 0; } - cn = StringRef{cn.c_str(), cn.size() - 1}; + cn = StringRef{cn.data(), cn.size() - 1}; } auto end_buf = std::copy(std::begin(cn), std::end(cn), std::begin(buf)); - OPENSSL_free(const_cast<char *>(cn.c_str())); + OPENSSL_free(const_cast<char *>(cn.data())); util::inp_strlower(std::begin(buf), end_buf); @@ -2154,7 +2153,7 @@ int cert_lookup_tree_add_ssl_ctx( bool in_proto_list(const std::vector<StringRef> &protos, const StringRef &needle) { for (auto &proto : protos) { - if (util::streq(proto, needle)) { + if (proto == needle) { return true; } } @@ -2210,8 +2209,8 @@ setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx, auto &tlsconf = config->tls; - auto ssl_ctx = create_ssl_context(tlsconf.private_key_file.c_str(), - tlsconf.cert_file.c_str(), tlsconf.sct_data + auto ssl_ctx = create_ssl_context(tlsconf.private_key_file.data(), + tlsconf.cert_file.data(), tlsconf.sct_data #ifdef HAVE_NEVERBLEED , nb @@ -2228,8 +2227,8 @@ setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx, } for (auto &c : tlsconf.subcerts) { - auto ssl_ctx = create_ssl_context(c.private_key_file.c_str(), - c.cert_file.c_str(), c.sct_data + auto ssl_ctx = create_ssl_context(c.private_key_file.data(), + c.cert_file.data(), c.sct_data #ifdef HAVE_NEVERBLEED , nb @@ -2266,8 +2265,8 @@ SSL_CTX *setup_quic_server_ssl_context( auto &tlsconf = config->tls; auto ssl_ctx = - create_quic_ssl_context(tlsconf.private_key_file.c_str(), - tlsconf.cert_file.c_str(), tlsconf.sct_data + create_quic_ssl_context(tlsconf.private_key_file.data(), + tlsconf.cert_file.data(), tlsconf.sct_data # ifdef HAVE_NEVERBLEED , nb @@ -2284,8 +2283,8 @@ SSL_CTX *setup_quic_server_ssl_context( } for (auto &c : tlsconf.subcerts) { - auto ssl_ctx = create_quic_ssl_context(c.private_key_file.c_str(), - c.cert_file.c_str(), c.sct_data + auto ssl_ctx = create_quic_ssl_context(c.private_key_file.data(), + c.cert_file.data(), c.sct_data # ifdef HAVE_NEVERBLEED , nb @@ -2378,17 +2377,17 @@ SSL_SESSION *reuse_tls_session(const TLSSessionCache &cache) { int proto_version_from_string(const StringRef &v) { #ifdef TLS1_3_VERSION - if (util::strieq_l("TLSv1.3", v)) { + if (util::strieq("TLSv1.3"_sr, v)) { return TLS1_3_VERSION; } #endif // TLS1_3_VERSION - if (util::strieq_l("TLSv1.2", v)) { + if (util::strieq("TLSv1.2"_sr, v)) { return TLS1_2_VERSION; } - if (util::strieq_l("TLSv1.1", v)) { + if (util::strieq("TLSv1.1"_sr, v)) { return TLS1_1_VERSION; } - if (util::strieq_l("TLSv1.0", v)) { + if (util::strieq("TLSv1.0"_sr, v)) { return TLS1_VERSION; } return -1; @@ -2500,9 +2499,9 @@ StringRef get_x509_name(BlockAllocator &balloc, X509_NAME *nm) { } auto iov = make_byte_ref(balloc, slen + 1); - BIO_read(b, iov.base, slen); - iov.base[slen] = '\0'; - return StringRef{iov.base, static_cast<size_t>(slen)}; + BIO_read(b, iov.data(), slen); + iov[slen] = '\0'; + return StringRef{iov.data(), static_cast<size_t>(slen)}; } } // namespace @@ -2526,7 +2525,7 @@ StringRef get_x509_serial(BlockAllocator &balloc, X509 *x) { auto n = BN_bn2bin(bn, b.data()); assert(n <= 20); - return util::format_hex(balloc, StringRef{b.data(), static_cast<size_t>(n)}); + return util::format_hex(balloc, std::span{b.data(), static_cast<size_t>(n)}); } namespace { diff --git a/src/shrpx_tls.h b/src/shrpx_tls.h index f740507..8ca165c 100644 --- a/src/shrpx_tls.h +++ b/src/shrpx_tls.h @@ -72,7 +72,11 @@ struct TLSContextData { std::mutex mu; #endif // !HAVE_ATOMIC_STD_SHARED_PTR // OCSP response +#ifdef HAVE_ATOMIC_STD_SHARED_PTR + std::atomic<std::shared_ptr<std::vector<uint8_t>>> ocsp_data; +#else // !HAVE_ATOMIC_STD_SHARED_PTR std::shared_ptr<std::vector<uint8_t>> ocsp_data; +#endif // !HAVE_ATOMIC_STD_SHARED_PTR // Path to certificate file const char *cert_file; diff --git a/src/shrpx_tls_test.cc b/src/shrpx_tls_test.cc index 04d16da..013c347 100644 --- a/src/shrpx_tls_test.cc +++ b/src/shrpx_tls_test.cc @@ -54,16 +54,16 @@ void test_shrpx_tls_create_lookup_tree(void) { auto tree = std::make_unique<tls::CertLookupTree>(); constexpr StringRef hostnames[] = { - StringRef::from_lit("example.com"), // 0 - StringRef::from_lit("www.example.org"), // 1 - StringRef::from_lit("*www.example.org"), // 2 - StringRef::from_lit("xy*.host.domain"), // 3 - StringRef::from_lit("*yy.host.domain"), // 4 - StringRef::from_lit("nghttp2.sourceforge.net"), // 5 - StringRef::from_lit("sourceforge.net"), // 6 - StringRef::from_lit("sourceforge.net"), // 7, duplicate - StringRef::from_lit("*.foo.bar"), // 8, oo.bar is suffix of *.foo.bar - StringRef::from_lit("oo.bar") // 9 + "example.com"_sr, // 0 + "www.example.org"_sr, // 1 + "*www.example.org"_sr, // 2 + "xy*.host.domain"_sr, // 3 + "*yy.host.domain"_sr, // 4 + "nghttp2.sourceforge.net"_sr, // 5 + "sourceforge.net"_sr, // 6 + "sourceforge.net"_sr, // 7, duplicate + "*.foo.bar"_sr, // 8, oo.bar is suffix of *.foo.bar + "oo.bar"_sr // 9 }; auto num = array_size(hostnames); @@ -75,13 +75,13 @@ void test_shrpx_tls_create_lookup_tree(void) { assert_ssize(0, ==, tree->lookup(hostnames[0])); assert_ssize(1, ==, tree->lookup(hostnames[1])); - assert_ssize(2, ==, tree->lookup(StringRef::from_lit("2www.example.org"))); - assert_ssize(-1, ==, tree->lookup(StringRef::from_lit("www2.example.org"))); - assert_ssize(3, ==, tree->lookup(StringRef::from_lit("xy1.host.domain"))); + assert_ssize(2, ==, tree->lookup("2www.example.org"_sr)); + assert_ssize(-1, ==, tree->lookup("www2.example.org"_sr)); + assert_ssize(3, ==, tree->lookup("xy1.host.domain"_sr)); // Does not match *yy.host.domain, because * must match at least 1 // character. - assert_ssize(-1, ==, tree->lookup(StringRef::from_lit("yy.host.domain"))); - assert_ssize(4, ==, tree->lookup(StringRef::from_lit("xyy.host.domain"))); + assert_ssize(-1, ==, tree->lookup("yy.host.domain"_sr)); + assert_ssize(4, ==, tree->lookup("xyy.host.domain"_sr)); assert_ssize(-1, ==, tree->lookup(StringRef{})); assert_ssize(5, ==, tree->lookup(hostnames[5])); assert_ssize(6, ==, tree->lookup(hostnames[6])); @@ -89,14 +89,14 @@ void test_shrpx_tls_create_lookup_tree(void) { for (int i = 0; i < 7; ++i) { assert_ssize(-1, ==, tree->lookup(StringRef{h6 + i, str_size(h6) - i})); } - assert_ssize(8, ==, tree->lookup(StringRef::from_lit("x.foo.bar"))); + assert_ssize(8, ==, tree->lookup("x.foo.bar"_sr)); assert_ssize(9, ==, tree->lookup(hostnames[9])); constexpr StringRef names[] = { - StringRef::from_lit("rab"), // 1 - StringRef::from_lit("zab"), // 2 - StringRef::from_lit("zzub"), // 3 - StringRef::from_lit("ab") // 4 + "rab"_sr, // 1 + "zab"_sr, // 2 + "zzub"_sr, // 3 + "ab"_sr // 4 }; num = array_size(names); @@ -169,12 +169,11 @@ void test_shrpx_tls_cert_lookup_tree_add_ssl_ctx(void) { assert_int(0, ==, rv); - assert_ssize(-1, ==, - tree.lookup(StringRef::from_lit("not-used.nghttp2.org"))); - assert_ssize(0, ==, tree.lookup(StringRef::from_lit("test.nghttp2.org"))); - assert_ssize(1, ==, tree.lookup(StringRef::from_lit("w.test.nghttp2.org"))); - assert_ssize(2, ==, tree.lookup(StringRef::from_lit("www.test.nghttp2.org"))); - assert_ssize(3, ==, tree.lookup(StringRef::from_lit("test.example.com"))); + assert_ssize(-1, ==, tree.lookup("not-used.nghttp2.org"_sr)); + assert_ssize(0, ==, tree.lookup("test.nghttp2.org"_sr)); + assert_ssize(1, ==, tree.lookup("w.test.nghttp2.org"_sr)); + assert_ssize(2, ==, tree.lookup("www.test.nghttp2.org"_sr)); + assert_ssize(3, ==, tree.lookup("test.example.com"_sr)); } template <size_t N, size_t M> @@ -249,11 +248,10 @@ static Address parse_addr(const char *ipaddr) { void test_shrpx_tls_verify_numeric_hostname(void) { { // Successful IPv4 address match in SAN - static constexpr char ipaddr[] = "127.0.0.1"; + static constexpr auto ipaddr = "127.0.0.1"_sr; auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/verify_hostname.crt"); - auto addr = parse_addr(ipaddr); - auto rv = - tls::verify_numeric_hostname(cert, StringRef::from_lit(ipaddr), &addr); + auto addr = parse_addr(ipaddr.data()); + auto rv = tls::verify_numeric_hostname(cert, ipaddr, &addr); assert_int(0, ==, rv); @@ -262,11 +260,10 @@ void test_shrpx_tls_verify_numeric_hostname(void) { { // Successful IPv6 address match in SAN - static constexpr char ipaddr[] = "::1"; + static constexpr auto ipaddr = "::1"_sr; auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/verify_hostname.crt"); - auto addr = parse_addr(ipaddr); - auto rv = - tls::verify_numeric_hostname(cert, StringRef::from_lit(ipaddr), &addr); + auto addr = parse_addr(ipaddr.data()); + auto rv = tls::verify_numeric_hostname(cert, ipaddr, &addr); assert_int(0, ==, rv); @@ -275,11 +272,10 @@ void test_shrpx_tls_verify_numeric_hostname(void) { { // Unsuccessful IPv4 address match in SAN - static constexpr char ipaddr[] = "192.168.0.127"; + static constexpr auto ipaddr = "192.168.0.127"_sr; auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/verify_hostname.crt"); - auto addr = parse_addr(ipaddr); - auto rv = - tls::verify_numeric_hostname(cert, StringRef::from_lit(ipaddr), &addr); + auto addr = parse_addr(ipaddr.data()); + auto rv = tls::verify_numeric_hostname(cert, ipaddr, &addr); assert_int(-1, ==, rv); @@ -288,11 +284,10 @@ void test_shrpx_tls_verify_numeric_hostname(void) { { // CommonName is not used if SAN is available - static constexpr char ipaddr[] = "192.168.0.1"; + static constexpr auto ipaddr = "192.168.0.1"_sr; auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/ipaddr.crt"); - auto addr = parse_addr(ipaddr); - auto rv = - tls::verify_numeric_hostname(cert, StringRef::from_lit(ipaddr), &addr); + auto addr = parse_addr(ipaddr.data()); + auto rv = tls::verify_numeric_hostname(cert, ipaddr, &addr); assert_int(-1, ==, rv); @@ -301,11 +296,10 @@ void test_shrpx_tls_verify_numeric_hostname(void) { { // Successful IPv4 address match in CommonName - static constexpr char ipaddr[] = "127.0.0.1"; + static constexpr auto ipaddr = "127.0.0.1"_sr; auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/nosan_ip.crt"); - auto addr = parse_addr(ipaddr); - auto rv = - tls::verify_numeric_hostname(cert, StringRef::from_lit(ipaddr), &addr); + auto addr = parse_addr(ipaddr.data()); + auto rv = tls::verify_numeric_hostname(cert, ipaddr, &addr); assert_int(0, ==, rv); @@ -317,8 +311,7 @@ void test_shrpx_tls_verify_dns_hostname(void) { { // Successful exact DNS name match in SAN auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/verify_hostname.crt"); - auto rv = tls::verify_dns_hostname( - cert, StringRef::from_lit("nghttp2.example.com")); + auto rv = tls::verify_dns_hostname(cert, "nghttp2.example.com"_sr); assert_int(0, ==, rv); @@ -328,8 +321,7 @@ void test_shrpx_tls_verify_dns_hostname(void) { { // Successful wildcard DNS name match in SAN auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/verify_hostname.crt"); - auto rv = tls::verify_dns_hostname( - cert, StringRef::from_lit("www.nghttp2.example.com")); + auto rv = tls::verify_dns_hostname(cert, "www.nghttp2.example.com"_sr); assert_int(0, ==, rv); @@ -339,7 +331,7 @@ void test_shrpx_tls_verify_dns_hostname(void) { { // CommonName is not used if SAN is available. auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/verify_hostname.crt"); - auto rv = tls::verify_dns_hostname(cert, StringRef::from_lit("localhost")); + auto rv = tls::verify_dns_hostname(cert, "localhost"_sr); assert_int(-1, ==, rv); @@ -349,7 +341,7 @@ void test_shrpx_tls_verify_dns_hostname(void) { { // Successful DNS name match in CommonName auto cert = load_cert(NGHTTP2_SRC_DIR "/testdata/nosan.crt"); - auto rv = tls::verify_dns_hostname(cert, StringRef::from_lit("localhost")); + auto rv = tls::verify_dns_hostname(cert, "localhost"_sr); assert_int(0, ==, rv); diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index 9f5911f..3a585f6 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -555,9 +555,9 @@ void Worker::process_events() { faddr = &quic_upstream_addrs_[wev.quic_pkt->upstream_addr_index]; } - quic_conn_handler_.handle_packet( - faddr, wev.quic_pkt->remote_addr, wev.quic_pkt->local_addr, - wev.quic_pkt->pi, wev.quic_pkt->data.data(), wev.quic_pkt->data.size()); + quic_conn_handler_.handle_packet(faddr, wev.quic_pkt->remote_addr, + wev.quic_pkt->local_addr, wev.quic_pkt->pi, + wev.quic_pkt->data); break; } @@ -579,7 +579,7 @@ tls::CertLookupTree *Worker::get_quic_cert_lookup_tree() const { std::shared_ptr<TicketKeys> Worker::get_ticket_keys() { #ifdef HAVE_ATOMIC_STD_SHARED_PTR - return std::atomic_load_explicit(&ticket_keys_, std::memory_order_acquire); + return ticket_keys_.load(std::memory_order_acquire); #else // !HAVE_ATOMIC_STD_SHARED_PTR std::lock_guard<std::mutex> g(ticket_keys_m_); return ticket_keys_; @@ -589,8 +589,7 @@ std::shared_ptr<TicketKeys> Worker::get_ticket_keys() { void Worker::set_ticket_keys(std::shared_ptr<TicketKeys> ticket_keys) { #ifdef HAVE_ATOMIC_STD_SHARED_PTR // This is single writer - std::atomic_store_explicit(&ticket_keys_, std::move(ticket_keys), - std::memory_order_release); + ticket_keys_.store(std::move(ticket_keys), std::memory_order_release); #else // !HAVE_ATOMIC_STD_SHARED_PTR std::lock_guard<std::mutex> g(ticket_keys_m_); ticket_keys_ = std::move(ticket_keys); @@ -855,8 +854,7 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { hints.ai_flags |= AI_ADDRCONFIG; # endif // AI_ADDRCONFIG - auto node = - faddr.host == StringRef::from_lit("*") ? nullptr : faddr.host.c_str(); + auto node = faddr.host == "*"_sr ? nullptr : faddr.host.data(); addrinfo *res, *rp; rv = getaddrinfo(node, service.c_str(), &hints, &res); @@ -1027,7 +1025,7 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { if (should_attach_bpf()) { auto &bpfconf = config->quic.bpf; - auto obj = bpf_object__open_file(bpfconf.prog_file.c_str(), nullptr); + auto obj = bpf_object__open_file(bpfconf.prog_file.data(), nullptr); if (!obj) { auto error = errno; LOG(FATAL) << "Failed to open bpf object file: " @@ -1231,13 +1229,13 @@ const UpstreamAddr *Worker::find_quic_upstream_addr(const Address &local_addr) { if (faddr.port == 443 || faddr.port == 80) { switch (faddr.family) { case AF_INET: - if (util::streq(faddr.hostport, StringRef::from_lit("0.0.0.0"))) { + if (faddr.hostport == "0.0.0.0"_sr) { fallback_faddr = &faddr; } break; case AF_INET6: - if (util::streq(faddr.hostport, StringRef::from_lit("[::]"))) { + if (faddr.hostport == "[::]"_sr) { fallback_faddr = &faddr; } @@ -1248,14 +1246,13 @@ const UpstreamAddr *Worker::find_quic_upstream_addr(const Address &local_addr) { } else { switch (faddr.family) { case AF_INET: - if (util::starts_with(faddr.hostport, - StringRef::from_lit("0.0.0.0:"))) { + if (util::starts_with(faddr.hostport, "0.0.0.0:"_sr)) { fallback_faddr = &faddr; } break; case AF_INET6: - if (util::starts_with(faddr.hostport, StringRef::from_lit("[::]:"))) { + if (util::starts_with(faddr.hostport, "[::]:"_sr)) { fallback_faddr = &faddr; } @@ -1297,10 +1294,10 @@ size_t match_downstream_addr_group_host( if (!wildcard_patterns.empty() && !host.empty()) { auto rev_host_src = make_byte_ref(balloc, host.size() - 1); - auto ep = - std::copy(std::begin(host) + 1, std::end(host), rev_host_src.base); - std::reverse(rev_host_src.base, ep); - auto rev_host = StringRef{rev_host_src.base, ep}; + auto ep = std::copy(std::begin(host) + 1, std::end(host), + std::begin(rev_host_src)); + std::reverse(std::begin(rev_host_src), ep); + auto rev_host = StringRef{std::span{std::begin(rev_host_src), ep}}; ssize_t best_group = -1; const RNode *last_node = nullptr; @@ -1334,7 +1331,7 @@ size_t match_downstream_addr_group_host( } } - group = router.match(StringRef::from_lit(""), path); + group = router.match(""_sr, path); if (group != -1) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Found pattern with query " << path @@ -1367,7 +1364,7 @@ size_t match_downstream_addr_group( auto path = StringRef{std::begin(raw_path), query}; if (path.empty() || path[0] != '/') { - path = StringRef::from_lit("/"); + path = "/"_sr; } if (hostport.empty()) { @@ -1398,10 +1395,10 @@ size_t match_downstream_addr_group( return 'A' <= c || c <= 'Z'; }) != std::end(host)) { auto low_host = make_byte_ref(balloc, host.size() + 1); - auto ep = std::copy(std::begin(host), std::end(host), low_host.base); + auto ep = std::copy(std::begin(host), std::end(host), std::begin(low_host)); *ep = '\0'; - util::inp_strlower(low_host.base, ep); - host = StringRef{low_host.base, ep}; + util::inp_strlower(std::begin(low_host), ep); + host = StringRef{std::span{std::begin(low_host), ep}}; } return match_downstream_addr_group_host(routerconf, host, path, groups, catch_all, balloc); diff --git a/src/shrpx_worker.h b/src/shrpx_worker.h index f8a2d84..346e764 100644 --- a/src/shrpx_worker.h +++ b/src/shrpx_worker.h @@ -265,12 +265,12 @@ struct WorkerStat { struct QUICPacket { QUICPacket(size_t upstream_addr_index, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen) + std::span<const uint8_t> data) : upstream_addr_index{upstream_addr_index}, remote_addr{remote_addr}, local_addr{local_addr}, pi{pi}, - data{data, data + datalen} {} + data{std::begin(data), std::end(data)} {} QUICPacket() : upstream_addr_index{}, remote_addr{}, local_addr{}, pi{} {} size_t upstream_addr_index; Address remote_addr; @@ -439,10 +439,12 @@ private: QUICConnectionHandler quic_conn_handler_; #endif // ENABLE_HTTP3 -#ifndef HAVE_ATOMIC_STD_SHARED_PTR +#ifdef HAVE_ATOMIC_STD_SHARED_PTR + std::atomic<std::shared_ptr<TicketKeys>> ticket_keys_; +#else // !HAVE_ATOMIC_STD_SHARED_PTR std::mutex ticket_keys_m_; -#endif // !HAVE_ATOMIC_STD_SHARED_PTR std::shared_ptr<TicketKeys> ticket_keys_; +#endif // !HAVE_ATOMIC_STD_SHARED_PTR std::vector<std::shared_ptr<DownstreamAddrGroup>> downstream_addr_groups_; // Worker level blocker for downstream connection. For example, // this is used when file descriptor is exhausted. diff --git a/src/shrpx_worker_process.cc b/src/shrpx_worker_process.cc index 6591e9b..14040b4 100644 --- a/src/shrpx_worker_process.cc +++ b/src/shrpx_worker_process.cc @@ -74,11 +74,11 @@ void drop_privileges( if (getuid() == 0 && config->uid != 0) { #ifdef HAVE_NEVERBLEED if (nb) { - neverbleed_setuidgid(nb, config->user.c_str(), 1); + neverbleed_setuidgid(nb, config->user.data(), 1); } #endif // HAVE_NEVERBLEED - if (initgroups(config->user.c_str(), config->gid) != 0) { + if (initgroups(config->user.data(), config->gid) != 0) { auto error = errno; LOG(FATAL) << "Could not change supplementary groups: " << xsi_strerror(error, errbuf.data(), errbuf.size()); @@ -576,10 +576,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) { } for (auto &qkm : qkms->keying_materials) { - if (generate_quic_connection_id_encryption_key( - qkm.cid_encryption_key.data(), qkm.cid_encryption_key.size(), - qkm.secret.data(), qkm.secret.size(), qkm.salt.data(), - qkm.salt.size()) != 0) { + if (generate_quic_connection_id_encryption_key(qkm.cid_encryption_key, + qkm.secret, qkm.salt) != 0) { LOG(ERROR) << "Failed to generate QUIC Connection ID encryption key"; return -1; } diff --git a/src/shrpx_worker_test.cc b/src/shrpx_worker_test.cc index 4b4b7a6..9372a2c 100644 --- a/src/shrpx_worker_test.cc +++ b/src/shrpx_worker_test.cc @@ -74,154 +74,134 @@ void test_shrpx_worker_match_downstream_addr_group(void) { } assert_size(0, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, "/"_sr, + groups, 255, balloc)); // port is removed assert_size(0, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org:8080"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org:8080"_sr, + "/"_sr, groups, 255, balloc)); // host is case-insensitive assert_size(4, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("WWW.nghttp2.org"), - StringRef::from_lit("/alpha"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "WWW.nghttp2.org"_sr, + "/alpha"_sr, groups, 255, balloc)); assert_size(1, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/bravo/"_sr, groups, 255, + balloc)); // /alpha/bravo also matches /alpha/bravo/ assert_size(1, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/bravo"_sr, groups, 255, + balloc)); // path part is case-sensitive assert_size(0, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/Alpha/bravo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/Alpha/bravo"_sr, groups, 255, + balloc)); assert_size(1, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/charlie"), groups, 255, - balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/bravo/charlie"_sr, groups, + 255, balloc)); assert_size(2, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/charlie"_sr, groups, 255, + balloc)); // pattern which does not end with '/' must match its entirely. So // this matches to group 0, not group 2. assert_size(0, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/charlie/"_sr, groups, 255, + balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("example.org"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "example.org"_sr, "/"_sr, + groups, 255, balloc)); assert_size(255, ==, - match_downstream_addr_group(routerconf, StringRef::from_lit(""), - StringRef::from_lit("/"), groups, 255, - balloc)); + match_downstream_addr_group(routerconf, ""_sr, "/"_sr, groups, + 255, balloc)); assert_size(255, ==, - match_downstream_addr_group(routerconf, StringRef::from_lit(""), - StringRef::from_lit("alpha"), groups, + match_downstream_addr_group(routerconf, ""_sr, "alpha"_sr, groups, 255, balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("foo/bar"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "foo/bar"_sr, "/"_sr, + groups, 255, balloc)); - // If path is StringRef::from_lit("*", only match with host + "/"). + // If path is "*", only match with host + "/"). assert_size(0, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("*"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, "*"_sr, + groups, 255, balloc)); assert_size(5, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1]"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "[::1]"_sr, "/"_sr, + groups, 255, balloc)); assert_size(5, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1]:8080"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "[::1]:8080"_sr, "/"_sr, + groups, 255, balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "[::1"_sr, "/"_sr, groups, + 255, balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1]8000"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "[::1]8000"_sr, "/"_sr, + groups, 255, balloc)); // Check the case where adding route extends tree assert_size(6, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/delta"), groups, 255, - balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/bravo/delta"_sr, groups, 255, + balloc)); assert_size(1, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/delta/"), groups, 255, - balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/alpha/bravo/delta/"_sr, groups, 255, + balloc)); // Check the case where query is done in a single node assert_size(7, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "example.com"_sr, + "/alpha/bravo"_sr, groups, 255, + balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha/bravo/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "example.com"_sr, + "/alpha/bravo/"_sr, groups, 255, + balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "example.com"_sr, + "/alpha"_sr, groups, 255, balloc)); // Check the case where quey is done in a single node assert_size(8, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "192.168.0.1"_sr, + "/alpha"_sr, groups, 255, balloc)); assert_size(8, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "192.168.0.1"_sr, + "/alpha/"_sr, groups, 255, balloc)); assert_size(8, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "192.168.0.1"_sr, + "/alpha/bravo"_sr, groups, 255, + balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alph"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "192.168.0.1"_sr, + "/alph"_sr, groups, 255, balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "192.168.0.1"_sr, "/"_sr, + groups, 255, balloc)); // Test for wildcard hosts auto g1 = std::make_shared<DownstreamAddrGroup>(); @@ -236,52 +216,46 @@ void test_shrpx_worker_match_downstream_addr_group(void) { g3->pattern = ImmutableString::from_lit(".local"); groups.push_back(std::move(g3)); - wp.emplace_back(StringRef::from_lit("git.nghttp2.org")); - wcrouter.add_route(StringRef::from_lit("gro.2ptthgn.tig"), 0); - wp.back().router.add_route(StringRef::from_lit("/echo/"), 10); + wp.emplace_back("git.nghttp2.org"_sr); + wcrouter.add_route("gro.2ptthgn.tig"_sr, 0); + wp.back().router.add_route("/echo/"_sr, 10); - wp.emplace_back(StringRef::from_lit(".nghttp2.org")); - wcrouter.add_route(StringRef::from_lit("gro.2ptthgn."), 1); - wp.back().router.add_route(StringRef::from_lit("/echo/"), 11); - wp.back().router.add_route(StringRef::from_lit("/echo/foxtrot"), 12); + wp.emplace_back(".nghttp2.org"_sr); + wcrouter.add_route("gro.2ptthgn."_sr, 1); + wp.back().router.add_route("/echo/"_sr, 11); + wp.back().router.add_route("/echo/foxtrot"_sr, 12); - wp.emplace_back(StringRef::from_lit(".local")); - wcrouter.add_route(StringRef::from_lit("lacol."), 2); - wp.back().router.add_route(StringRef::from_lit("/"), 13); + wp.emplace_back(".local"_sr); + wcrouter.add_route("lacol."_sr, 2); + wp.back().router.add_route("/"_sr, 13); assert_size(11, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("git.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "git.nghttp2.org"_sr, + "/echo"_sr, groups, 255, balloc)); assert_size(10, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("0git.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "0git.nghttp2.org"_sr, + "/echo"_sr, groups, 255, balloc)); assert_size(11, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("it.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "it.nghttp2.org"_sr, + "/echo"_sr, groups, 255, balloc)); assert_size(255, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit(".nghttp2.org"), - StringRef::from_lit("/echo/foxtrot"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, ".nghttp2.org"_sr, + "/echo/foxtrot"_sr, groups, 255, + balloc)); assert_size(9, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("alpha.nghttp2.org"), - StringRef::from_lit("/golf"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "alpha.nghttp2.org"_sr, + "/golf"_sr, groups, 255, balloc)); assert_size(0, ==, - match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); + match_downstream_addr_group(routerconf, "nghttp2.org"_sr, + "/echo"_sr, groups, 255, balloc)); assert_size(13, ==, - match_downstream_addr_group(routerconf, - StringRef::from_lit("test.local"), + match_downstream_addr_group(routerconf, "test.local"_sr, StringRef{}, groups, 255, balloc)); } diff --git a/src/template.h b/src/template.h index 530a1d1..3ab3677 100644 --- a/src/template.h +++ b/src/template.h @@ -37,20 +37,11 @@ #include <algorithm> #include <ostream> #include <utility> +#include <span> +#include <string_view> namespace nghttp2 { -// std::forward is constexpr since C++14 -template <typename... T> -constexpr std::array< - typename std::decay<typename std::common_type<T...>::type>::type, - sizeof...(T)> -make_array(T &&...t) { - return std::array< - typename std::decay<typename std::common_type<T...>::type>::type, - sizeof...(T)>{{std::forward<T>(t)...}}; -} - template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) { return N; } @@ -67,8 +58,7 @@ template <typename F, typename... T> struct Defer { Defer(Defer &&o) noexcept : f(std::move(o.f)) {} ~Defer() { f(); } - using ResultType = typename std::result_of<typename std::decay<F>::type( - typename std::decay<T>::type...)>::type; + using ResultType = std::invoke_result_t<F, T...>; std::function<ResultType()> f; }; @@ -234,27 +224,27 @@ public: using const_iterator = const_pointer; using const_reverse_iterator = std::reverse_iterator<const_iterator>; - ImmutableString() : len(0), base("") {} - ImmutableString(const char *s, size_t slen) + constexpr ImmutableString() : len(0), base("") {} + constexpr ImmutableString(const char *s, size_t slen) : len(slen), base(copystr(s, s + len)) {} - explicit ImmutableString(const char *s) - : len(strlen(s)), base(copystr(s, s + len)) {} - explicit ImmutableString(const std::string &s) + constexpr explicit ImmutableString(const char *s) + : len(traits_type::length(s)), base(copystr(s, s + len)) {} + constexpr explicit ImmutableString(const std::string &s) : len(s.size()), base(copystr(std::begin(s), std::end(s))) {} template <typename InputIt> - ImmutableString(InputIt first, InputIt last) + constexpr ImmutableString(InputIt first, InputIt last) : len(std::distance(first, last)), base(copystr(first, last)) {} - ImmutableString(const ImmutableString &other) + constexpr ImmutableString(const ImmutableString &other) : len(other.len), base(copystr(std::begin(other), std::end(other))) {} - ImmutableString(ImmutableString &&other) noexcept + constexpr ImmutableString(ImmutableString &&other) noexcept : len{std::exchange(other.len, 0)}, base{std::exchange(other.base, "")} {} - ~ImmutableString() { + constexpr ~ImmutableString() { if (len) { delete[] base; } } - ImmutableString &operator=(const ImmutableString &other) { + constexpr ImmutableString &operator=(const ImmutableString &other) { if (this == &other) { return *this; } @@ -265,7 +255,7 @@ public: base = copystr(std::begin(other), std::end(other)); return *this; } - ImmutableString &operator=(ImmutableString &&other) noexcept { + constexpr ImmutableString &operator=(ImmutableString &&other) noexcept { if (this == &other) { return *this; } @@ -277,33 +267,41 @@ public: return *this; } - template <size_t N> static ImmutableString from_lit(const char (&s)[N]) { + template <size_t N> + static constexpr ImmutableString from_lit(const char (&s)[N]) { return ImmutableString(s, N - 1); } - const_iterator begin() const { return base; }; - const_iterator cbegin() const { return base; }; + constexpr const_iterator begin() const noexcept { return base; }; + constexpr const_iterator cbegin() const noexcept { return base; }; - const_iterator end() const { return base + len; }; - const_iterator cend() const { return base + len; }; + constexpr const_iterator end() const noexcept { return base + len; }; + constexpr const_iterator cend() const noexcept { return base + len; }; - const_reverse_iterator rbegin() const { + constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{base + len}; } - const_reverse_iterator crbegin() const { + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{base + len}; } - const_reverse_iterator rend() const { return const_reverse_iterator{base}; } - const_reverse_iterator crend() const { return const_reverse_iterator{base}; } + constexpr const_reverse_iterator rend() const noexcept { + return const_reverse_iterator{base}; + } + constexpr const_reverse_iterator crend() const noexcept { + return const_reverse_iterator{base}; + } - const char *c_str() const { return base; } - size_type size() const { return len; } - bool empty() const { return len == 0; } - const_reference operator[](size_type pos) const { return *(base + pos); } + constexpr const char *c_str() const noexcept { return base; } + constexpr size_type size() const noexcept { return len; } + constexpr bool empty() const noexcept { return len == 0; } + constexpr const_reference operator[](size_type pos) const noexcept { + return *(base + pos); + } private: - template <typename InputIt> const char *copystr(InputIt first, InputIt last) { + template <typename InputIt> + constexpr const char *copystr(InputIt first, InputIt last) { if (first == last) { return ""; } @@ -316,49 +314,23 @@ private: const char *base; }; -inline bool operator==(const ImmutableString &lhs, const ImmutableString &rhs) { +inline constexpr bool operator==(const ImmutableString &lhs, + const ImmutableString &rhs) { return lhs.size() == rhs.size() && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); } -inline bool operator==(const ImmutableString &lhs, const std::string &rhs) { +inline constexpr bool operator==(const ImmutableString &lhs, + const std::string &rhs) { return lhs.size() == rhs.size() && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); } -inline bool operator==(const std::string &lhs, const ImmutableString &rhs) { - return rhs == lhs; -} - -inline bool operator==(const ImmutableString &lhs, const char *rhs) { - return lhs.size() == strlen(rhs) && +inline constexpr bool operator==(const ImmutableString &lhs, const char *rhs) { + return lhs.size() == std::char_traits<char>::length(rhs) && std::equal(std::begin(lhs), std::end(lhs), rhs); } -inline bool operator==(const char *lhs, const ImmutableString &rhs) { - return rhs == lhs; -} - -inline bool operator!=(const ImmutableString &lhs, const ImmutableString &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const ImmutableString &lhs, const std::string &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const std::string &lhs, const ImmutableString &rhs) { - return !(rhs == lhs); -} - -inline bool operator!=(const ImmutableString &lhs, const char *rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const char *lhs, const ImmutableString &rhs) { - return !(rhs == lhs); -} - inline std::ostream &operator<<(std::ostream &o, const ImmutableString &s) { return o.write(s.c_str(), s.size()); } @@ -371,8 +343,7 @@ inline std::string &operator+=(std::string &lhs, const ImmutableString &rhs) { // StringRef is a reference to a string owned by something else. So // it behaves like simple string, but it does not own pointer. When // it is default constructed, it has empty string. You can freely -// copy or move around this struct, but never free its pointer. str() -// function can be used to export the content as std::string. +// copy or move around this struct, but never free its pointer. class StringRef { public: using traits_type = std::char_traits<char>; @@ -386,28 +357,28 @@ public: using const_iterator = const_pointer; using const_reverse_iterator = std::reverse_iterator<const_iterator>; - constexpr StringRef() : base(""), len(0) {} - explicit StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {} - explicit StringRef(const ImmutableString &s) + constexpr StringRef() noexcept : base(""), len(0) {} + constexpr StringRef(const StringRef &other) noexcept = default; + constexpr StringRef(std::nullptr_t) = delete; + constexpr StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {} + constexpr explicit StringRef(const std::string_view &s) + : base(s.data()), len(s.size()) {} + constexpr explicit StringRef(const ImmutableString &s) : base(s.c_str()), len(s.size()) {} - explicit StringRef(const char *s) : base(s), len(strlen(s)) {} + constexpr StringRef(const char *s) : base(s), len(traits_type::length(s)) {} constexpr StringRef(const char *s, size_t n) : base(s), len(n) {} - template <typename CharT> - constexpr StringRef(const CharT *s, size_t n) + explicit StringRef(const uint8_t *s, size_t n) : base(reinterpret_cast<const char *>(s)), len(n) {} - template <typename InputIt> - StringRef(InputIt first, InputIt last) - : base(reinterpret_cast<const char *>(&*first)), - len(std::distance(first, last)) {} - template <typename InputIt> - StringRef(InputIt *first, InputIt *last) - : base(reinterpret_cast<const char *>(first)), - len(std::distance(first, last)) {} - template <typename CharT, size_t N> - constexpr static StringRef from_lit(const CharT (&s)[N]) { - return StringRef{s, N - 1}; - } - static StringRef from_maybe_nullptr(const char *s) { + template <std::contiguous_iterator InputIt, + typename = std::enable_if_t< + std::is_same_v<std::iter_value_t<InputIt>, char>>> + constexpr StringRef(InputIt first, InputIt last) + : base(std::to_address(first)), len(std::distance(first, last)) {} + constexpr StringRef(std::span<const char> s) + : base(s.data()), len(s.size_bytes()) {} + explicit StringRef(std::span<const uint8_t> s) + : base(reinterpret_cast<const char *>(s.data())), len(s.size_bytes()) {} + static constexpr StringRef from_maybe_nullptr(const char *s) noexcept { if (s == nullptr) { return StringRef(); } @@ -415,105 +386,103 @@ public: return StringRef(s); } - constexpr const_iterator begin() const { return base; }; - constexpr const_iterator cbegin() const { return base; }; + constexpr StringRef &operator=(const StringRef &other) noexcept = default; + + constexpr const_iterator begin() const noexcept { return base; }; + constexpr const_iterator cbegin() const noexcept { return base; }; - constexpr const_iterator end() const { return base + len; }; - constexpr const_iterator cend() const { return base + len; }; + constexpr const_iterator end() const noexcept { return base + len; }; + constexpr const_iterator cend() const noexcept { return base + len; }; - const_reverse_iterator rbegin() const { + constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{base + len}; } - const_reverse_iterator crbegin() const { + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{base + len}; } - const_reverse_iterator rend() const { return const_reverse_iterator{base}; } - const_reverse_iterator crend() const { return const_reverse_iterator{base}; } + constexpr const_reverse_iterator rend() const noexcept { + return const_reverse_iterator{base}; + } + constexpr const_reverse_iterator crend() const noexcept { + return const_reverse_iterator{base}; + } - constexpr const char *c_str() const { return base; } - constexpr size_type size() const { return len; } - constexpr bool empty() const { return len == 0; } + constexpr const_pointer data() const noexcept { return base; } + constexpr size_type size() const noexcept { return len; } + [[nodiscard]] constexpr bool empty() const noexcept { return len == 0; } constexpr const_reference operator[](size_type pos) const { return *(base + pos); } - std::string str() const { return std::string(base, len); } const uint8_t *byte() const { return reinterpret_cast<const uint8_t *>(base); } + constexpr operator std::string_view() const noexcept { return {base, len}; } + + static constexpr size_type npos = size_type(-1); + + constexpr StringRef substr(size_type pos = 0, size_type count = npos) const { + return {base + pos, std::min(count, len - pos)}; + } + private: const char *base; size_type len; }; -inline bool operator==(const StringRef &lhs, const StringRef &rhs) { +inline constexpr bool operator==(const StringRef &lhs, + const StringRef &rhs) noexcept { return lhs.size() == rhs.size() && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); } -inline bool operator==(const StringRef &lhs, const std::string &rhs) { +inline constexpr bool operator==(const StringRef &lhs, + const ImmutableString &rhs) noexcept { return lhs.size() == rhs.size() && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); } -inline bool operator==(const std::string &lhs, const StringRef &rhs) { - return rhs == lhs; -} - -inline bool operator==(const StringRef &lhs, const char *rhs) { - return lhs.size() == strlen(rhs) && - std::equal(std::begin(lhs), std::end(lhs), rhs); -} - -inline bool operator==(const StringRef &lhs, const ImmutableString &rhs) { - return lhs.size() == rhs.size() && - std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); +#ifndef __APPLE__ +inline constexpr std::strong_ordering +operator<=>(const StringRef &lhs, const StringRef &rhs) noexcept { + return std::lexicographical_compare_three_way(std::begin(lhs), std::end(lhs), + std::begin(rhs), std::end(rhs)); } - -inline bool operator==(const ImmutableString &lhs, const StringRef &rhs) { - return rhs == lhs; -} - -inline bool operator==(const char *lhs, const StringRef &rhs) { - return rhs == lhs; -} - -inline bool operator!=(const StringRef &lhs, const StringRef &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const StringRef &lhs, const std::string &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const std::string &lhs, const StringRef &rhs) { - return !(rhs == lhs); -} - -inline bool operator!=(const StringRef &lhs, const char *rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const char *lhs, const StringRef &rhs) { - return !(rhs == lhs); -} - -inline bool operator<(const StringRef &lhs, const StringRef &rhs) { +#else // __APPLE__ +inline constexpr bool operator<(const StringRef &lhs, + const StringRef &rhs) noexcept { return std::lexicographical_compare(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs)); } +#endif // __APPLE__ inline std::ostream &operator<<(std::ostream &o, const StringRef &s) { - return o.write(s.c_str(), s.size()); + return o.write(s.data(), s.size()); } inline std::string &operator+=(std::string &lhs, const StringRef &rhs) { - lhs.append(rhs.c_str(), rhs.size()); + lhs.append(rhs.data(), rhs.size()); return lhs; } +constexpr StringRef operator""_sr(const char *str, size_t len) noexcept { + return {str, len}; +} + +template <typename T, std::size_t N> +[[nodiscard]] std::span<const uint8_t, N == std::dynamic_extent + ? std::dynamic_extent + : N * sizeof(T)> +as_uint8_span(std::span<T, N> s) noexcept { + return std::span < const uint8_t, + N == std::dynamic_extent + ? std::dynamic_extent + : N * sizeof(T) > {reinterpret_cast<const uint8_t *>(s.data()), + s.size_bytes()}; +} + inline int run_app(std::function<int(int, char **)> app, int argc, char **argv) { try { diff --git a/src/template_test.cc b/src/template_test.cc index db212d1..99b193b 100644 --- a/src/template_test.cc +++ b/src/template_test.cc @@ -32,12 +32,15 @@ #include "template.h" +using namespace std::literals; + namespace nghttp2 { namespace { const MunitTest tests[]{ munit_void_test(test_template_immutable_string), munit_void_test(test_template_string_ref), + munit_void_test(test_template_as_uint8_span), munit_test_end(), }; } // namespace @@ -147,7 +150,7 @@ void test_template_immutable_string(void) { void test_template_string_ref(void) { StringRef empty; - assert_stdstring_equal("", empty.str()); + assert_stdsv_equal(""sv, empty); assert_size(0, ==, empty.size()); // from std::string @@ -162,9 +165,9 @@ void test_template_string_ref(void) { assert_size(5, ==, ref.size()); // from string literal - auto from_lit = StringRef::from_lit("alpha"); + auto from_lit = "alpha"_sr; - assert_stdstring_equal("alpha", from_lit.str()); + assert_stdsv_equal("alpha"sv, from_lit); assert_size(5, ==, from_lit.size()); // from ImmutableString @@ -172,19 +175,19 @@ void test_template_string_ref(void) { StringRef imref(im); - assert_stdstring_equal("bravo", imref.str()); + assert_stdsv_equal("bravo"sv, imref); assert_size(5, ==, imref.size()); // from C-string StringRef cstrref("charlie"); - assert_stdstring_equal("charlie", cstrref.str()); + assert_stdsv_equal("charlie"sv, cstrref); assert_size(7, ==, cstrref.size()); // from C-string and its length StringRef cstrnref("delta", 5); - assert_stdstring_equal("delta", cstrnref.str()); + assert_stdsv_equal("delta"sv, cstrnref); assert_size(5, ==, cstrnref.size()); // operator[] @@ -213,4 +216,24 @@ void test_template_string_ref(void) { } } +void test_template_as_uint8_span(void) { + uint32_t a[2]; + + memcpy(&a, "\xc0\xc1\xc2\xc3\xf0\xf1\xf2\xf3", sizeof(a)); + + // dynamic extent + auto s = as_uint8_span(std::span{a, 2}); + + assert_size(sizeof(a), ==, s.size()); + assert_size(std::dynamic_extent, ==, s.extent); + assert_memory_equal(s.size(), &a, s.data()); + + // non-dynamic extent + auto t = as_uint8_span(std::span<uint32_t, 2>{a, 2}); + + assert_size(sizeof(a), ==, t.size()); + assert_size(sizeof(a), ==, t.extent); + assert_memory_equal(t.size(), &a, t.data()); +} + } // namespace nghttp2 diff --git a/src/template_test.h b/src/template_test.h index df39de9..d52bd26 100644 --- a/src/template_test.h +++ b/src/template_test.h @@ -39,6 +39,7 @@ extern const MunitSuite template_suite; munit_void_test_decl(test_template_immutable_string); munit_void_test_decl(test_template_string_ref); +munit_void_test_decl(test_template_as_uint8_span); } // namespace nghttp2 @@ -28,11 +28,14 @@ #include "nghttp2_config.h" #include <cinttypes> +#include <string_view> #include <openssl/ssl.h> #include "ssl_compat.h" +using namespace std::literals; + namespace nghttp2 { namespace tls { @@ -41,19 +44,20 @@ namespace tls { // suites for TLSv1.2 by mozilla. // // https://wiki.mozilla.org/Security/Server_Side_TLS -constexpr char DEFAULT_CIPHER_LIST[] = +constexpr auto DEFAULT_CIPHER_LIST = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-" "AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-" "POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-" - "AES256-GCM-SHA384"; + "AES256-GCM-SHA384"sv; // Recommended general purpose "Modern compatibility" cipher suites // for TLSv1.3 by mozilla. // // https://wiki.mozilla.org/Security/Server_Side_TLS -constexpr char DEFAULT_TLS13_CIPHER_LIST[] = +constexpr auto DEFAULT_TLS13_CIPHER_LIST = #if defined(NGHTTP2_GENUINE_OPENSSL) || defined(NGHTTP2_OPENSSL_IS_LIBRESSL) - "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" + "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256"sv #else // !NGHTTP2_GENUINE_OPENSSL && !NGHTTP2_OPENSSL_IS_LIBRESSL "" #endif // !NGHTTP2_GENUINE_OPENSSL && !NGHTTP2_OPENSSL_IS_LIBRESSL diff --git a/src/util.cc b/src/util.cc index 47151b2..e6c4214 100644 --- a/src/util.cc +++ b/src/util.cc @@ -191,11 +191,11 @@ bool in_attr_char(char c) { StringRef percent_encode_token(BlockAllocator &balloc, const StringRef &target) { auto iov = make_byte_ref(balloc, target.size() * 3 + 1); - auto p = percent_encode_token(iov.base, target); + auto p = percent_encode_token(std::begin(iov), target); *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } size_t percent_encode_tokenlen(const StringRef &target) { @@ -237,11 +237,11 @@ StringRef quote_string(BlockAllocator &balloc, const StringRef &target) { } auto iov = make_byte_ref(balloc, target.size() + cnt + 1); - auto p = quote_string(iov.base, target); + auto p = quote_string(std::begin(iov), target); *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } size_t quote_stringlen(const StringRef &target) { @@ -465,13 +465,13 @@ time_t parse_http_date(const StringRef &s) { tm tm{}; #ifdef _WIN32 // there is no strptime - use std::get_time - std::stringstream sstr(s.str()); + std::stringstream sstr(s.data()); sstr >> std::get_time(&tm, "%a, %d %b %Y %H:%M:%S GMT"); if (sstr.fail()) { return 0; } #else // !_WIN32 - char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm); + char *r = strptime(s.data(), "%a, %d %b %Y %H:%M:%S GMT", &tm); if (r == 0) { return 0; } @@ -481,7 +481,7 @@ time_t parse_http_date(const StringRef &s) { time_t parse_openssl_asn1_time_print(const StringRef &s) { tm tm{}; - auto r = strptime(s.c_str(), "%b %d %H:%M:%S %Y GMT", &tm); + auto r = strptime(s.data(), "%b %d %H:%M:%S %Y GMT", &tm); if (r == nullptr) { return 0; } @@ -496,32 +496,22 @@ char upcase(char c) { } } -std::string format_hex(const unsigned char *s, size_t len) { +std::string format_hex(std::span<const uint8_t> s) { std::string res; - res.resize(len * 2); + res.resize(s.size() * 2); - for (size_t i = 0; i < len; ++i) { - unsigned char c = s[i]; + format_hex(std::begin(res), s); - res[i * 2] = LOWER_XDIGITS[c >> 4]; - res[i * 2 + 1] = LOWER_XDIGITS[c & 0x0f]; - } return res; } -StringRef format_hex(BlockAllocator &balloc, const StringRef &s) { +StringRef format_hex(BlockAllocator &balloc, std::span<const uint8_t> s) { auto iov = make_byte_ref(balloc, s.size() * 2 + 1); - auto p = iov.base; - - for (auto cc : s) { - uint8_t c = cc; - *p++ = LOWER_XDIGITS[c >> 4]; - *p++ = LOWER_XDIGITS[c & 0xf]; - } + auto p = format_hex(std::begin(iov), s); *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } void to_token68(std::string &base64str) { @@ -544,19 +534,18 @@ StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str) { // At most 3 padding '=' auto len = token68str.size() + 3; auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - - p = std::transform(std::begin(token68str), std::end(token68str), p, - [](char c) { - switch (c) { - case '-': - return '+'; - case '_': - return '/'; - default: - return c; - } - }); + + auto p = std::transform(std::begin(token68str), std::end(token68str), + std::begin(iov), [](char c) { + switch (c) { + case '-': + return '+'; + case '_': + return '/'; + default: + return c; + } + }); auto rem = token68str.size() & 0x3; if (rem) { @@ -565,7 +554,7 @@ StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str) { *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } namespace { @@ -878,7 +867,7 @@ bool check_path(const std::string &path) { path.find('\\') == std::string::npos && path.find("/../") == std::string::npos && path.find("/./") == std::string::npos && - !util::ends_with_l(path, "/..") && !util::ends_with_l(path, "/."); + !util::ends_with(path, "/.."_sr) && !util::ends_with(path, "/."_sr); } int64_t to_time64(const timeval &tv) { @@ -886,8 +875,8 @@ int64_t to_time64(const timeval &tv) { } bool check_h2_is_selected(const StringRef &proto) { - return streq(NGHTTP2_H2, proto) || streq(NGHTTP2_H2_16, proto) || - streq(NGHTTP2_H2_14, proto); + return NGHTTP2_H2 == proto || NGHTTP2_H2_16 == proto || + NGHTTP2_H2_14 == proto; } namespace { @@ -1148,58 +1137,63 @@ bool ipv6_numeric_addr(const char *host) { } namespace { -std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) { - const uint8_t *s = static_cast<const uint8_t *>(ss); - int64_t n = 0; - size_t i; - if (len == 0) { - return {-1, 0}; +std::optional<std::pair<int64_t, StringRef>> +parse_uint_digits(const StringRef &s) { + if (s.empty()) { + return {}; } + constexpr int64_t max = std::numeric_limits<int64_t>::max(); - for (i = 0; i < len; ++i) { - if ('0' <= s[i] && s[i] <= '9') { - if (n > max / 10) { - return {-1, 0}; - } - n *= 10; - if (n > max - (s[i] - '0')) { - return {-1, 0}; - } - n += s[i] - '0'; - continue; + + int64_t n = 0; + size_t i = 0; + + for (auto c : s) { + if ('0' > c || c > '9') { + break; } - break; + + if (n > max / 10) { + return {}; + } + + n *= 10; + + if (n > max - (c - '0')) { + return {}; + } + + n += c - '0'; + + ++i; } + if (i == 0) { - return {-1, 0}; + return {}; } - return {n, i}; + + return std::pair{n, s.substr(i)}; } } // namespace -int64_t parse_uint_with_unit(const char *s) { - return parse_uint_with_unit(reinterpret_cast<const uint8_t *>(s), strlen(s)); -} +std::optional<int64_t> parse_uint_with_unit(const StringRef &s) { + auto r = parse_uint_digits(s); + if (!r) { + return {}; + } -int64_t parse_uint_with_unit(const StringRef &s) { - return parse_uint_with_unit(s.byte(), s.size()); -} + auto [n, rest] = *r; -int64_t parse_uint_with_unit(const uint8_t *s, size_t len) { - int64_t n; - size_t i; - std::tie(n, i) = parse_uint_digits(s, len); - if (n == -1) { - return -1; - } - if (i == len) { + if (rest.empty()) { return n; } - if (i + 1 != len) { - return -1; + + if (rest.size() != 1) { + return {}; } + int mul = 1; - switch (s[i]) { + switch (rest[0]) { case 'K': case 'k': mul = 1 << 10; @@ -1213,94 +1207,81 @@ int64_t parse_uint_with_unit(const uint8_t *s, size_t len) { mul = 1 << 30; break; default: - return -1; + return {}; } + constexpr int64_t max = std::numeric_limits<int64_t>::max(); if (n > max / mul) { - return -1; + return {}; } - return n * mul; -} -int64_t parse_uint(const char *s) { - return parse_uint(reinterpret_cast<const uint8_t *>(s), strlen(s)); -} - -int64_t parse_uint(const std::string &s) { - return parse_uint(reinterpret_cast<const uint8_t *>(s.c_str()), s.size()); -} - -int64_t parse_uint(const StringRef &s) { - return parse_uint(s.byte(), s.size()); + return n * mul; } -int64_t parse_uint(const uint8_t *s, size_t len) { - int64_t n; - size_t i; - std::tie(n, i) = parse_uint_digits(s, len); - if (n == -1 || i != len) { - return -1; +std::optional<int64_t> parse_uint(const StringRef &s) { + auto r = parse_uint_digits(s); + if (!r || !(*r).second.empty()) { + return {}; } - return n; -} - -double parse_duration_with_unit(const char *s) { - return parse_duration_with_unit(reinterpret_cast<const uint8_t *>(s), - strlen(s)); -} -double parse_duration_with_unit(const StringRef &s) { - return parse_duration_with_unit(s.byte(), s.size()); + return (*r).first; } -double parse_duration_with_unit(const uint8_t *s, size_t len) { +std::optional<double> parse_duration_with_unit(const StringRef &s) { constexpr auto max = std::numeric_limits<int64_t>::max(); - int64_t n; - size_t i; - std::tie(n, i) = parse_uint_digits(s, len); - if (n == -1) { - goto fail; + auto r = parse_uint_digits(s); + if (!r) { + return {}; } - if (i == len) { + + auto [n, rest] = *r; + + if (rest.empty()) { return static_cast<double>(n); } - switch (s[i]) { + + switch (rest[0]) { case 'S': case 's': // seconds - if (i + 1 != len) { - goto fail; + if (rest.size() != 1) { + return {}; } + return static_cast<double>(n); case 'M': case 'm': - if (i + 1 == len) { + if (rest.size() == 1) { // minutes if (n > max / 60) { - goto fail; + return {}; } + return static_cast<double>(n) * 60; } - if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) { - goto fail; + if (rest.size() != 2 || (rest[1] != 's' && rest[1] != 'S')) { + return {}; } + // milliseconds return static_cast<double>(n) / 1000.; case 'H': case 'h': // hours - if (i + 1 != len) { - goto fail; + if (rest.size() != 1) { + return {}; } + if (n > max / 3600) { - goto fail; + return {}; } + return static_cast<double>(n) * 3600; + default: + return {}; } -fail: - return std::numeric_limits<double>::infinity(); } std::string duration_str(double t) { @@ -1362,13 +1343,13 @@ std::string dtos(double n) { StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host, uint16_t port) { auto iov = make_byte_ref(balloc, host.size() + 2 + 1 + 5 + 1); - return make_http_hostport(iov.base, host, port); + return make_http_hostport(std::begin(iov), host, port); } StringRef make_hostport(BlockAllocator &balloc, const StringRef &host, uint16_t port) { auto iov = make_byte_ref(balloc, host.size() + 2 + 1 + 5 + 1); - return make_hostport(iov.base, host, port); + return make_hostport(std::begin(iov), host, port); } namespace { @@ -1611,7 +1592,7 @@ int read_mime_types(std::map<std::string, std::string> &res, StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) { auto iov = make_byte_ref(balloc, src.size() * 3 + 1); - auto p = iov.base; + auto p = std::begin(iov); for (auto first = std::begin(src); first != std::end(src); ++first) { if (*first != '%') { *p++ = *first; @@ -1628,7 +1609,7 @@ StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) { *p++ = *first; } *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } // Returns x**y @@ -1669,7 +1650,7 @@ int message_digest(uint8_t *res, const EVP_MD *meth, const StringRef &s) { return -1; } - rv = EVP_DigestUpdate(ctx, s.c_str(), s.size()); + rv = EVP_DigestUpdate(ctx, s.data(), s.size()); if (rv != 1) { return -1; } @@ -1707,11 +1688,12 @@ bool is_hex_string(const StringRef &s) { return true; } -StringRef decode_hex(BlockAllocator &balloc, const StringRef &s) { +std::span<const uint8_t> decode_hex(BlockAllocator &balloc, + const StringRef &s) { auto iov = make_byte_ref(balloc, s.size() + 1); - auto p = decode_hex(iov.base, s); + auto p = decode_hex(std::begin(iov), s); *p = '\0'; - return StringRef{iov.base, p}; + return {std::begin(iov), p}; } StringRef extract_host(const StringRef &hostport) { @@ -1824,7 +1806,7 @@ StringRef rstrip(BlockAllocator &balloc, const StringRef &s) { return s; } - return make_string_ref(balloc, StringRef{s.c_str(), s.size() - len}); + return make_string_ref(balloc, StringRef{s.data(), s.size() - len}); } #ifdef ENABLE_HTTP3 @@ -46,6 +46,7 @@ #include <chrono> #include <map> #include <random> +#include <optional> #ifdef HAVE_LIBEV # include <ev.h> @@ -59,20 +60,20 @@ namespace nghttp2 { -constexpr auto NGHTTP2_H2_ALPN = StringRef::from_lit("\x2h2"); -constexpr auto NGHTTP2_H2 = StringRef::from_lit("h2"); +constexpr auto NGHTTP2_H2_ALPN = "\x2h2"_sr; +constexpr auto NGHTTP2_H2 = "h2"_sr; // The additional HTTP/2 protocol ALPN protocol identifier we also // supports for our applications to make smooth migration into final // h2 ALPN ID. -constexpr auto NGHTTP2_H2_16_ALPN = StringRef::from_lit("\x5h2-16"); -constexpr auto NGHTTP2_H2_16 = StringRef::from_lit("h2-16"); +constexpr auto NGHTTP2_H2_16_ALPN = "\x5h2-16"_sr; +constexpr auto NGHTTP2_H2_16 = "h2-16"_sr; -constexpr auto NGHTTP2_H2_14_ALPN = StringRef::from_lit("\x5h2-14"); -constexpr auto NGHTTP2_H2_14 = StringRef::from_lit("h2-14"); +constexpr auto NGHTTP2_H2_14_ALPN = "\x5h2-14"_sr; +constexpr auto NGHTTP2_H2_14 = "h2-14"_sr; -constexpr auto NGHTTP2_H1_1_ALPN = StringRef::from_lit("\x8http/1.1"); -constexpr auto NGHTTP2_H1_1 = StringRef::from_lit("http/1.1"); +constexpr auto NGHTTP2_H1_1_ALPN = "\x8http/1.1"_sr; +constexpr auto NGHTTP2_H1_1 = "http/1.1"_sr; constexpr size_t NGHTTP2_MAX_UINT64_DIGITS = str_size("18446744073709551615"); @@ -185,35 +186,42 @@ OutputIt quote_string(OutputIt it, const StringRef &target) { // NUL byte. size_t quote_stringlen(const StringRef &target); -std::string format_hex(const unsigned char *s, size_t len); +static constexpr char LOWER_XDIGITS[] = "0123456789abcdef"; + +template <std::weakly_incrementable OutputIt> +OutputIt format_hex(OutputIt it, std::span<const uint8_t> s) { + for (auto c : s) { + *it++ = LOWER_XDIGITS[c >> 4]; + *it++ = LOWER_XDIGITS[c & 0xf]; + } -template <size_t N> std::string format_hex(const unsigned char (&s)[N]) { - return format_hex(s, N); + return it; } -template <size_t N> std::string format_hex(const std::array<uint8_t, N> &s) { - return format_hex(s.data(), s.size()); +template <typename T, size_t N = std::dynamic_extent, + std::weakly_incrementable OutputIt> +OutputIt format_hex(OutputIt it, std::span<T, N> s) { + return format_hex(it, std::span<const uint8_t>{as_uint8_span(s)}); } -StringRef format_hex(BlockAllocator &balloc, const StringRef &s); +std::string format_hex(std::span<const uint8_t> s); -static constexpr char LOWER_XDIGITS[] = "0123456789abcdef"; +template <typename T, size_t N = std::dynamic_extent> +std::string format_hex(std::span<T, N> s) { + return format_hex(std::span<const uint8_t>{as_uint8_span(s)}); +} -template <typename OutputIt> -OutputIt format_hex(OutputIt it, const StringRef &s) { - for (auto cc : s) { - uint8_t c = cc; - *it++ = LOWER_XDIGITS[c >> 4]; - *it++ = LOWER_XDIGITS[c & 0xf]; - } +StringRef format_hex(BlockAllocator &balloc, std::span<const uint8_t> s); - return it; +template <typename T, size_t N = std::dynamic_extent> +StringRef format_hex(BlockAllocator &balloc, std::span<T, N> s) { + return format_hex(balloc, std::span<const uint8_t>{as_uint8_span(s)}); } // decode_hex decodes hex string |s|, returns the decoded byte string. // This function assumes |s| is hex string, that is is_hex_string(s) // == true. -StringRef decode_hex(BlockAllocator &balloc, const StringRef &s); +std::span<const uint8_t> decode_hex(BlockAllocator &balloc, const StringRef &s); template <typename OutputIt> OutputIt decode_hex(OutputIt d_first, const StringRef &s) { @@ -289,14 +297,12 @@ inline char lowcase(char c) { template <typename InputIterator1, typename InputIterator2> bool starts_with(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { - if (last1 - first1 < last2 - first2) { - return false; - } - return std::equal(first2, last2, first1); + return std::distance(first1, last1) >= std::distance(first2, last2) && + std::equal(first2, last2, first1); } template <typename S, typename T> bool starts_with(const S &a, const T &b) { - return starts_with(a.begin(), a.end(), b.begin(), b.end()); + return starts_with(std::begin(a), std::end(a), std::begin(b), std::end(b)); } struct CaseCmp { @@ -308,107 +314,60 @@ struct CaseCmp { template <typename InputIterator1, typename InputIterator2> bool istarts_with(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { - if (last1 - first1 < last2 - first2) { - return false; - } - return std::equal(first2, last2, first1, CaseCmp()); + return std::distance(first1, last1) >= std::distance(first2, last2) && + std::equal(first2, last2, first1, CaseCmp()); } template <typename S, typename T> bool istarts_with(const S &a, const T &b) { - return istarts_with(a.begin(), a.end(), b.begin(), b.end()); -} - -template <typename T, typename CharT, size_t N> -bool istarts_with_l(const T &a, const CharT (&b)[N]) { - return istarts_with(a.begin(), a.end(), b, b + N - 1); + return istarts_with(std::begin(a), std::end(a), std::begin(b), std::end(b)); } template <typename InputIterator1, typename InputIterator2> bool ends_with(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { - if (last1 - first1 < last2 - first2) { - return false; - } - return std::equal(first2, last2, last1 - (last2 - first2)); -} + auto len1 = std::distance(first1, last1); + auto len2 = std::distance(first2, last2); -template <typename T, typename S> bool ends_with(const T &a, const S &b) { - return ends_with(a.begin(), a.end(), b.begin(), b.end()); + return len1 >= len2 && std::equal(first2, last2, first1 + (len1 - len2)); } -template <typename T, typename CharT, size_t N> -bool ends_with_l(const T &a, const CharT (&b)[N]) { - return ends_with(a.begin(), a.end(), b, b + N - 1); +template <typename T, typename S> bool ends_with(const T &a, const S &b) { + return ends_with(std::begin(a), std::end(a), std::begin(b), std::end(b)); } template <typename InputIterator1, typename InputIterator2> bool iends_with(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { - if (last1 - first1 < last2 - first2) { - return false; - } - return std::equal(first2, last2, last1 - (last2 - first2), CaseCmp()); -} + auto len1 = std::distance(first1, last1); + auto len2 = std::distance(first2, last2); -template <typename T, typename S> bool iends_with(const T &a, const S &b) { - return iends_with(a.begin(), a.end(), b.begin(), b.end()); + return len1 >= len2 && + std::equal(first2, last2, first1 + (len1 - len2), CaseCmp()); } -template <typename T, typename CharT, size_t N> -bool iends_with_l(const T &a, const CharT (&b)[N]) { - return iends_with(a.begin(), a.end(), b, b + N - 1); +template <typename T, typename S> bool iends_with(const T &a, const S &b) { + return iends_with(std::begin(a), std::end(a), std::begin(b), std::end(b)); } template <typename InputIt1, typename InputIt2> bool strieq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { - if (std::distance(first1, last1) != std::distance(first2, last2)) { - return false; - } - - return std::equal(first1, last1, first2, CaseCmp()); + return std::equal(first1, last1, first2, last2, CaseCmp()); } template <typename T, typename S> bool strieq(const T &a, const S &b) { - return strieq(a.begin(), a.end(), b.begin(), b.end()); -} - -template <typename CharT, typename InputIt, size_t N> -bool strieq_l(const CharT (&a)[N], InputIt b, size_t blen) { - return strieq(a, a + (N - 1), b, b + blen); -} - -template <typename CharT, size_t N, typename T> -bool strieq_l(const CharT (&a)[N], const T &b) { - return strieq(a, a + (N - 1), b.begin(), b.end()); -} - -template <typename InputIt1, typename InputIt2> -bool streq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { - if (std::distance(first1, last1) != std::distance(first2, last2)) { - return false; - } - return std::equal(first1, last1, first2); -} - -template <typename T, typename S> bool streq(const T &a, const S &b) { - return streq(a.begin(), a.end(), b.begin(), b.end()); + return strieq(std::begin(a), std::end(a), std::begin(b), std::end(b)); } -template <typename CharT, typename InputIt, size_t N> -bool streq_l(const CharT (&a)[N], InputIt b, size_t blen) { - return streq(a, a + (N - 1), b, b + blen); +template <typename T, typename S> +bool strieq(const T &a, const S &b, size_t blen) { + return std::equal(std::begin(a), std::end(a), std::begin(b), + std::next(std::begin(b), blen), CaseCmp()); } -template <typename CharT, size_t N, typename T> -bool streq_l(const CharT (&a)[N], const T &b) { - return streq(a, a + (N - 1), b.begin(), b.end()); -} - -// Returns true if |a| contains |b|. If both |a| and |b| are empty, -// this function returns false. -template <typename S, typename T> bool strifind(const S &a, const T &b) { - return std::search(a.begin(), a.end(), b.begin(), b.end(), CaseCmp()) != - a.end(); +template <typename T, typename S> +bool streq(const T &a, const S &b, size_t blen) { + return std::equal(std::begin(a), std::end(a), std::begin(b), + std::next(std::begin(b), blen)); } template <typename InputIt> void inp_strlower(InputIt first, InputIt last) { @@ -458,10 +417,10 @@ template <typename T, typename OutputIt> OutputIt utos(OutputIt dst, T n) { template <typename T> StringRef make_string_ref_uint(BlockAllocator &balloc, T n) { auto iov = make_byte_ref(balloc, NGHTTP2_MAX_UINT64_DIGITS + 1); - auto p = iov.base; + auto p = std::begin(iov); p = util::utos(p, n); *p = '\0'; - return StringRef{iov.base, p}; + return StringRef{std::span{std::begin(iov), p}}; } template <typename T> std::string utos_unit(T n) { @@ -735,35 +694,22 @@ int get_socket_error(int fd); // Returns true if |host| is IPv6 numeric address (e.g., ::1) bool ipv6_numeric_addr(const char *host); -// Parses NULL terminated string |s| as unsigned integer and returns -// the parsed integer. Additionally, if |s| ends with 'k', 'm', 'g' -// and its upper case characters, multiply the integer by 1024, 1024 * -// 1024 and 1024 * 1024 respectively. If there is an error, returns -// -1. -int64_t parse_uint_with_unit(const char *s); -// The following overload does not require |s| is NULL terminated. -int64_t parse_uint_with_unit(const uint8_t *s, size_t len); -int64_t parse_uint_with_unit(const StringRef &s); - -// Parses NULL terminated string |s| as unsigned integer and returns -// the parsed integer. If there is an error, returns -1. -int64_t parse_uint(const char *s); -// The following overload does not require |s| is NULL terminated. -int64_t parse_uint(const uint8_t *s, size_t len); -int64_t parse_uint(const std::string &s); -int64_t parse_uint(const StringRef &s); - -// Parses NULL terminated string |s| as unsigned integer and returns -// the parsed integer casted to double. If |s| ends with "s", the -// parsed value's unit is a second. If |s| ends with "ms", the unit -// is millisecond. Similarly, it also supports 'm' and 'h' for -// minutes and hours respectively. If none of them are given, the -// unit is second. This function returns -// std::numeric_limits<double>::infinity() if error occurs. -double parse_duration_with_unit(const char *s); -// The following overload does not require |s| is NULL terminated. -double parse_duration_with_unit(const uint8_t *s, size_t len); -double parse_duration_with_unit(const StringRef &s); +// Parses |s| as unsigned integer and returns the parsed integer. +// Additionally, if |s| ends with 'k', 'm', 'g' and its upper case +// characters, multiply the integer by 1024, 1024 * 1024 and 1024 * +// 1024 respectively. If there is an error, returns no value. +std::optional<int64_t> parse_uint_with_unit(const StringRef &s); + +// Parses |s| as unsigned integer and returns the parsed integer.. +std::optional<int64_t> parse_uint(const StringRef &s); + +// Parses |s| as unsigned integer and returns the parsed integer +// casted to double. If |s| ends with "s", the parsed value's unit is +// a second. If |s| ends with "ms", the unit is millisecond. +// Similarly, it also supports 'm' and 'h' for minutes and hours +// respectively. If none of them are given, the unit is second. This +// function returns no value if error occurs. +std::optional<double> parse_duration_with_unit(const StringRef &s); // Returns string representation of time duration |t|. If t has // fractional part (at least more than or equal to 1e-3), |t| is @@ -792,7 +738,7 @@ StringRef make_hostport(BlockAllocator &balloc, const StringRef &host, template <typename OutputIt> StringRef make_hostport(OutputIt first, const StringRef &host, uint16_t port) { - auto ipv6 = ipv6_numeric_addr(host.c_str()); + auto ipv6 = ipv6_numeric_addr(host.data()); auto serv = utos(port); auto p = first; @@ -812,7 +758,7 @@ StringRef make_hostport(OutputIt first, const StringRef &host, uint16_t port) { *p = '\0'; - return StringRef{first, p}; + return StringRef{std::span{first, p}}; } // Creates "host:port" string using given |host| and |port|. If @@ -828,7 +774,7 @@ StringRef make_http_hostport(OutputIt first, const StringRef &host, return make_hostport(first, host, port); } - auto ipv6 = ipv6_numeric_addr(host.c_str()); + auto ipv6 = ipv6_numeric_addr(host.data()); auto p = first; if (ipv6) { @@ -843,7 +789,7 @@ StringRef make_http_hostport(OutputIt first, const StringRef &host, *p = '\0'; - return StringRef{first, p}; + return StringRef{std::span{first, p}}; } // hexdump dumps |data| of length |datalen| in the format similar to @@ -909,13 +855,13 @@ void shuffle(RandomIt first, RandomIt last, Generator &&gen, SwapFun fun) { return; } - for (unsigned int i = 0; i < static_cast<unsigned int>(len - 1); ++i) { - auto dis = std::uniform_int_distribution<unsigned int>(i, len - 1); - auto j = dis(gen); - if (i == j) { - continue; - } - fun(first + i, first + j); + using dist_type = std::uniform_int_distribution<size_t>; + using param_type = dist_type::param_type; + + dist_type d; + + for (decltype(len) i = 0; i < len - 1; ++i) { + fun(first + i, first + d(gen, param_type(i, len - 1))); } } diff --git a/src/util_test.cc b/src/util_test.cc index 2e01e9d..e65c3a8 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -36,6 +36,7 @@ #include "template.h" using namespace nghttp2; +using namespace std::literals; namespace shrpx { @@ -70,7 +71,6 @@ const MunitTest tests[]{ munit_void_test(test_util_parse_config_str_list), munit_void_test(test_util_make_http_hostport), munit_void_test(test_util_make_hostport), - munit_void_test(test_util_strifind), munit_void_test(test_util_random_alpha_digit), munit_void_test(test_util_format_hex), munit_void_test(test_util_is_hex_string), @@ -88,33 +88,14 @@ const MunitSuite util_suite{ }; void test_util_streq(void) { - assert_true( - util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); - assert_false(util::streq(StringRef::from_lit("alpha"), - StringRef::from_lit("alphabravo"))); - assert_false(util::streq(StringRef::from_lit("alphabravo"), - StringRef::from_lit("alpha"))); - assert_false( - util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); - assert_false(util::streq(StringRef{}, StringRef::from_lit("a"))); - assert_true(util::streq(StringRef{}, StringRef{})); - assert_false(util::streq(StringRef::from_lit("alpha"), StringRef{})); - - assert_false( - util::streq(StringRef::from_lit("alph"), StringRef::from_lit("alpha"))); - assert_false( - util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alph"))); - assert_false( - util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); - - assert_true(util::streq_l("alpha", "alpha", 5)); - assert_true(util::streq_l("alpha", "alphabravo", 5)); - assert_false(util::streq_l("alpha", "alphabravo", 6)); - assert_false(util::streq_l("alphabravo", "alpha", 5)); - assert_false(util::streq_l("alpha", "alphA", 5)); - assert_false(util::streq_l("", "a", 1)); - assert_true(util::streq_l("", "", 0)); - assert_false(util::streq_l("alpha", "", 0)); + assert_true(util::streq("alpha"_sr, "alpha"_sr, 5)); + assert_true(util::streq("alpha"_sr, "alphabravo"_sr, 5)); + assert_false(util::streq("alpha"_sr, "alphabravo"_sr, 6)); + assert_false(util::streq("alphabravo"_sr, "alpha"_sr, 5)); + assert_false(util::streq("alpha"_sr, "alphA"_sr, 5)); + assert_false(util::streq(""_sr, "a"_sr, 1)); + assert_true(util::streq(""_sr, ""_sr, 0)); + assert_false(util::streq("alpha"_sr, ""_sr, 0)); } void test_util_strieq(void) { @@ -124,27 +105,16 @@ void test_util_strieq(void) { assert_false(util::strieq(std::string("alpha"), std::string("AlPhA "))); assert_false(util::strieq(std::string(), std::string("AlPhA "))); - assert_true( - util::strieq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); - assert_true( - util::strieq(StringRef::from_lit("alpha"), StringRef::from_lit("AlPhA"))); + assert_true(util::strieq("alpha"_sr, "alpha"_sr)); + assert_true(util::strieq("alpha"_sr, "AlPhA"_sr)); assert_true(util::strieq(StringRef{}, StringRef{})); - assert_false(util::strieq(StringRef::from_lit("alpha"), - StringRef::from_lit("AlPhA "))); - assert_false( - util::strieq(StringRef::from_lit(""), StringRef::from_lit("AlPhA "))); + assert_false(util::strieq("alpha"_sr, "AlPhA "_sr)); + assert_false(util::strieq(""_sr, "AlPhA "_sr)); - assert_true(util::strieq_l("alpha", "alpha", 5)); - assert_true(util::strieq_l("alpha", "AlPhA", 5)); - assert_true(util::strieq_l("", static_cast<const char *>(nullptr), 0)); - assert_false(util::strieq_l("alpha", "AlPhA ", 6)); - assert_false(util::strieq_l("", "AlPhA ", 6)); - - assert_true(util::strieq_l("alpha", StringRef::from_lit("alpha"))); - assert_true(util::strieq_l("alpha", StringRef::from_lit("AlPhA"))); - assert_true(util::strieq_l("", StringRef{})); - assert_false(util::strieq_l("alpha", StringRef::from_lit("AlPhA "))); - assert_false(util::strieq_l("", StringRef::from_lit("AlPhA "))); + assert_true(util::strieq("alpha"_sr, "alpha"_sr, 5)); + assert_true(util::strieq("alpha"_sr, "AlPhA"_sr, 5)); + assert_false(util::strieq("alpha"_sr, "AlPhA "_sr, 6)); + assert_false(util::strieq(""_sr, "AlPhA "_sr, 6)); } void test_util_inp_strlower(void) { @@ -164,12 +134,8 @@ void test_util_inp_strlower(void) { void test_util_to_base64(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "AAA++B/=", - util::to_base64(balloc, StringRef::from_lit("AAA--B_")).str()); - assert_stdstring_equal( - "AAA++B/B", - util::to_base64(balloc, StringRef::from_lit("AAA--B_B")).str()); + assert_stdsv_equal("AAA++B/="sv, util::to_base64(balloc, "AAA--B_"_sr)); + assert_stdsv_equal("AAA++B/B"sv, util::to_base64(balloc, "AAA--B_B"_sr)); } void test_util_to_token68(void) { @@ -184,18 +150,11 @@ void test_util_to_token68(void) { void test_util_percent_encode_token(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "h2", - util::percent_encode_token(balloc, StringRef::from_lit("h2")).str()); - assert_stdstring_equal( - "h3~", - util::percent_encode_token(balloc, StringRef::from_lit("h3~")).str()); - assert_stdstring_equal( - "100%25", - util::percent_encode_token(balloc, StringRef::from_lit("100%")).str()); - assert_stdstring_equal( - "http%202", - util::percent_encode_token(balloc, StringRef::from_lit("http 2")).str()); + assert_stdsv_equal("h2"sv, util::percent_encode_token(balloc, "h2"_sr)); + assert_stdsv_equal("h3~"sv, util::percent_encode_token(balloc, "h3~"_sr)); + assert_stdsv_equal("100%25"sv, util::percent_encode_token(balloc, "100%"_sr)); + assert_stdsv_equal("http%202"sv, + util::percent_encode_token(balloc, "http 2"_sr)); } void test_util_percent_decode(void) { @@ -216,27 +175,20 @@ void test_util_percent_decode(void) { } BlockAllocator balloc(1024, 1024); - assert_stdstring_equal( - "foobar", - util::percent_decode(balloc, StringRef::from_lit("%66%6F%6f%62%61%72")) - .str()); + assert_stdsv_equal("foobar"sv, + util::percent_decode(balloc, "%66%6F%6f%62%61%72"_sr)); - assert_stdstring_equal( - "f%6", util::percent_decode(balloc, StringRef::from_lit("%66%6")).str()); + assert_stdsv_equal("f%6"sv, util::percent_decode(balloc, "%66%6"_sr)); - assert_stdstring_equal( - "f%", util::percent_decode(balloc, StringRef::from_lit("%66%")).str()); + assert_stdsv_equal("f%"sv, util::percent_decode(balloc, "%66%"_sr)); } void test_util_quote_string(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "alpha", util::quote_string(balloc, StringRef::from_lit("alpha")).str()); - assert_stdstring_equal( - "", util::quote_string(balloc, StringRef::from_lit("")).str()); - assert_stdstring_equal( - "\\\"alpha\\\"", - util::quote_string(balloc, StringRef::from_lit("\"alpha\"")).str()); + assert_stdsv_equal("alpha"sv, util::quote_string(balloc, "alpha"_sr)); + assert_stdsv_equal(""sv, util::quote_string(balloc, ""_sr)); + assert_stdsv_equal("\\\"alpha\\\""sv, + util::quote_string(balloc, "\"alpha\""_sr)); } void test_util_utox(void) { @@ -255,17 +207,15 @@ void test_util_http_date(void) { std::array<char, 30> http_buf; - assert_stdstring_equal( - "Thu, 01 Jan 1970 00:00:00 GMT", + assert_stdsv_equal( + "Thu, 01 Jan 1970 00:00:00 GMT"sv, util::format_http_date(http_buf.data(), - std::chrono::system_clock::time_point()) - .str()); - assert_stdstring_equal( - "Wed, 29 Feb 2012 09:15:16 GMT", + std::chrono::system_clock::time_point())); + assert_stdsv_equal( + "Wed, 29 Feb 2012 09:15:16 GMT"sv, util::format_http_date(http_buf.data(), std::chrono::system_clock::time_point( - std::chrono::seconds(1330506916))) - .str()); + std::chrono::seconds(1330506916)))); } void test_util_select_h2(void) { @@ -310,7 +260,7 @@ void test_util_select_h2(void) { // picked up because it has precedence over the other. const unsigned char t6[] = "\x5h2-14\x5h2-16"; assert_true(util::select_h2(&out, &outlen, t6, sizeof(t6) - 1)); - assert_true(util::streq(NGHTTP2_H2_16, StringRef{out, outlen})); + assert_stdsv_equal(NGHTTP2_H2_16, (StringRef{out, outlen})); } void test_util_ipv6_numeric_addr(void) { @@ -336,11 +286,11 @@ void test_util_utos(void) { void test_util_make_string_ref_uint(void) { BlockAllocator balloc(1024, 1024); - assert_stdstring_equal("0", util::make_string_ref_uint(balloc, 0).str()); - assert_stdstring_equal("123", util::make_string_ref_uint(balloc, 123).str()); - assert_stdstring_equal( - "18446744073709551615", - util::make_string_ref_uint(balloc, 18446744073709551615ULL).str()); + assert_stdsv_equal("0"sv, util::make_string_ref_uint(balloc, 0)); + assert_stdsv_equal("123"sv, util::make_string_ref_uint(balloc, 123)); + assert_stdsv_equal( + "18446744073709551615"sv, + util::make_string_ref_uint(balloc, 18446744073709551615ULL)); } void test_util_utos_unit(void) { @@ -369,65 +319,69 @@ void test_util_utos_funit(void) { } void test_util_parse_uint_with_unit(void) { - assert_int64(0, ==, util::parse_uint_with_unit("0")); - assert_int64(1023, ==, util::parse_uint_with_unit("1023")); - assert_int64(1024, ==, util::parse_uint_with_unit("1k")); - assert_int64(2048, ==, util::parse_uint_with_unit("2K")); - assert_int64(1 << 20, ==, util::parse_uint_with_unit("1m")); - assert_int64(1 << 21, ==, util::parse_uint_with_unit("2M")); - assert_int64(1 << 30, ==, util::parse_uint_with_unit("1g")); - assert_int64(1LL << 31, ==, util::parse_uint_with_unit("2G")); + assert_int64(0, ==, util::parse_uint_with_unit("0").value_or(-1)); + assert_int64(1023, ==, util::parse_uint_with_unit("1023").value_or(-1)); + assert_int64(1024, ==, util::parse_uint_with_unit("1k").value_or(-1)); + assert_int64(2048, ==, util::parse_uint_with_unit("2K").value_or(-1)); + assert_int64(1 << 20, ==, util::parse_uint_with_unit("1m").value_or(-1)); + assert_int64(1 << 21, ==, util::parse_uint_with_unit("2M").value_or(-1)); + assert_int64(1 << 30, ==, util::parse_uint_with_unit("1g").value_or(-1)); + assert_int64(1LL << 31, ==, util::parse_uint_with_unit("2G").value_or(-1)); assert_int64(9223372036854775807LL, ==, - util::parse_uint_with_unit("9223372036854775807")); + util::parse_uint_with_unit("9223372036854775807").value_or(-1)); // check overflow case - assert_int64(-1, ==, util::parse_uint_with_unit("9223372036854775808")); - assert_int64(-1, ==, util::parse_uint_with_unit("10000000000000000000")); - assert_int64(-1, ==, util::parse_uint_with_unit("9223372036854775807G")); + assert_false(util::parse_uint_with_unit("9223372036854775808")); + assert_false(util::parse_uint_with_unit("10000000000000000000")); + assert_false(util::parse_uint_with_unit("9223372036854775807G")); // bad characters - assert_int64(-1, ==, util::parse_uint_with_unit("1.1")); - assert_int64(-1, ==, util::parse_uint_with_unit("1a")); - assert_int64(-1, ==, util::parse_uint_with_unit("a1")); - assert_int64(-1, ==, util::parse_uint_with_unit("1T")); - assert_int64(-1, ==, util::parse_uint_with_unit("")); + assert_false(util::parse_uint_with_unit("1.1")); + assert_false(util::parse_uint_with_unit("1a")); + assert_false(util::parse_uint_with_unit("a1")); + assert_false(util::parse_uint_with_unit("1T")); + assert_false(util::parse_uint_with_unit("")); } void test_util_parse_uint(void) { - assert_int64(0, ==, util::parse_uint("0")); - assert_int64(1023, ==, util::parse_uint("1023")); - assert_int64(-1, ==, util::parse_uint("1k")); + assert_int64(0, ==, util::parse_uint("0").value_or(-1)); + assert_int64(1023, ==, util::parse_uint("1023").value_or(-1)); + assert_false(util::parse_uint("1k")); assert_int64(9223372036854775807LL, ==, - util::parse_uint("9223372036854775807")); + util::parse_uint("9223372036854775807").value_or(-1)); // check overflow case - assert_int64(-1, ==, util::parse_uint("9223372036854775808")); - assert_int64(-1, ==, util::parse_uint("10000000000000000000")); + assert_false(util::parse_uint("9223372036854775808")); + assert_false(util::parse_uint("10000000000000000000")); // bad characters - assert_int64(-1, ==, util::parse_uint("1.1")); - assert_int64(-1, ==, util::parse_uint("1a")); - assert_int64(-1, ==, util::parse_uint("a1")); - assert_int64(-1, ==, util::parse_uint("1T")); - assert_int64(-1, ==, util::parse_uint("")); + assert_false(util::parse_uint("1.1")); + assert_false(util::parse_uint("1a")); + assert_false(util::parse_uint("a1")); + assert_false(util::parse_uint("1T")); + assert_false(util::parse_uint("")); } void test_util_parse_duration_with_unit(void) { - assert_double(0., ==, util::parse_duration_with_unit("0")); - assert_double(123., ==, util::parse_duration_with_unit("123")); - assert_double(123., ==, util::parse_duration_with_unit("123s")); - assert_double(0.500, ==, util::parse_duration_with_unit("500ms")); - assert_double(123., ==, util::parse_duration_with_unit("123S")); - assert_double(0.500, ==, util::parse_duration_with_unit("500MS")); - assert_double(180, ==, util::parse_duration_with_unit("3m")); - assert_double(3600 * 5, ==, util::parse_duration_with_unit("5h")); - - auto err = std::numeric_limits<double>::infinity(); + auto inf = std::numeric_limits<double>::infinity(); + + assert_double(0., ==, util::parse_duration_with_unit("0").value_or(inf)); + assert_double(123., ==, util::parse_duration_with_unit("123").value_or(inf)); + assert_double(123., ==, util::parse_duration_with_unit("123s").value_or(inf)); + assert_double(0.500, ==, + util::parse_duration_with_unit("500ms").value_or(inf)); + assert_double(123., ==, util::parse_duration_with_unit("123S").value_or(inf)); + assert_double(0.500, ==, + util::parse_duration_with_unit("500MS").value_or(inf)); + assert_double(180, ==, util::parse_duration_with_unit("3m").value_or(inf)); + assert_double(3600 * 5, ==, + util::parse_duration_with_unit("5h").value_or(inf)); + // check overflow case - assert_double(err, ==, util::parse_duration_with_unit("9223372036854775808")); + assert_false(util::parse_duration_with_unit("9223372036854775808")); // bad characters - assert_double(err, ==, util::parse_duration_with_unit("0u")); - assert_double(err, ==, util::parse_duration_with_unit("0xs")); - assert_double(err, ==, util::parse_duration_with_unit("0mt")); - assert_double(err, ==, util::parse_duration_with_unit("0mss")); - assert_double(err, ==, util::parse_duration_with_unit("s")); - assert_double(err, ==, util::parse_duration_with_unit("ms")); + assert_false(util::parse_duration_with_unit("0u")); + assert_false(util::parse_duration_with_unit("0xs")); + assert_false(util::parse_duration_with_unit("0mt")); + assert_false(util::parse_duration_with_unit("0mss")); + assert_false(util::parse_duration_with_unit("s")); + assert_false(util::parse_duration_with_unit("ms")); } void test_util_duration_str(void) { @@ -469,51 +423,32 @@ void test_util_format_duration(void) { } void test_util_starts_with(void) { - assert_true(util::starts_with(StringRef::from_lit("foo"), - StringRef::from_lit("foo"))); - assert_true(util::starts_with(StringRef::from_lit("fooo"), - StringRef::from_lit("foo"))); - assert_true(util::starts_with(StringRef::from_lit("ofoo"), StringRef{})); - assert_false(util::starts_with(StringRef::from_lit("ofoo"), - StringRef::from_lit("foo"))); - - assert_true(util::istarts_with(StringRef::from_lit("FOO"), - StringRef::from_lit("fOO"))); - assert_true(util::istarts_with(StringRef::from_lit("ofoo"), StringRef{})); - assert_true(util::istarts_with(StringRef::from_lit("fOOo"), - StringRef::from_lit("Foo"))); - assert_false(util::istarts_with(StringRef::from_lit("ofoo"), - StringRef::from_lit("foo"))); - - assert_true(util::istarts_with_l(StringRef::from_lit("fOOo"), "Foo")); - assert_false(util::istarts_with_l(StringRef::from_lit("ofoo"), "foo")); + assert_true(util::starts_with("foo"_sr, "foo"_sr)); + assert_true(util::starts_with("fooo"_sr, "foo"_sr)); + assert_true(util::starts_with("ofoo"_sr, StringRef{})); + assert_false(util::starts_with("ofoo"_sr, "foo"_sr)); + + assert_true(util::istarts_with("FOO"_sr, "fOO"_sr)); + assert_true(util::istarts_with("ofoo"_sr, StringRef{})); + assert_true(util::istarts_with("fOOo"_sr, "Foo"_sr)); + assert_false(util::istarts_with("ofoo"_sr, "foo"_sr)); } void test_util_ends_with(void) { - assert_true( - util::ends_with(StringRef::from_lit("foo"), StringRef::from_lit("foo"))); - assert_true(util::ends_with(StringRef::from_lit("foo"), StringRef{})); - assert_true( - util::ends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("foo"))); - assert_false( - util::ends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("fo"))); - - assert_true( - util::iends_with(StringRef::from_lit("fOo"), StringRef::from_lit("Foo"))); - assert_true(util::iends_with(StringRef::from_lit("foo"), StringRef{})); - assert_true(util::iends_with(StringRef::from_lit("oFoo"), - StringRef::from_lit("fOO"))); - assert_false( - util::iends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("fo"))); + assert_true(util::ends_with("foo"_sr, "foo"_sr)); + assert_true(util::ends_with("foo"_sr, StringRef{})); + assert_true(util::ends_with("ofoo"_sr, "foo"_sr)); + assert_false(util::ends_with("ofoo"_sr, "fo"_sr)); - assert_true(util::iends_with_l(StringRef::from_lit("oFoo"), "fOO")); - assert_false(util::iends_with_l(StringRef::from_lit("ofoo"), "fo")); + assert_true(util::iends_with("fOo"_sr, "Foo"_sr)); + assert_true(util::iends_with("foo"_sr, StringRef{})); + assert_true(util::iends_with("oFoo"_sr, "fOO"_sr)); + assert_false(util::iends_with("ofoo"_sr, "fo"_sr)); } void test_util_parse_http_date(void) { assert_int64(1001939696, ==, - util::parse_http_date( - StringRef::from_lit("Mon, 1 Oct 2001 12:34:56 GMT"))); + util::parse_http_date("Mon, 1 Oct 2001 12:34:56 GMT"_sr)); } void test_util_localtime_date(void) { @@ -535,21 +470,19 @@ void test_util_localtime_date(void) { std::array<char, 27> common_buf; - assert_stdstring_equal( - "02/Oct/2001:00:34:56 +1200", + assert_stdsv_equal( + "02/Oct/2001:00:34:56 +1200"sv, util::format_common_log(common_buf.data(), std::chrono::system_clock::time_point( - std::chrono::seconds(1001939696))) - .str()); + std::chrono::seconds(1001939696)))); std::array<char, 30> iso8601_buf; - assert_stdstring_equal( - "2001-10-02T00:34:56.123+12:00", + assert_stdsv_equal( + "2001-10-02T00:34:56.123+12:00"sv, util::format_iso8601(iso8601_buf.data(), std::chrono::system_clock::time_point( - std::chrono::milliseconds(1001939696123LL))) - .str()); + std::chrono::milliseconds(1001939696123LL)))); if (tz) { setenv("TZ", tz, 1); @@ -562,16 +495,16 @@ void test_util_localtime_date(void) { void test_util_get_uint64(void) { { - auto v = std::array<unsigned char, 8>{ - {0x01, 0x12, 0x34, 0x56, 0xff, 0x9a, 0xab, 0xbc}}; + auto v = std::to_array<unsigned char>( + {0x01, 0x12, 0x34, 0x56, 0xff, 0x9a, 0xab, 0xbc}); auto n = util::get_uint64(v.data()); assert_uint64(0x01123456ff9aabbcULL, ==, n); } { - auto v = std::array<unsigned char, 8>{ - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; + auto v = std::to_array<unsigned char>( + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}); auto n = util::get_uint64(v.data()); @@ -580,16 +513,16 @@ void test_util_get_uint64(void) { } void test_util_parse_config_str_list(void) { - auto res = util::parse_config_str_list(StringRef::from_lit("a")); + auto res = util::parse_config_str_list("a"_sr); assert_size(1, ==, res.size()); assert_stdstring_equal("a", res[0]); - res = util::parse_config_str_list(StringRef::from_lit("a,")); + res = util::parse_config_str_list("a,"_sr); assert_size(2, ==, res.size()); assert_stdstring_equal("a", res[0]); assert_stdstring_equal("", res[1]); - res = util::parse_config_str_list(StringRef::from_lit(":a::"), ':'); + res = util::parse_config_str_list(":a::"_sr, ':'); assert_size(4, ==, res.size()); assert_stdstring_equal("", res[0]); assert_stdstring_equal("a", res[1]); @@ -600,7 +533,7 @@ void test_util_parse_config_str_list(void) { assert_size(1, ==, res.size()); assert_stdstring_equal("", res[0]); - res = util::parse_config_str_list(StringRef::from_lit("alpha,bravo,charlie")); + res = util::parse_config_str_list("alpha,bravo,charlie"_sr); assert_size(3, ==, res.size()); assert_stdstring_equal("alpha", res[0]); assert_stdstring_equal("bravo", res[1]); @@ -610,56 +543,27 @@ void test_util_parse_config_str_list(void) { void test_util_make_http_hostport(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "localhost", - util::make_http_hostport(balloc, StringRef::from_lit("localhost"), 80) - .str()); - assert_stdstring_equal( - "[::1]", - util::make_http_hostport(balloc, StringRef::from_lit("::1"), 443).str()); - assert_stdstring_equal( - "localhost:3000", - util::make_http_hostport(balloc, StringRef::from_lit("localhost"), 3000) - .str()); + assert_stdsv_equal("localhost"sv, + util::make_http_hostport(balloc, "localhost"_sr, 80)); + assert_stdsv_equal("[::1]"sv, + util::make_http_hostport(balloc, "::1"_sr, 443)); + assert_stdsv_equal("localhost:3000"sv, + util::make_http_hostport(balloc, "localhost"_sr, 3000)); } void test_util_make_hostport(void) { std::array<char, util::max_hostport> hostport_buf; - assert_stdstring_equal( - "localhost:80", util::make_hostport(std::begin(hostport_buf), - StringRef::from_lit("localhost"), 80) - .str()); - assert_stdstring_equal("[::1]:443", - util::make_hostport(std::begin(hostport_buf), - StringRef::from_lit("::1"), 443) - .str()); + assert_stdsv_equal( + "localhost:80"sv, + util::make_hostport(std::begin(hostport_buf), "localhost"_sr, 80)); + assert_stdsv_equal( + "[::1]:443"sv, + util::make_hostport(std::begin(hostport_buf), "::1"_sr, 443)); BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "localhost:80", - util::make_hostport(balloc, StringRef::from_lit("localhost"), 80).str()); - assert_stdstring_equal( - "[::1]:443", - util::make_hostport(balloc, StringRef::from_lit("::1"), 443).str()); -} - -void test_util_strifind(void) { - assert_true(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), - StringRef::from_lit("gzip"))); - - assert_true(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), - StringRef::from_lit("dEflate"))); - - assert_true(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), - StringRef::from_lit("BZIP2"))); - - assert_true(util::strifind(StringRef::from_lit("nghttp2"), StringRef{})); - - // Be aware this fact - assert_false(util::strifind(StringRef{}, StringRef{})); - - assert_false(util::strifind(StringRef::from_lit("nghttp2"), - StringRef::from_lit("http1"))); + assert_stdsv_equal("localhost:80"sv, + util::make_hostport(balloc, "localhost"_sr, 80)); + assert_stdsv_equal("[::1]:443"sv, util::make_hostport(balloc, "::1"_sr, 443)); } void test_util_random_alpha_digit(void) { @@ -680,123 +584,121 @@ void test_util_random_alpha_digit(void) { void test_util_format_hex(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "0ff0", util::format_hex(balloc, StringRef::from_lit("\x0f\xf0")).str()); - assert_stdstring_equal( - "", util::format_hex(balloc, StringRef::from_lit("")).str()); + assert_stdsv_equal("0ff0"sv, + util::format_hex(balloc, std::span{"\x0f\xf0"_sr})); + assert_stdsv_equal(""sv, + util::format_hex(balloc, std::span<const uint8_t>{})); + + union T { + uint16_t x; + uint8_t y[2]; + }; + + auto t = T{.y = {0xbe, 0xef}}; + + assert_stdstring_equal("beef", util::format_hex(std::span{&t.x, 1})); + + std::string o; + o.resize(4); + + assert_true(std::end(o) == + util::format_hex(std::begin(o), std::span{&t.x, 1})); + assert_stdstring_equal("beef", o); + + struct S { + uint8_t x[8]; + }; + + auto s = S{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf8}}; + + assert_stdstring_equal("01020304050607f8", util::format_hex(s.x)); } void test_util_is_hex_string(void) { assert_true(util::is_hex_string(StringRef{})); - assert_true(util::is_hex_string(StringRef::from_lit("0123456789abcdef"))); - assert_true(util::is_hex_string(StringRef::from_lit("0123456789ABCDEF"))); - assert_false(util::is_hex_string(StringRef::from_lit("000"))); - assert_false(util::is_hex_string(StringRef::from_lit("XX"))); + assert_true(util::is_hex_string("0123456789abcdef"_sr)); + assert_true(util::is_hex_string("0123456789ABCDEF"_sr)); + assert_false(util::is_hex_string("000"_sr)); + assert_false(util::is_hex_string("XX"_sr)); } void test_util_decode_hex(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "\x0f\xf0", util::decode_hex(balloc, StringRef::from_lit("0ff0")).str()); - assert_stdstring_equal("", util::decode_hex(balloc, StringRef{}).str()); + assert_stdsv_equal("\x0f\xf0"sv, + StringRef{util::decode_hex(balloc, "0ff0"_sr)}); + assert_stdsv_equal(""sv, StringRef{util::decode_hex(balloc, StringRef{})}); } void test_util_extract_host(void) { - assert_stdstring_equal("foo", - util::extract_host(StringRef::from_lit("foo")).str()); - assert_stdstring_equal("foo", - util::extract_host(StringRef::from_lit("foo:")).str()); - assert_stdstring_equal( - "foo", util::extract_host(StringRef::from_lit("foo:0")).str()); - assert_stdstring_equal( - "[::1]", util::extract_host(StringRef::from_lit("[::1]")).str()); - assert_stdstring_equal( - "[::1]", util::extract_host(StringRef::from_lit("[::1]:")).str()); - - assert_true(util::extract_host(StringRef::from_lit(":foo")).empty()); - assert_true(util::extract_host(StringRef::from_lit("[::1")).empty()); - assert_true(util::extract_host(StringRef::from_lit("[::1]0")).empty()); + assert_stdsv_equal("foo"sv, util::extract_host("foo"_sr)); + assert_stdsv_equal("foo"sv, util::extract_host("foo:"_sr)); + assert_stdsv_equal("foo"sv, util::extract_host("foo:0"_sr)); + assert_stdsv_equal("[::1]"sv, util::extract_host("[::1]"_sr)); + assert_stdsv_equal("[::1]"sv, util::extract_host("[::1]:"_sr)); + + assert_true(util::extract_host(":foo"_sr).empty()); + assert_true(util::extract_host("[::1"_sr).empty()); + assert_true(util::extract_host("[::1]0"_sr).empty()); assert_true(util::extract_host(StringRef{}).empty()); } void test_util_split_hostport(void) { - assert_true(std::make_pair(StringRef::from_lit("foo"), StringRef{}) == - util::split_hostport(StringRef::from_lit("foo"))); - assert_true( - std::make_pair(StringRef::from_lit("foo"), StringRef::from_lit("80")) == - util::split_hostport(StringRef::from_lit("foo:80"))); - assert_true( - std::make_pair(StringRef::from_lit("::1"), StringRef::from_lit("80")) == - util::split_hostport(StringRef::from_lit("[::1]:80"))); - assert_true(std::make_pair(StringRef::from_lit("::1"), StringRef{}) == - util::split_hostport(StringRef::from_lit("[::1]"))); + assert_true(std::make_pair("foo"_sr, StringRef{}) == + util::split_hostport("foo"_sr)); + assert_true(std::make_pair("foo"_sr, "80"_sr) == + util::split_hostport("foo:80"_sr)); + assert_true(std::make_pair("::1"_sr, "80"_sr) == + util::split_hostport("[::1]:80"_sr)); + assert_true(std::make_pair("::1"_sr, StringRef{}) == + util::split_hostport("[::1]"_sr)); assert_true(std::make_pair(StringRef{}, StringRef{}) == util::split_hostport(StringRef{})); assert_true(std::make_pair(StringRef{}, StringRef{}) == - util::split_hostport(StringRef::from_lit("[::1]:"))); + util::split_hostport("[::1]:"_sr)); assert_true(std::make_pair(StringRef{}, StringRef{}) == - util::split_hostport(StringRef::from_lit("foo:"))); + util::split_hostport("foo:"_sr)); assert_true(std::make_pair(StringRef{}, StringRef{}) == - util::split_hostport(StringRef::from_lit("[::1:"))); + util::split_hostport("[::1:"_sr)); assert_true(std::make_pair(StringRef{}, StringRef{}) == - util::split_hostport(StringRef::from_lit("[::1]80"))); + util::split_hostport("[::1]80"_sr)); } void test_util_split_str(void) { - assert_true(std::vector<StringRef>{StringRef::from_lit("")} == - util::split_str(StringRef::from_lit(""), ',')); - assert_true(std::vector<StringRef>{StringRef::from_lit("alpha")} == - util::split_str(StringRef::from_lit("alpha"), ',')); - assert_true((std::vector<StringRef>{StringRef::from_lit("alpha"), - StringRef::from_lit("")}) == - util::split_str(StringRef::from_lit("alpha,"), ',')); - assert_true((std::vector<StringRef>{StringRef::from_lit("alpha"), - StringRef::from_lit("bravo")}) == - util::split_str(StringRef::from_lit("alpha,bravo"), ',')); - assert_true((std::vector<StringRef>{StringRef::from_lit("alpha"), - StringRef::from_lit("bravo"), - StringRef::from_lit("charlie")}) == - util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',')); - assert_true( - (std::vector<StringRef>{StringRef::from_lit("alpha"), - StringRef::from_lit("bravo"), - StringRef::from_lit("charlie")}) == - util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',', 0)); - assert_true(std::vector<StringRef>{StringRef::from_lit("")} == - util::split_str(StringRef::from_lit(""), ',', 1)); - assert_true(std::vector<StringRef>{StringRef::from_lit("")} == - util::split_str(StringRef::from_lit(""), ',', 2)); - assert_true( - (std::vector<StringRef>{StringRef::from_lit("alpha"), - StringRef::from_lit("bravo,charlie")}) == - util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',', 2)); - assert_true(std::vector<StringRef>{StringRef::from_lit("alpha")} == - util::split_str(StringRef::from_lit("alpha"), ',', 2)); - assert_true((std::vector<StringRef>{StringRef::from_lit("alpha"), - StringRef::from_lit("")}) == - util::split_str(StringRef::from_lit("alpha,"), ',', 2)); - assert_true(std::vector<StringRef>{StringRef::from_lit("alpha")} == - util::split_str(StringRef::from_lit("alpha"), ',', 0)); - assert_true( - std::vector<StringRef>{StringRef::from_lit("alpha,bravo,charlie")} == - util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',', 1)); + assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',')); + assert_true(std::vector<StringRef>{"alpha"_sr} == + util::split_str("alpha"_sr, ',')); + assert_true((std::vector<StringRef>{"alpha"_sr, ""_sr}) == + util::split_str("alpha,"_sr, ',')); + assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr}) == + util::split_str("alpha,bravo"_sr, ',')); + assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr, "charlie"_sr}) == + util::split_str("alpha,bravo,charlie"_sr, ',')); + assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr, "charlie"_sr}) == + util::split_str("alpha,bravo,charlie"_sr, ',', 0)); + assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',', 1)); + assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',', 2)); + assert_true((std::vector<StringRef>{"alpha"_sr, "bravo,charlie"_sr}) == + util::split_str("alpha,bravo,charlie"_sr, ',', 2)); + assert_true(std::vector<StringRef>{"alpha"_sr} == + util::split_str("alpha"_sr, ',', 2)); + assert_true((std::vector<StringRef>{"alpha"_sr, ""_sr}) == + util::split_str("alpha,"_sr, ',', 2)); + assert_true(std::vector<StringRef>{"alpha"_sr} == + util::split_str("alpha"_sr, ',', 0)); + assert_true(std::vector<StringRef>{"alpha,bravo,charlie"_sr} == + util::split_str("alpha,bravo,charlie"_sr, ',', 1)); } void test_util_rstrip(void) { BlockAllocator balloc(4096, 4096); - assert_stdstring_equal( - "alpha", util::rstrip(balloc, StringRef::from_lit("alpha")).str()); - assert_stdstring_equal( - "alpha", util::rstrip(balloc, StringRef::from_lit("alpha ")).str()); - assert_stdstring_equal( - "alpha", util::rstrip(balloc, StringRef::from_lit("alpha \t")).str()); - assert_stdstring_equal("", - util::rstrip(balloc, StringRef::from_lit("")).str()); - assert_stdstring_equal( - "", util::rstrip(balloc, StringRef::from_lit("\t\t\t ")).str()); + assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha"_sr)); + assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha "_sr)); + assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha \t"_sr)); + assert_stdsv_equal(""sv, util::rstrip(balloc, ""_sr)); + assert_stdsv_equal(""sv, util::rstrip(balloc, "\t\t\t "_sr)); } } // namespace shrpx diff --git a/src/util_test.h b/src/util_test.h index 8b9608b..39d6167 100644 --- a/src/util_test.h +++ b/src/util_test.h @@ -66,7 +66,6 @@ munit_void_test_decl(test_util_get_uint64); munit_void_test_decl(test_util_parse_config_str_list); munit_void_test_decl(test_util_make_http_hostport); munit_void_test_decl(test_util_make_hostport); -munit_void_test_decl(test_util_strifind); munit_void_test_decl(test_util_random_alpha_digit); munit_void_test_decl(test_util_format_hex); munit_void_test_decl(test_util_is_hex_string); |