deps: update nghttp2 to 1.34.0

Key new feature: RFC 8441 `:protocol` support

PR-URL: https://github.com/nodejs/node/pull/23284
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
James M Snell 2018-10-05 13:09:10 -07:00
parent 314c1fa583
commit 8290015d0a
No known key found for this signature in database
GPG Key ID: 7341B15C070877AC
10 changed files with 96 additions and 26 deletions

View File

@ -680,7 +680,12 @@ typedef enum {
/** /**
* SETTINGS_MAX_HEADER_LIST_SIZE * SETTINGS_MAX_HEADER_LIST_SIZE
*/ */
NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06 NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06,
/**
* SETTINGS_ENABLE_CONNECT_PROTOCOL
* (`RFC 8441 <https://tools.ietf.org/html/rfc8441>`_)
*/
NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08
} nghttp2_settings_id; } nghttp2_settings_id;
/* Note: If we add SETTINGS, update the capacity of /* Note: If we add SETTINGS, update the capacity of
NGHTTP2_INBOUND_NUM_IV as well */ NGHTTP2_INBOUND_NUM_IV as well */

View File

@ -29,7 +29,7 @@
* @macro * @macro
* Version number of the nghttp2 library release * Version number of the nghttp2 library release
*/ */
#define NGHTTP2_VERSION "1.33.0" #define NGHTTP2_VERSION "1.34.0"
/** /**
* @macro * @macro
@ -37,6 +37,6 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits * release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/ */
#define NGHTTP2_VERSION_NUM 0x012100 #define NGHTTP2_VERSION_NUM 0x012200
#endif /* NGHTTP2VER_H */ #endif /* NGHTTP2VER_H */

View File

@ -1050,6 +1050,11 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
break; break;
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
break; break;
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
if (iv[i].value != 0 && iv[i].value != 1) {
return 0;
}
break;
} }
} }
return 1; return 1;

View File

@ -45,7 +45,7 @@
/* 3rd parameter is nghttp2_token value for header field name. We use /* 3rd parameter is nghttp2_token value for header field name. We use
first enum value if same header names are repeated (e.g., first enum value if same header names are repeated (e.g.,
:status). */ :status). */
static nghttp2_hd_static_entry static_table[] = { static const nghttp2_hd_static_entry static_table[] = {
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u), MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u), MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u), MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
@ -271,6 +271,15 @@ static int32_t lookup_token(const uint8_t *name, size_t namelen) {
break; break;
} }
break; break;
case 9:
switch (name[8]) {
case 'l':
if (memeq(":protoco", name, 8)) {
return NGHTTP2_TOKEN__PROTOCOL;
}
break;
}
break;
case 10: case 10:
switch (name[9]) { switch (name[9]) {
case 'e': case 'e':
@ -1159,7 +1168,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
int name_only) { int name_only) {
search_result res = {token, 0}; search_result res = {token, 0};
int i; int i;
nghttp2_hd_static_entry *ent; const nghttp2_hd_static_entry *ent;
if (name_only) { if (name_only) {
return res; return res;
@ -1184,7 +1193,7 @@ static search_result search_hd_table(nghttp2_hd_context *context,
int indexing_mode, nghttp2_hd_map *map, int indexing_mode, nghttp2_hd_map *map,
uint32_t hash) { uint32_t hash) {
search_result res = {-1, 0}; search_result res = {-1, 0};
nghttp2_hd_entry *ent; const nghttp2_hd_entry *ent;
int exact_match; int exact_match;
int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING; int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
@ -1289,8 +1298,9 @@ nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH) return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
->nv; ->nv;
} else { } else {
nghttp2_hd_static_entry *ent = &static_table[idx]; const nghttp2_hd_static_entry *ent = &static_table[idx];
nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token, nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
(nghttp2_rcbuf *)&ent->value, ent->token,
NGHTTP2_NV_FLAG_NONE}; NGHTTP2_NV_FLAG_NONE};
return nv; return nv;
} }

