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
183189Http2Priority::Http2Priority (Environment* env,
@@ -204,7 +210,10 @@ Http2Session::Http2Session(Environment* env,
204210
205211 padding_strategy_ = opts.GetPaddingStrategy ();
206212
207- Init (type, *opts);
213+ int32_t maxHeaderPairs = opts.GetMaxHeaderPairs ();
214+ maxHeaderPairs = type == NGHTTP2_SESSION_SERVER ?
215+ std::max (maxHeaderPairs, 4 ) : std::max (maxHeaderPairs, 1 );
216+ Init (type, *opts, nullptr , maxHeaderPairs);
208217
209218 // For every node::Http2Session instance, there is a uv_prepare_t handle
210219 // whose callback is triggered on every tick of the event loop. When
@@ -901,7 +910,8 @@ void Http2Session::OnTrailers(Nghttp2Stream* stream,
901910
902911void Http2Session::OnHeaders (
903912 Nghttp2Stream* stream,
904- std::queue<nghttp2_header>* headers,
913+ nghttp2_header* headers,
914+ size_t count,
905915 nghttp2_headers_category cat,
906916 uint8_t flags) {
907917 Local<Context> context = env ()->context ();
@@ -926,18 +936,19 @@ void Http2Session::OnHeaders(
926936 // like {name1: value1, name2: value2, name3: [value3, value4]}. We do it
927937 // this way for performance reasons (it's faster to generate and pass an
928938 // array than it is to generate and pass the object).
929- do {
939+ size_t n = 0 ;
940+ while (count > 0 ) {
930941 size_t j = 0 ;
931- while (!headers-> empty () && j < arraysize (argv) / 2 ) {
932- nghttp2_header item = headers-> front () ;
942+ while (count > 0 && j < arraysize (argv) / 2 ) {
943+ nghttp2_header item = headers[n++] ;
933944 // The header name and value are passed as external one-byte strings
934945 name_str =
935946 ExternalHeader::New<true >(env (), item.name ).ToLocalChecked ();
936947 value_str =
937948 ExternalHeader::New<false >(env (), item.value ).ToLocalChecked ();
938949 argv[j * 2 ] = name_str;
939950 argv[j * 2 + 1 ] = value_str;
940- headers-> pop () ;
951+ count-- ;
941952 j++;
942953 }
943954 // For performance, we pass name and value pairs to array.protototype.push
@@ -946,7 +957,7 @@ void Http2Session::OnHeaders(
946957 if (j > 0 ) {
947958 fn->Call (env ()->context (), holder, j * 2 , argv).ToLocalChecked ();
948959 }
949- } while (!headers-> empty ());
960+ }
950961
951962 Local<Value> args[4 ] = {
952963 Integer::New (isolate, stream->id ()),
0 commit comments