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