summaryrefslogtreecommitdiff
path: root/src/node_http2.cc
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2017-11-01 11:48:11 -0700
committerJames M Snell <jasnell@gmail.com>2017-11-04 22:32:44 -0700
commit9f3d59eabb6564ad337a762d61ac767f9130e8a5 (patch)
treea0fdb43c530be18d6ed5dded16378c6f30d91da6 /src/node_http2.cc
parent1f045f491a6a8d6ac193474f3856e2bdbd6847be (diff)
downloadandroid-node-v8-9f3d59eabb6564ad337a762d61ac767f9130e8a5.tar.gz
android-node-v8-9f3d59eabb6564ad337a762d61ac767f9130e8a5.tar.bz2
android-node-v8-9f3d59eabb6564ad337a762d61ac767f9130e8a5.zip
http2: refactor multiple internals
* eliminate pooling of Nghttp2Stream instances. After testing, the pooling is not having any tangible benefit and makes things more complicated. Simplify. Simplify. * refactor inbound headers * Enforce MAX_HEADERS_LIST setting and limit the number of header pairs accepted from the peer. Use the ENHANCE_YOUR_CALM error code when receiving either too many headers or too many octets. Use a vector to store the headers instead of a queue PR-URL: https://github.com/nodejs/node/pull/16676 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'src/node_http2.cc')
-rw-r--r--src/node_http2.cc31
1 files changed, 21 insertions, 10 deletions
diff --git a/src/node_http2.cc b/src/node_http2.cc
index 8beaee0548..f9025d1fd3 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -5,6 +5,7 @@
#include "node_http2_state.h"
#include <queue>
+#include <algorithm>
namespace node {
@@ -20,8 +21,6 @@ using v8::Undefined;
namespace http2 {
-Freelist<Nghttp2Stream, FREELIST_MAX> stream_free_list;
-
Nghttp2Session::Callbacks Nghttp2Session::callback_struct_saved[2] = {
Callbacks(false),
Callbacks(true)};
@@ -67,6 +66,10 @@ Http2Options::Http2Options(Environment* env) {
buffer.GetValue(IDX_OPTIONS_PADDING_STRATEGY));
SetPaddingStrategy(strategy);
}
+
+ if (flags & (1 << IDX_OPTIONS_MAX_HEADER_LIST_PAIRS)) {
+ SetMaxHeaderPairs(buffer[IDX_OPTIONS_MAX_HEADER_LIST_PAIRS]);
+ }
}
Http2Settings::Http2Settings(Environment* env) : env_(env) {
@@ -173,11 +176,14 @@ inline void Http2Settings::RefreshDefaults(Environment* env) {
DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE;
buffer[IDX_SETTINGS_MAX_FRAME_SIZE] =
DEFAULT_SETTINGS_MAX_FRAME_SIZE;
+ buffer[IDX_SETTINGS_MAX_HEADER_LIST_SIZE] =
+ DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE;
buffer[IDX_SETTINGS_COUNT] =
(1 << IDX_SETTINGS_HEADER_TABLE_SIZE) |
(1 << IDX_SETTINGS_ENABLE_PUSH) |
(1 << IDX_SETTINGS_INITIAL_WINDOW_SIZE) |
- (1 << IDX_SETTINGS_MAX_FRAME_SIZE);
+ (1 << IDX_SETTINGS_MAX_FRAME_SIZE) |
+ (1 << IDX_SETTINGS_MAX_HEADER_LIST_SIZE);
}
@@ -192,7 +198,10 @@ Http2Session::Http2Session(Environment* env,
padding_strategy_ = opts.GetPaddingStrategy();
- Init(type, *opts);
+ int32_t maxHeaderPairs = opts.GetMaxHeaderPairs();
+ maxHeaderPairs = type == NGHTTP2_SESSION_SERVER ?
+ std::max(maxHeaderPairs, 4) : std::max(maxHeaderPairs, 1);
+ Init(type, *opts, nullptr, maxHeaderPairs);
// For every node::Http2Session instance, there is a uv_prepare_t handle
// whose callback is triggered on every tick of the event loop. When
@@ -911,7 +920,8 @@ void Http2Session::OnTrailers(Nghttp2Stream* stream,
void Http2Session::OnHeaders(
Nghttp2Stream* stream,
- std::queue<nghttp2_header>* headers,
+ nghttp2_header* headers,
+ size_t count,
nghttp2_headers_category cat,
uint8_t flags) {
Local<Context> context = env()->context();
@@ -936,10 +946,11 @@ void Http2Session::OnHeaders(
// like {name1: value1, name2: value2, name3: [value3, value4]}. We do it
// this way for performance reasons (it's faster to generate and pass an
// array than it is to generate and pass the object).
- do {
+ size_t n = 0;
+ while (count > 0) {
size_t j = 0;
- while (!headers->empty() && j < arraysize(argv) / 2) {
- nghttp2_header item = headers->front();
+ while (count > 0 && j < arraysize(argv) / 2) {
+ nghttp2_header item = headers[n++];
// The header name and value are passed as external one-byte strings
name_str =
ExternalHeader::New<true>(env(), item.name).ToLocalChecked();
@@ -947,7 +958,7 @@ void Http2Session::OnHeaders(
ExternalHeader::New<false>(env(), item.value).ToLocalChecked();
argv[j * 2] = name_str;
argv[j * 2 + 1] = value_str;
- headers->pop();
+ count--;
j++;
}
// For performance, we pass name and value pairs to array.protototype.push
@@ -956,7 +967,7 @@ void Http2Session::OnHeaders(
if (j > 0) {
fn->Call(env()->context(), holder, j * 2, argv).ToLocalChecked();
}
- } while (!headers->empty());
+ }
Local<Value> args[4] = {
Integer::New(isolate, stream->id()),