View File

@ -111,6 +111,7 @@ typedef enum {
NGHTTP2_TOKEN_KEEP_ALIVE, NGHTTP2_TOKEN_KEEP_ALIVE,
NGHTTP2_TOKEN_PROXY_CONNECTION, NGHTTP2_TOKEN_PROXY_CONNECTION,
NGHTTP2_TOKEN_UPGRADE, NGHTTP2_TOKEN_UPGRADE,
NGHTTP2_TOKEN__PROTOCOL,
} nghttp2_token; } nghttp2_token;
struct nghttp2_hd_entry; struct nghttp2_hd_entry;

View File

@ -340,7 +340,7 @@ const char *nghttp2_strerror(int error_code) {
} }
/* Generated by gennmchartbl.py */ /* Generated by gennmchartbl.py */
static int VALID_HD_NAME_CHARS[] = { static const int VALID_HD_NAME_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */, 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
@ -428,7 +428,7 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
} }
/* Generated by genvchartbl.py */ /* Generated by genvchartbl.py */
static int VALID_HD_VALUE_CHARS[] = { static const int VALID_HD_VALUE_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */, 0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,

View File

@ -113,7 +113,7 @@ static int check_path(nghttp2_stream *stream) {
} }
static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv, static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
int trailer) { int trailer, int connect_protocol) {
if (nv->name->base[0] == ':') { if (nv->name->base[0] == ':') {
if (trailer || if (trailer ||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
@ -146,10 +146,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
if (stream->http_flags &
(NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) {
return NGHTTP2_ERR_HTTP_HEADER;
}
} }
break; break;
case 'S': case 'S':
@ -162,9 +158,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
} }
break; break;
case NGHTTP2_TOKEN__PATH: case NGHTTP2_TOKEN__PATH:
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
return NGHTTP2_ERR_HTTP_HEADER;
}
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
@ -175,9 +168,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
} }
break; break;
case NGHTTP2_TOKEN__SCHEME: case NGHTTP2_TOKEN__SCHEME:
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
return NGHTTP2_ERR_HTTP_HEADER;
}
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
@ -186,6 +176,15 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP; stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
} }
break; break;
case NGHTTP2_TOKEN__PROTOCOL:
if (!connect_protocol) {
return NGHTTP2_ERR_HTTP_HEADER;
}
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PROTOCOL)) {
return NGHTTP2_ERR_HTTP_HEADER;
}
break;
case NGHTTP2_TOKEN_HOST: case NGHTTP2_TOKEN_HOST:
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
@ -265,7 +264,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
return NGHTTP2_ERR_REMOVE_HTTP_HEADER; return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
} }
if (stream->status_code / 100 == 1 || if (stream->status_code / 100 == 1 ||
(stream->status_code == 200 && (stream->status_code / 100 == 2 &&
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) { (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
@ -458,7 +457,9 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
} }
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) { if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
return http_request_on_header(stream, nv, trailer); return http_request_on_header(stream, nv, trailer,
session->server &&
session->pending_enable_connect_protocol);
} }
return http_response_on_header(stream, nv, trailer); return http_response_on_header(stream, nv, trailer);
@ -466,8 +467,11 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
int nghttp2_http_on_request_headers(nghttp2_stream *stream, int nghttp2_http_on_request_headers(nghttp2_stream *stream,
nghttp2_frame *frame) { nghttp2_frame *frame) {
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) { if (!(stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) &&
if ((stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) { (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT)) {
if ((stream->http_flags &
(NGHTTP2_HTTP_FLAG__SCHEME | NGHTTP2_HTTP_FLAG__PATH)) ||
(stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) {
return -1; return -1;
} }
stream->content_length = -1; stream->content_length = -1;
@ -478,6 +482,11 @@ int nghttp2_http_on_request_headers(nghttp2_stream *stream,
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) { (NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
return -1; return -1;
} }
if ((stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) &&
((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) == 0 ||
(stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0)) {
return -1;
}
if (!check_path(stream)) { if (!check_path(stream)) {
return -1; return -1;
} }

View File

@ -4361,6 +4361,9 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
session->local_settings.max_header_list_size = iv[i].value; session->local_settings.max_header_list_size = iv[i].value;
break; break;
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
session->local_settings.enable_connect_protocol = iv[i].value;
break;
} }
} }
@ -4499,6 +4502,26 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
session->remote_settings.max_header_list_size = entry->value; session->remote_settings.max_header_list_size = entry->value;
break;
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
if (entry->value != 0 && entry->value != 1) {
return session_handle_invalid_connection(
session, frame, NGHTTP2_ERR_PROTO,
"SETTINGS: invalid SETTINGS_ENABLE_CONNECT_PROTOCOL");
}
if (!session->server &&
session->remote_settings.enable_connect_protocol &&
entry->value == 0) {
return session_handle_invalid_connection(
session, frame, NGHTTP2_ERR_PROTO,
"SETTINGS: server attempted to disable "
"SETTINGS_ENABLE_CONNECT_PROTOCOL");
}
session->remote_settings.enable_connect_protocol = entry->value;
break; break;
} }
} }
@ -5250,6 +5273,7 @@ static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
break; break;
default: default:
DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id); DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id);
@ -7052,6 +7076,13 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
} }
} }
for (i = niv; i > 0; --i) {
if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL) {
session->pending_enable_connect_protocol = (uint8_t)iv[i - 1].value;
break;
}
}
return 0; return 0;
} }
@ -7360,6 +7391,8 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
return session->remote_settings.max_frame_size; return session->remote_settings.max_frame_size;
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
return session->remote_settings.max_header_list_size; return session->remote_settings.max_header_list_size;
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
return session->remote_settings.enable_connect_protocol;
} }
assert(0); assert(0);
@ -7381,6 +7414,8 @@ uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
return session->local_settings.max_frame_size; return session->local_settings.max_frame_size;
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
return session->local_settings.max_header_list_size; return session->local_settings.max_header_list_size;
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
return session->local_settings.enable_connect_protocol;
} }
assert(0); assert(0);

