src: Refactor code around ALPN setup
This commit is contained in:
parent
8e30adbca0
commit
d98e9a63d0
|
@ -593,11 +593,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) {
|
||||
std::string proto(next_proto, 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(proto == NGHTTP2_PROTO_VERSION_ID) {
|
||||
if(util::check_h2_is_selected(next_proto, next_proto_len)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
@ -1555,7 +1555,7 @@ int HttpServer::run()
|
|||
{
|
||||
SSL_CTX *ssl_ctx = nullptr;
|
||||
std::pair<unsigned char*, size_t> next_proto;
|
||||
unsigned char proto_list[255];
|
||||
|
||||
if(!config_->no_tls) {
|
||||
ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if(!ssl_ctx) {
|
||||
|
@ -1646,11 +1646,13 @@ int HttpServer::run()
|
|||
verify_callback);
|
||||
}
|
||||
|
||||
proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
memcpy(&proto_list[1], NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
next_proto.first = proto_list;
|
||||
next_proto.second = proto_list[0] + 1;
|
||||
auto proto_list = util::get_default_alpn();
|
||||
|
||||
std::pair<unsigned char*, size_t> next_proto(proto_list.data(),
|
||||
proto_list.size());
|
||||
|
||||
next_proto.first = proto_list.data();
|
||||
next_proto.second = proto_list.size();
|
||||
|
||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
|
|
@ -80,16 +80,11 @@ http2_impl::http2_impl()
|
|||
{}
|
||||
|
||||
namespace {
|
||||
std::array<unsigned char, NGHTTP2_PROTO_VERSION_ID_LEN + 1>&
|
||||
std::vector<unsigned char>&
|
||||
get_alpn_token()
|
||||
{
|
||||
static std::array<unsigned char, NGHTTP2_PROTO_VERSION_ID_LEN + 1> token;
|
||||
|
||||
token[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
std::copy(NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID + NGHTTP2_PROTO_VERSION_ID_LEN,
|
||||
std::begin(token) + 1);
|
||||
return token;
|
||||
static auto alpn_token = util::get_default_alpn();
|
||||
return alpn_token;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -469,8 +469,7 @@ void eventcb(bufferevent *bev, short events, void *ptr)
|
|||
return;
|
||||
}
|
||||
|
||||
if(next_proto_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto, next_proto_len) == 0) {
|
||||
if(util::check_h2_is_selected(next_proto, next_proto_len)) {
|
||||
client->session = util::make_unique<Http2Session>(client);
|
||||
} else {
|
||||
#ifdef HAVE_SPDYLAY
|
||||
|
|
|
@ -1632,9 +1632,7 @@ void eventcb(bufferevent *bev, short events, void *ptr)
|
|||
next_proto_len);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
if(NGHTTP2_PROTO_VERSION_ID_LEN != next_proto_len ||
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN) != 0) {
|
||||
if(!util::check_h2_is_selected(next_proto, next_proto_len)) {
|
||||
next_proto = nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -1739,11 +1737,9 @@ int communicate(const std::string& scheme, const std::string& host,
|
|||
client_select_next_proto_cb, nullptr);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
unsigned char proto_list[255];
|
||||
proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
memcpy(&proto_list[1], NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list, proto_list[0] + 1);
|
||||
auto proto_list = util::get_default_alpn();
|
||||
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list.data(), proto_list.size());
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
}
|
||||
{
|
||||
|
|
|
@ -301,9 +301,7 @@ int ClientHandler::validate_next_proto()
|
|||
next_proto, next_proto_len)) {
|
||||
break;
|
||||
}
|
||||
if(next_proto_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
|
||||
if(util::check_h2_is_selected(next_proto, next_proto_len)) {
|
||||
|
||||
set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb,
|
||||
upstream_eventcb);
|
||||
|
|
|
@ -1355,9 +1355,7 @@ int Http2Session::on_connect()
|
|||
std::string proto(next_proto, next_proto+next_proto_len);
|
||||
SSLOG(INFO, this) << "Negotiated next protocol: " << proto;
|
||||
}
|
||||
if(next_proto_len != NGHTTP2_PROTO_VERSION_ID_LEN ||
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, next_proto,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN) != 0) {
|
||||
if(!util::check_h2_is_selected(next_proto, next_proto_len)) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -86,23 +86,31 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
|
||||
std::vector<unsigned char> set_alpn_prefs(const std::vector<char*>& protos)
|
||||
{
|
||||
unsigned char out[256];
|
||||
auto ptr = out;
|
||||
auto end = ptr + sizeof(out);
|
||||
size_t len = 0;
|
||||
|
||||
for(auto proto : protos) {
|
||||
auto plen = strlen(proto);
|
||||
auto n = strlen(proto);
|
||||
|
||||
if(ptr + plen + 1 > end) {
|
||||
LOG(FATAL) << "Too long alpn list";
|
||||
if(n > 255) {
|
||||
LOG(FATAL) << "Too long ALPN identifier: " << n;
|
||||
DIE();
|
||||
}
|
||||
|
||||
*ptr = plen;
|
||||
memcpy(ptr + 1, proto, plen);
|
||||
ptr += plen + 1;
|
||||
len += 1 + n;
|
||||
}
|
||||
return std::vector<unsigned char>(out, ptr);
|
||||
|
||||
auto out = std::vector<unsigned char>(len);
|
||||
auto ptr = out.data();
|
||||
|
||||
for(auto proto : protos) {
|
||||
auto proto_len = strlen(proto);
|
||||
|
||||
*ptr++ = proto_len;
|
||||
memcpy(ptr, proto, proto_len);
|
||||
ptr += proto_len;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -445,14 +453,9 @@ SSL_CTX* create_ssl_client_context()
|
|||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
// ALPN advertisement; We only advertise HTTP/2
|
||||
unsigned char proto_list[256];
|
||||
auto proto_list = util::get_default_alpn();
|
||||
|
||||
proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
memcpy(proto_list + 1, NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
auto proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list, proto_list_len);
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list.data(), proto_list.size());
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
return ssl_ctx;
|
||||
|
|
19
src/util.cc
19
src/util.cc
|
@ -36,6 +36,8 @@
|
|||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "timegm.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
@ -686,6 +688,23 @@ 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(NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN,
|
||||
proto, len);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> get_default_alpn()
|
||||
{
|
||||
auto res = std::vector<unsigned char>(1 + NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
auto p = res.data();
|
||||
|
||||
*p++ = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
memcpy(p, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <getopt.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
@ -470,6 +471,14 @@ 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 default ALPN protocol list, which only contains supported
|
||||
// HTTP/2 protocol identifier.
|
||||
std::vector<unsigned char> get_default_alpn();
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
Loading…
Reference in New Issue