nghttp, nghttpx, nghttpd, h2load: Support h2-16 in NPN/ALPN
The nghttp2 library itself is still h2-14. To experiment with the implementations to require h2-16 to test new features (e.g., prioritization), nghttp, nghttpx, nghttpd and h2load now support h2-16 as well as h2-14. Cleartext HTTP Upgrade is still limited to h2-14 however.
This commit is contained in:
parent
5fa9dd7cd5
commit
d695d2ccc0
|
@ -1403,8 +1403,7 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nghttp2_select_next_protocol(const_cast<unsigned char **>(out), outlen,
|
if (!util::select_h2(out, outlen, in, inlen)) {
|
||||||
in, inlen) <= 0) {
|
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
}
|
}
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
|
|
@ -565,11 +565,12 @@ namespace {
|
||||||
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
|
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
|
||||||
unsigned char *outlen, const unsigned char *in,
|
unsigned char *outlen, const unsigned char *in,
|
||||||
unsigned int inlen, void *arg) {
|
unsigned int inlen, void *arg) {
|
||||||
if (nghttp2_select_next_protocol(out, outlen, in, inlen) > 0) {
|
if (util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
|
||||||
|
inlen)) {
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SPDYLAY
|
#ifdef HAVE_SPDYLAY
|
||||||
else if (spdylay_select_next_protocol(out, outlen, in, inlen) > 0) {
|
if (spdylay_select_next_protocol(out, outlen, in, inlen) > 0) {
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1701,7 +1701,8 @@ int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
|
if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
|
||||||
|
inlen)) {
|
||||||
print_protocol_nego_error();
|
print_protocol_nego_error();
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ int main(int argc, char *argv[]) {
|
||||||
shrpx::test_util_quote_string) ||
|
shrpx::test_util_quote_string) ||
|
||||||
!CU_add_test(pSuite, "util_utox", shrpx::test_util_utox) ||
|
!CU_add_test(pSuite, "util_utox", shrpx::test_util_utox) ||
|
||||||
!CU_add_test(pSuite, "util_http_date", shrpx::test_util_http_date) ||
|
!CU_add_test(pSuite, "util_http_date", shrpx::test_util_http_date) ||
|
||||||
|
!CU_add_test(pSuite, "util_select_h2", shrpx::test_util_select_h2) ||
|
||||||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)) {
|
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
|
|
@ -636,11 +636,11 @@ bool conf_exists(const char *path) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const char *DEFAULT_NPN_LIST = NGHTTP2_PROTO_VERSION_ID ","
|
const char *DEFAULT_NPN_LIST = "h2-16," NGHTTP2_PROTO_VERSION_ID ","
|
||||||
#ifdef HAVE_SPDYLAY
|
#ifdef HAVE_SPDYLAY
|
||||||
"spdy/3.1,"
|
"spdy/3.1,"
|
||||||
#endif // HAVE_SPDYLAY
|
#endif // HAVE_SPDYLAY
|
||||||
"http/1.1";
|
"http/1.1";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -280,7 +280,9 @@ int ClientHandler::validate_next_proto() {
|
||||||
next_proto_len)) {
|
next_proto_len)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (util::check_h2_is_selected(next_proto, next_proto_len)) {
|
if (util::check_h2_is_selected(next_proto, next_proto_len) ||
|
||||||
|
(next_proto_len == sizeof("h2-16") - 1 &&
|
||||||
|
memcmp("h2-16", next_proto, next_proto_len) == 0)) {
|
||||||
|
|
||||||
set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb,
|
set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb,
|
||||||
upstream_eventcb);
|
upstream_eventcb);
|
||||||
|
|
|
@ -364,10 +364,11 @@ namespace {
|
||||||
int select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
|
int select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
|
||||||
const unsigned char *in, unsigned int inlen,
|
const unsigned char *in, unsigned int inlen,
|
||||||
void *arg) {
|
void *arg) {
|
||||||
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
|
if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
|
||||||
*out = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
|
inlen)) {
|
||||||
*outlen = NGHTTP2_PROTO_VERSION_ID_LEN;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
46
src/util.cc
46
src/util.cc
|
@ -42,6 +42,9 @@
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
|
const unsigned char NGHTTP2_H2_PROTO_ALIAS[] = "h2-16";
|
||||||
|
size_t NGHTTP2_H2_PROTO_ALIAS_LEN = sizeof(NGHTTP2_H2_PROTO_ALIAS) - 1;
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
const char DEFAULT_STRIP_CHARSET[] = "\r\n\t ";
|
const char DEFAULT_STRIP_CHARSET[] = "\r\n\t ";
|
||||||
|
@ -772,13 +775,52 @@ int64_t to_time64(const timeval &tv) {
|
||||||
|
|
||||||
bool check_h2_is_selected(const unsigned char *proto, size_t len) {
|
bool check_h2_is_selected(const unsigned char *proto, size_t len) {
|
||||||
return streq(NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN, proto,
|
return streq(NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN, proto,
|
||||||
len);
|
len) ||
|
||||||
|
streq(NGHTTP2_H2_PROTO_ALIAS, NGHTTP2_H2_PROTO_ALIAS_LEN, proto, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool select_h2(const unsigned char **out, unsigned char *outlen,
|
||||||
|
const unsigned char *in, unsigned int inlen,
|
||||||
|
const unsigned char *target, unsigned int tlen) {
|
||||||
|
for (auto p = in, end = in + inlen; p < end;) {
|
||||||
|
auto len = *p++;
|
||||||
|
if (p + len > end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len != tlen) {
|
||||||
|
p += len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (memcmp(target, p, tlen) == 0) {
|
||||||
|
*out = target;
|
||||||
|
*outlen = tlen;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool select_h2(const unsigned char **out, unsigned char *outlen,
|
||||||
|
const unsigned char *in, unsigned int inlen) {
|
||||||
|
return select_h2(out, outlen, in, inlen, NGHTTP2_H2_PROTO_ALIAS,
|
||||||
|
NGHTTP2_H2_PROTO_ALIAS_LEN) ||
|
||||||
|
select_h2(
|
||||||
|
out, outlen, in, inlen,
|
||||||
|
reinterpret_cast<const unsigned char *>(NGHTTP2_PROTO_VERSION_ID),
|
||||||
|
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> get_default_alpn() {
|
std::vector<unsigned char> get_default_alpn() {
|
||||||
auto res = std::vector<unsigned char>(1 + NGHTTP2_PROTO_VERSION_ID_LEN);
|
auto res = std::vector<unsigned char>(1 + NGHTTP2_PROTO_VERSION_ID_LEN + 1 +
|
||||||
|
NGHTTP2_H2_PROTO_ALIAS_LEN);
|
||||||
auto p = res.data();
|
auto p = res.data();
|
||||||
|
|
||||||
|
*p++ = NGHTTP2_H2_PROTO_ALIAS_LEN;
|
||||||
|
memcpy(p, NGHTTP2_H2_PROTO_ALIAS, NGHTTP2_H2_PROTO_ALIAS_LEN);
|
||||||
|
p += NGHTTP2_H2_PROTO_ALIAS_LEN;
|
||||||
*p++ = NGHTTP2_PROTO_VERSION_ID_LEN;
|
*p++ = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||||
memcpy(p, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN);
|
memcpy(p, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||||
|
|
||||||
|
|
12
src/util.h
12
src/util.h
|
@ -43,6 +43,12 @@
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
|
// The additional HTTP/2 protocol ALPN ID we also supports for our
|
||||||
|
// applications. This will be removed once HTTP/2 specification is
|
||||||
|
// finalized.
|
||||||
|
extern const unsigned char NGHTTP2_H2_PROTO_ALIAS[];
|
||||||
|
extern size_t NGHTTP2_H2_PROTO_ALIAS_LEN;
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) {
|
template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) {
|
||||||
|
@ -424,6 +430,12 @@ int64_t to_time64(const timeval &tv);
|
||||||
// protocol identifier.
|
// protocol identifier.
|
||||||
bool check_h2_is_selected(const unsigned char *alpn, size_t len);
|
bool check_h2_is_selected(const unsigned char *alpn, size_t len);
|
||||||
|
|
||||||
|
// Selects h2 protocol ALPN ID if one of supported h2 versions are
|
||||||
|
// present in |in| of length inlen. Returns true if h2 version is
|
||||||
|
// selected.
|
||||||
|
bool select_h2(const unsigned char **out, unsigned char *outlen,
|
||||||
|
const unsigned char *in, unsigned int inlen);
|
||||||
|
|
||||||
// Returns default ALPN protocol list, which only contains supported
|
// Returns default ALPN protocol list, which only contains supported
|
||||||
// HTTP/2 protocol identifier.
|
// HTTP/2 protocol identifier.
|
||||||
std::vector<unsigned char> get_default_alpn();
|
std::vector<unsigned char> get_default_alpn();
|
||||||
|
|
|
@ -24,10 +24,13 @@
|
||||||
*/
|
*/
|
||||||
#include "util_test.h"
|
#include "util_test.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <CUnit/CUnit.h>
|
#include <CUnit/CUnit.h>
|
||||||
|
|
||||||
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
@ -116,4 +119,50 @@ void test_util_http_date(void) {
|
||||||
CU_ASSERT("Wed, 29 Feb 2012 09:15:16 GMT" == util::http_date(1330506916));
|
CU_ASSERT("Wed, 29 Feb 2012 09:15:16 GMT" == util::http_date(1330506916));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_util_select_h2(void) {
|
||||||
|
const unsigned char *out = NULL;
|
||||||
|
unsigned char outlen = 0;
|
||||||
|
|
||||||
|
// Check single entry and select it.
|
||||||
|
const unsigned char t1[] = "\x5h2-14";
|
||||||
|
CU_ASSERT(util::select_h2(&out, &outlen, t1, sizeof(t1) - 1));
|
||||||
|
CU_ASSERT(
|
||||||
|
memcmp(NGHTTP2_PROTO_VERSION_ID, out, NGHTTP2_PROTO_VERSION_ID_LEN) == 0);
|
||||||
|
CU_ASSERT(NGHTTP2_PROTO_VERSION_ID_LEN == outlen);
|
||||||
|
|
||||||
|
out = NULL;
|
||||||
|
outlen = 0;
|
||||||
|
|
||||||
|
// Check the case where id is correct but length is invalid and too
|
||||||
|
// long.
|
||||||
|
const unsigned char t2[] = "\x6h2-14";
|
||||||
|
CU_ASSERT(!util::select_h2(&out, &outlen, t2, sizeof(t2) - 1));
|
||||||
|
|
||||||
|
// Check the case where h2-14 is located after bogus ID.
|
||||||
|
const unsigned char t3[] = "\x2h3\x5h2-14";
|
||||||
|
CU_ASSERT(util::select_h2(&out, &outlen, t3, sizeof(t3) - 1));
|
||||||
|
CU_ASSERT(
|
||||||
|
memcmp(NGHTTP2_PROTO_VERSION_ID, out, NGHTTP2_PROTO_VERSION_ID_LEN) == 0);
|
||||||
|
CU_ASSERT(NGHTTP2_PROTO_VERSION_ID_LEN == outlen);
|
||||||
|
|
||||||
|
out = NULL;
|
||||||
|
outlen = 0;
|
||||||
|
|
||||||
|
// Check the case that last entry's length is invalid and too long.
|
||||||
|
const unsigned char t4[] = "\x2h3\x6h2-14";
|
||||||
|
CU_ASSERT(!util::select_h2(&out, &outlen, t4, sizeof(t4) - 1));
|
||||||
|
|
||||||
|
// Check the case that all entries are not supported.
|
||||||
|
const unsigned char t5[] = "\x2h3\x2h4";
|
||||||
|
CU_ASSERT(!util::select_h2(&out, &outlen, t5, sizeof(t5) - 1));
|
||||||
|
|
||||||
|
// Check the case where 2 values are eligible, but last one is
|
||||||
|
// picked up because it has precedence over the other.
|
||||||
|
const unsigned char t6[] = "\x5h2-14\x5h2-16";
|
||||||
|
CU_ASSERT(util::select_h2(&out, &outlen, t6, sizeof(t6) - 1));
|
||||||
|
CU_ASSERT(memcmp(NGHTTP2_H2_PROTO_ALIAS, out, NGHTTP2_H2_PROTO_ALIAS_LEN) ==
|
||||||
|
0);
|
||||||
|
CU_ASSERT(NGHTTP2_H2_PROTO_ALIAS_LEN == outlen);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -35,6 +35,7 @@ void test_util_percent_encode_token(void);
|
||||||
void test_util_quote_string(void);
|
void test_util_quote_string(void);
|
||||||
void test_util_utox(void);
|
void test_util_utox(void);
|
||||||
void test_util_http_date(void);
|
void test_util_http_date(void);
|
||||||
|
void test_util_select_h2(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue