diff --git a/src/HttpServer.cc b/src/HttpServer.cc index ccad1f26..a3770e07 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -879,11 +879,11 @@ int Http2Handler::verify_npn_result() { SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len); for (int i = 0; i < 2; ++i) { if (next_proto) { + auto proto = StringRef{next_proto, next_proto_len}; if (sessions_->get_config()->verbose) { - std::string proto(next_proto, next_proto + next_proto_len); std::cout << "The negotiated protocol: " << proto << std::endl; } - if (util::check_h2_is_selected(next_proto, next_proto_len)) { + if (util::check_h2_is_selected(proto)) { return 0; } break; diff --git a/src/asio_common.cc b/src/asio_common.cc index c8d148fa..6893e5a1 100644 --- a/src/asio_common.cc +++ b/src/asio_common.cc @@ -187,7 +187,7 @@ bool tls_h2_negotiated(ssl_socket &socket) { return false; } - return util::check_h2_is_selected(next_proto, next_proto_len); + return util::check_h2_is_selected(StringRef{next_proto, next_proto_len}); } } // namespace asio_http2 diff --git a/src/h2load.cc b/src/h2load.cc index 7966e8eb..1791fdc1 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -770,9 +770,10 @@ int Client::connection_made() { #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L if (next_proto) { - if (util::check_h2_is_selected(next_proto, next_proto_len)) { + auto proto = StringRef{next_proto, next_proto_len}; + if (util::check_h2_is_selected(proto)) { session = make_unique(this); - } else if (util::streq_l(NGHTTP2_H1_1, next_proto, next_proto_len)) { + } else if (util::streq_l(NGHTTP2_H1_1, proto)) { session = make_unique(this); } #ifdef HAVE_SPDYLAY @@ -786,7 +787,7 @@ int Client::connection_made() { // Just assign next_proto to selected_proto anyway to show the // negotiation result. - selected_proto.assign(next_proto, next_proto + next_proto_len); + selected_proto = proto.str(); } else { std::cout << "No protocol negotiated. Fallback behaviour may be activated" << std::endl; diff --git a/src/nghttp.cc b/src/nghttp.cc index d219d1da..dad9652f 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -966,13 +966,11 @@ int HttpClient::connection_made() { SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); for (int i = 0; i < 2; ++i) { if (next_proto) { + auto proto = StringRef{next_proto, next_proto_len}; if (config.verbose) { - std::cout << "The negotiated protocol: "; - std::cout.write(reinterpret_cast(next_proto), - next_proto_len); - std::cout << std::endl; + std::cout << "The negotiated protocol: " << proto << std::endl; } - if (!util::check_h2_is_selected(next_proto, next_proto_len)) { + if (!util::check_h2_is_selected(proto)) { next_proto = nullptr; } break; diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 63dbf104..de0d1ecc 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -548,26 +548,26 @@ int ClientHandler::validate_next_proto() { return 0; } + auto proto = StringRef{next_proto, next_proto_len}; + if (LOG_ENABLED(INFO)) { - std::string proto(next_proto, next_proto + next_proto_len); CLOG(INFO, this) << "The negotiated next protocol: " << proto; } - if (!ssl::in_proto_list(get_config()->tls.npn_list, next_proto, - next_proto_len)) { + if (!ssl::in_proto_list(get_config()->tls.npn_list, proto)) { if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "The negotiated protocol is not supported"; + CLOG(INFO, this) << "The negotiated protocol is not supported: " << proto; } return -1; } - if (util::check_h2_is_selected(next_proto, next_proto_len)) { + if (util::check_h2_is_selected(proto)) { on_read_ = &ClientHandler::upstream_http2_connhd_read; auto http2_upstream = make_unique(this); upstream_ = std::move(http2_upstream); - alpn_.assign(next_proto, next_proto + next_proto_len); + alpn_.assign(std::begin(proto), std::end(proto)); // At this point, input buffer is already filled with some bytes. // The read callback is not called until new data come. So consume @@ -580,7 +580,7 @@ int ClientHandler::validate_next_proto() { } #ifdef HAVE_SPDYLAY - auto spdy_version = spdylay_npn_get_version(next_proto, next_proto_len); + auto spdy_version = spdylay_npn_get_version(proto.byte(), proto.size()); if (spdy_version) { upstream_ = make_unique(spdy_version, this); @@ -609,9 +609,9 @@ int ClientHandler::validate_next_proto() { } #endif // HAVE_SPDYLAY - if (next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) { + if (proto == StringRef::from_lit("http/1.1")) { upstream_ = make_unique(this); - alpn_ = "http/1.1"; + alpn_ = proto.str(); // At this point, input buffer is already filled with some bytes. // The read callback is not called until new data come. So consume diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 9ba424f5..2ca55127 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -489,8 +489,8 @@ std::vector parse_log_format(const StringRef &optarg) { if (type == SHRPX_LOGF_NONE) { if (util::istarts_with(var_name, var_namelen, "http_")) { - if (util::streq("host", var_name + str_size("http_"), - var_namelen - str_size("http_"))) { + if (util::streq_l("host", StringRef{var_name + str_size("http_"), + var_namelen - 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. diff --git a/src/shrpx_connection.cc b/src/shrpx_connection.cc index 418afb12..8a5814bc 100644 --- a/src/shrpx_connection.cc +++ b/src/shrpx_connection.cc @@ -486,7 +486,7 @@ int Connection::check_http2_requirement() { } #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L if (next_proto == nullptr || - !util::check_h2_is_selected(next_proto, next_proto_len)) { + !util::check_h2_is_selected(StringRef{next_proto, next_proto_len})) { return 0; } if (!nghttp2::ssl::check_http2_tls_version(tls.ssl)) { diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index bbad8f64..7ad2af65 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -1448,11 +1448,11 @@ int Http2Session::connection_made() { SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len); for (int i = 0; i < 2; ++i) { if (next_proto) { + auto proto = StringRef{next_proto, next_proto_len}; if (LOG_ENABLED(INFO)) { - std::string proto(next_proto, next_proto + next_proto_len); SSLOG(INFO, this) << "Negotiated next protocol: " << proto; } - if (!util::check_h2_is_selected(next_proto, next_proto_len)) { + if (!util::check_h2_is_selected(proto)) { return -1; } break; diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc index 7db5a8d0..9f813413 100644 --- a/src/shrpx_ssl.cc +++ b/src/shrpx_ssl.cc @@ -419,8 +419,8 @@ 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.c_str(), target_proto_id.size(), proto_id, - proto_len)) { + util::streq(StringRef{target_proto_id}, + StringRef{proto_id, proto_len})) { *out = reinterpret_cast(proto_id); *outlen = proto_len; @@ -1252,9 +1252,9 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx, } bool in_proto_list(const std::vector &protos, - const unsigned char *needle, size_t len) { + const StringRef &needle) { for (auto &proto : protos) { - if (util::streq(proto.c_str(), proto.size(), needle, len)) { + if (util::streq(StringRef{proto}, needle)) { return true; } } diff --git a/src/shrpx_ssl.h b/src/shrpx_ssl.h index abe464f5..eced6479 100644 --- a/src/shrpx_ssl.h +++ b/src/shrpx_ssl.h @@ -163,10 +163,10 @@ private: int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx, const char *certfile); -// Returns true if |needle| which has |len| bytes is included in the +// Returns true if |proto| is included in the // protocol list |protos|. bool in_proto_list(const std::vector &protos, - const unsigned char *needle, size_t len); + const StringRef &proto); // Returns true if security requirement for HTTP/2 is fulfilled. bool check_http2_requirement(SSL *ssl); diff --git a/src/util.cc b/src/util.cc index e761c37c..ccb5b8f8 100644 --- a/src/util.cc +++ b/src/util.cc @@ -791,10 +791,9 @@ int64_t to_time64(const timeval &tv) { return tv.tv_sec * 1000000 + tv.tv_usec; } -bool check_h2_is_selected(const unsigned char *proto, size_t len) { - return streq_l(NGHTTP2_PROTO_VERSION_ID, proto, len) || - streq_l(NGHTTP2_H2_16, proto, len) || - streq_l(NGHTTP2_H2_14, proto, len); +bool check_h2_is_selected(const StringRef &proto) { + return streq_l(NGHTTP2_PROTO_VERSION_ID, proto) || + streq_l(NGHTTP2_H2_16, proto) || streq_l(NGHTTP2_H2_14, proto); } namespace { diff --git a/src/util.h b/src/util.h index 49d72dc0..a258bd2c 100644 --- a/src/util.h +++ b/src/util.h @@ -316,16 +316,6 @@ bool strieq_l(const CharT(&a)[N], const StringRef &b) { return strieq(a, a + (N - 1), std::begin(b), std::end(b)); } -template bool streq(const char *a, InputIt b, size_t bn) { - if (!a) { - return false; - } - auto blast = b + bn; - for (; *a && b != blast && *a == *b; ++a, ++b) - ; - return !*a && b == blast; -} - template bool streq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { if (std::distance(first1, last1) != std::distance(first2, last2)) { @@ -334,38 +324,23 @@ bool streq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { return std::equal(first1, last1, first2); } -template -bool streq(InputIt1 a, size_t alen, InputIt2 b, size_t blen) { - if (alen != blen) { - return false; - } - return std::equal(a, a + alen, b); -} - -inline bool streq(const char *a, const char *b) { - if (!a || !b) { - return false; - } - return streq(a, strlen(a), b, strlen(b)); -} - inline bool streq(const StringRef &a, const StringRef &b) { return streq(std::begin(a), std::end(a), std::begin(b), std::end(b)); } template bool streq_l(const CharT(&a)[N], InputIt b, size_t blen) { - return streq(a, N - 1, b, blen); + return streq(a, a + (N - 1), b, b + blen); } template bool streq_l(const CharT(&a)[N], const std::string &b) { - return streq(a, N - 1, std::begin(b), b.size()); + return streq(a, a + (N - 1), std::begin(b), std::end(b)); } template bool streq_l(const CharT(&a)[N], const StringRef &b) { - return streq(a, N - 1, std::begin(b), b.size()); + return streq(a, a + (N - 1), std::begin(b), std::end(b)); } bool strifind(const char *a, const char *b); @@ -563,9 +538,9 @@ bool check_path(const std::string &path); // unit. int64_t to_time64(const timeval &tv); -// Returns true if ALPN ID |proto| of length |len| is supported HTTP/2 -// protocol identifier. -bool check_h2_is_selected(const unsigned char *alpn, size_t len); +// Returns true if ALPN ID |proto| is supported HTTP/2 protocol +// identifier. +bool check_h2_is_selected(const StringRef &proto); // Selects h2 protocol ALPN ID if one of supported h2 versions are // present in |in| of length inlen. Returns true if h2 version is diff --git a/src/util_test.cc b/src/util_test.cc index f5c1c305..19cb0610 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -39,22 +39,24 @@ using namespace nghttp2; namespace shrpx { void test_util_streq(void) { - CU_ASSERT(util::streq("alpha", "alpha", 5)); - CU_ASSERT(util::streq("alpha", "alphabravo", 5)); - CU_ASSERT(!util::streq("alpha", "alphabravo", 6)); - CU_ASSERT(!util::streq("alphabravo", "alpha", 5)); - CU_ASSERT(!util::streq("alpha", "alphA", 5)); - CU_ASSERT(!util::streq("", "a", 1)); - CU_ASSERT(util::streq("", "", 0)); - CU_ASSERT(!util::streq("alpha", "", 0)); + CU_ASSERT( + util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); + CU_ASSERT(!util::streq(StringRef::from_lit("alpha"), + StringRef::from_lit("alphabravo"))); + CU_ASSERT(!util::streq(StringRef::from_lit("alphabravo"), + StringRef::from_lit("alpha"))); + CU_ASSERT( + !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); + CU_ASSERT(!util::streq(StringRef{}, StringRef::from_lit("a"))); + CU_ASSERT(util::streq(StringRef{}, StringRef{})); + CU_ASSERT(!util::streq(StringRef::from_lit("alpha"), StringRef{})); - CU_ASSERT(util::streq("alpha", 5, "alpha", 5)); - CU_ASSERT(!util::streq("alpha", 4, "alpha", 5)); - CU_ASSERT(!util::streq("alpha", 5, "alpha", 4)); - CU_ASSERT(!util::streq("alpha", 5, "alphA", 5)); - char *a = nullptr; - char *b = nullptr; - CU_ASSERT(util::streq(a, 0, b, 0)); + CU_ASSERT( + !util::streq(StringRef::from_lit("alph"), StringRef::from_lit("alpha"))); + CU_ASSERT( + !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alph"))); + CU_ASSERT( + !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); CU_ASSERT(util::streq_l("alpha", "alpha", 5)); CU_ASSERT(util::streq_l("alpha", "alphabravo", 5));