55#include " node_http2_state.h"
66
77#include < queue>
8+ #include < algorithm>
89
910namespace node {
1011
@@ -20,8 +21,6 @@ using v8::Undefined;
2021
2122namespace http2 {
2223
23- Freelist<Nghttp2Stream, FREELIST_MAX> stream_free_list;
24-
2524Nghttp2Session::Callbacks Nghttp2Session::callback_struct_saved[2 ] = {
2625 Callbacks (false ),
2726 Callbacks (true )};
@@ -67,6 +66,10 @@ Http2Options::Http2Options(Environment* env) {
6766 buffer.GetValue (IDX_OPTIONS_PADDING_STRATEGY));
6867 SetPaddingStrategy (strategy);
6968 }
69+
70+ if (flags & (1 << IDX_OPTIONS_MAX_HEADER_LIST_PAIRS)) {
71+ SetMaxHeaderPairs (buffer[IDX_OPTIONS_MAX_HEADER_LIST_PAIRS]);
72+ }
7073}
7174
7275Http2Settings::Http2Settings (Environment* env) : env_(env) {
@@ -173,11 +176,14 @@ inline void Http2Settings::RefreshDefaults(Environment* env) {
173176 DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE;
174177 buffer[IDX_SETTINGS_MAX_FRAME_SIZE] =
175178 DEFAULT_SETTINGS_MAX_FRAME_SIZE;
179+ buffer[IDX_SETTINGS_MAX_HEADER_LIST_SIZE] =
180+ DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE;
176181 buffer[IDX_SETTINGS_COUNT] =
177182 (1 << IDX_SETTINGS_HEADER_TABLE_SIZE) |
178183 (1 << IDX_SETTINGS_ENABLE_PUSH) |
179184 (1 << IDX_SETTINGS_INITIAL_WINDOW_SIZE) |
180- (1 << IDX_SETTINGS_MAX_FRAME_SIZE);
185+ (1 << IDX_SETTINGS_MAX_FRAME_SIZE) |
186+ (1 << IDX_SETTINGS_MAX_HEADER_LIST_SIZE);
181187}
182188
183189
@@ -192,7 +198,10 @@ Http2Session::Http2Session(Environment* env,
192198
193199 padding_strategy_ = opts.GetPaddingStrategy ();
194200
195- Init (type, *opts);
201+ int32_t maxHeaderPairs = opts.GetMaxHeaderPairs ();
202+ maxHeaderPairs = type == NGHTTP2_SESSION_SERVER ?
203+ std::max (maxHeaderPairs, 4 ) : std::max (maxHeaderPairs, 1 );
204+ Init (type, *opts, nullptr , maxHeaderPairs);
196205
197206 // For every node::Http2Session instance, there is a uv_prepare_t handle
198207 // whose callback is triggered on every tick of the event loop. When
@@ -911,7 +920,8 @@ void Http2Session::OnTrailers(Nghttp2Stream* stream,
911920
912921void Http2Session::OnHeaders (
913922 Nghttp2Stream* stream,
914- std::queue<nghttp2_header>* headers,
923+ nghttp2_header* headers,
924+ size_t count,
915925 nghttp2_headers_category cat,
916926 uint8_t flags) {
917927 Local<Context> context = env ()->context ();
@@ -936,18 +946,19 @@ void Http2Session::OnHeaders(
936946 // like {name1: value1, name2: value2, name3: [value3, value4]}. We do it
937947 // this way for performance reasons (it's faster to generate and pass an
938948 // array than it is to generate and pass the object).
939- do {
949+ size_t n = 0 ;
950+ while (count > 0 ) {
940951 size_t j = 0 ;
941- while (!headers-> empty () && j < arraysize (argv) / 2 ) {
942- nghttp2_header item = headers-> front () ;
952+ while (count > 0 && j < arraysize (argv) / 2 ) {
953+ nghttp2_header item = headers[n++] ;
943954 // The header name and value are passed as external one-byte strings
944955 name_str =
945956 ExternalHeader::New<true >(env (), item.name ).ToLocalChecked ();
946957 value_str =
947958 ExternalHeader::New<false >(env (), item.value ).ToLocalChecked ();
948959 argv[j * 2 ] = name_str;
949960 argv[j * 2 + 1 ] = value_str;
950- headers-> pop () ;
961+ count-- ;
951962 j++;
952963 }
953964 // For performance, we pass name and value pairs to array.protototype.push
@@ -956,7 +967,7 @@ void Http2Session::OnHeaders(
956967 if (j > 0 ) {
957968 fn->Call (env ()->context (), holder, j * 2 , argv).ToLocalChecked ();
958969 }
959- } while (!headers-> empty ());
970+ }
960971
961972 Local<Value> args[4 ] = {
962973 Integer::New (isolate, stream->id ()),
0 commit comments