View File

@ -164,6 +164,7 @@ typedef struct {
uint32_t initial_window_size; uint32_t initial_window_size;
uint32_t max_frame_size; uint32_t max_frame_size;
uint32_t max_header_list_size; uint32_t max_header_list_size;
uint32_t enable_connect_protocol;
} nghttp2_settings_storage; } nghttp2_settings_storage;
typedef enum { typedef enum {
@ -321,6 +322,9 @@ struct nghttp2_session {
/* Unacked local ENABLE_PUSH value. We use this to refuse /* Unacked local ENABLE_PUSH value. We use this to refuse
PUSH_PROMISE before SETTINGS ACK is received. */ PUSH_PROMISE before SETTINGS ACK is received. */
uint8_t pending_enable_push; uint8_t pending_enable_push;
/* Unacked local ENABLE_CONNECT_PROTOCOL value. We use this to
accept :protocol header field before SETTINGS_ACK is received. */
uint8_t pending_enable_connect_protocol;
/* Nonzero if the session is server side. */ /* Nonzero if the session is server side. */
uint8_t server; uint8_t server;
/* Flags indicating GOAWAY is sent and/or received. The flags are /* Flags indicating GOAWAY is sent and/or received. The flags are

View File

@ -130,7 +130,8 @@ typedef enum {
/* "http" or "https" scheme */ /* "http" or "https" scheme */
NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13, NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
/* set if final response is expected */ /* set if final response is expected */
NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14 NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14,
NGHTTP2_HTTP_FLAG__PROTOCOL = 1 << 15,
} nghttp2_http_flag; } nghttp2_http_flag;
struct nghttp2_stream { struct nghttp2_stream {