• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef SRC_NODE_HTTP2_H_
2 #define SRC_NODE_HTTP2_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 // FIXME(joyeecheung): nghttp2.h needs stdint.h to compile on Windows
7 #include <cstdint>
8 #include "nghttp2/nghttp2.h"
9 
10 #include "allocated_buffer.h"
11 #include "aliased_struct.h"
12 #include "node_http2_state.h"
13 #include "node_http_common.h"
14 #include "node_mem.h"
15 #include "node_perf.h"
16 #include "stream_base.h"
17 #include "string_bytes.h"
18 
19 #include <algorithm>
20 #include <queue>
21 
22 namespace node {
23 namespace http2 {
24 
25 // Constants in all caps are exported as user-facing constants
26 // in JavaScript. Constants using the kName pattern are internal
27 // only.
28 
29 // We strictly limit the number of outstanding unacknowledged PINGS a user
30 // may send in order to prevent abuse. The current default cap is 10. The
31 // user may set a different limit using a per Http2Session configuration
32 // option.
33 constexpr size_t kDefaultMaxPings = 10;
34 
35 // Also strictly limit the number of outstanding SETTINGS frames a user sends
36 constexpr size_t kDefaultMaxSettings = 10;
37 
38 // Default maximum total memory cap for Http2Session.
39 constexpr uint64_t kDefaultMaxSessionMemory = 10000000;
40 
41 // These are the standard HTTP/2 defaults as specified by the RFC
42 constexpr uint32_t DEFAULT_SETTINGS_HEADER_TABLE_SIZE = 4096;
43 constexpr uint32_t DEFAULT_SETTINGS_ENABLE_PUSH = 1;
44 constexpr uint32_t DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS = 0xffffffffu;
45 constexpr uint32_t DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE = 65535;
46 constexpr uint32_t DEFAULT_SETTINGS_MAX_FRAME_SIZE = 16384;
47 constexpr uint32_t DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE = 65535;
48 constexpr uint32_t DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0;
49 constexpr uint32_t MAX_MAX_FRAME_SIZE = 16777215;
50 constexpr uint32_t MIN_MAX_FRAME_SIZE = DEFAULT_SETTINGS_MAX_FRAME_SIZE;
51 constexpr uint32_t MAX_INITIAL_WINDOW_SIZE = 2147483647;
52 
53 // Stream is not going to have any DATA frames
54 constexpr int STREAM_OPTION_EMPTY_PAYLOAD = 0x1;
55 
56 // Stream might have trailing headers
57 constexpr int STREAM_OPTION_GET_TRAILERS = 0x2;
58 
59 // Http2Stream internal states
60 constexpr int kStreamStateNone = 0x0;
61 constexpr int kStreamStateShut = 0x1;
62 constexpr int kStreamStateReadStart = 0x2;
63 constexpr int kStreamStateReadPaused = 0x4;
64 constexpr int kStreamStateClosed = 0x8;
65 constexpr int kStreamStateDestroyed = 0x10;
66 constexpr int kStreamStateTrailers = 0x20;
67 
68 // Http2Session internal states
69 constexpr int kSessionStateNone = 0x0;
70 constexpr int kSessionStateHasScope = 0x1;
71 constexpr int kSessionStateWriteScheduled = 0x2;
72 constexpr int kSessionStateClosed = 0x4;
73 constexpr int kSessionStateClosing = 0x8;
74 constexpr int kSessionStateSending = 0x10;
75 constexpr int kSessionStateWriteInProgress = 0x20;
76 constexpr int kSessionStateReadingStopped = 0x40;
77 constexpr int kSessionStateReceivePaused = 0x80;
78 
79 // The Padding Strategy determines the method by which extra padding is
80 // selected for HEADERS and DATA frames. These are configurable via the
81 // options passed in to a Http2Session object.
82 enum PaddingStrategy {
83   // No padding strategy. This is the default.
84   PADDING_STRATEGY_NONE,
85   // Attempts to ensure that the frame is 8-byte aligned
86   PADDING_STRATEGY_ALIGNED,
87   // Padding will ensure all data frames are maxFrameSize
88   PADDING_STRATEGY_MAX,
89   // Removed and turned into an alias because it is unreasonably expensive for
90   // very little benefit.
91   PADDING_STRATEGY_CALLBACK = PADDING_STRATEGY_ALIGNED
92 };
93 
94 enum SessionType {
95   NGHTTP2_SESSION_SERVER,
96   NGHTTP2_SESSION_CLIENT
97 };
98 
99 template <typename T, void(*fn)(T*)>
100 struct Nghttp2Deleter {
operatorNghttp2Deleter101   void operator()(T* ptr) const noexcept { fn(ptr); }
102 };
103 
104 using Nghttp2OptionPointer =
105     std::unique_ptr<nghttp2_option,
106                     Nghttp2Deleter<nghttp2_option, nghttp2_option_del>>;
107 
108 using Nghttp2SessionPointer =
109     std::unique_ptr<nghttp2_session,
110                     Nghttp2Deleter<nghttp2_session, nghttp2_session_del>>;
111 
112 using Nghttp2SessionCallbacksPointer =
113     std::unique_ptr<nghttp2_session_callbacks,
114                     Nghttp2Deleter<nghttp2_session_callbacks,
115                                    nghttp2_session_callbacks_del>>;
116 
117 struct Http2HeadersTraits {
118   typedef nghttp2_nv nv_t;
119 };
120 
121 struct Http2RcBufferPointerTraits {
122   typedef nghttp2_rcbuf rcbuf_t;
123   typedef nghttp2_vec vector_t;
124 
incHttp2RcBufferPointerTraits125   static void inc(rcbuf_t* buf) {
126     CHECK_NOT_NULL(buf);
127     nghttp2_rcbuf_incref(buf);
128   }
decHttp2RcBufferPointerTraits129   static void dec(rcbuf_t* buf) {
130     CHECK_NOT_NULL(buf);
131     nghttp2_rcbuf_decref(buf);
132   }
get_vecHttp2RcBufferPointerTraits133   static vector_t get_vec(rcbuf_t* buf) {
134     CHECK_NOT_NULL(buf);
135     return nghttp2_rcbuf_get_buf(buf);
136   }
is_staticHttp2RcBufferPointerTraits137   static bool is_static(const rcbuf_t* buf) {
138     CHECK_NOT_NULL(buf);
139     return nghttp2_rcbuf_is_static(buf);
140   }
141 };
142 
143 using Http2Headers = NgHeaders<Http2HeadersTraits>;
144 using Http2RcBufferPointer = NgRcBufPointer<Http2RcBufferPointerTraits>;
145 
146 struct NgHttp2StreamWrite : public MemoryRetainer {
147   BaseObjectPtr<AsyncWrap> req_wrap;
148   uv_buf_t buf;
149 
NgHttp2StreamWriteNgHttp2StreamWrite150   inline explicit NgHttp2StreamWrite(uv_buf_t buf_) : buf(buf_) {}
NgHttp2StreamWriteNgHttp2StreamWrite151   inline NgHttp2StreamWrite(BaseObjectPtr<AsyncWrap> req_wrap, uv_buf_t buf_) :
152       req_wrap(std::move(req_wrap)), buf(buf_) {}
153 
154   void MemoryInfo(MemoryTracker* tracker) const override;
155   SET_MEMORY_INFO_NAME(NgHttp2StreamWrite)
156   SET_SELF_SIZE(NgHttp2StreamWrite)
157 };
158 
159 typedef uint32_t(*get_setting)(nghttp2_session* session,
160                                nghttp2_settings_id id);
161 
162 class Http2Ping;
163 class Http2Session;
164 class Http2Settings;
165 class Http2Stream;
166 class Origins;
167 
168 // This scope should be present when any call into nghttp2 that may schedule
169 // data to be written to the underlying transport is made, and schedules
170 // such a write automatically once the scope is exited.
171 class Http2Scope {
172  public:
173   explicit Http2Scope(Http2Stream* stream);
174   explicit Http2Scope(Http2Session* session);
175   ~Http2Scope();
176 
177  private:
178   BaseObjectPtr<Http2Session> session_;
179 };
180 
181 // The Http2Options class is used to parse the options object passed in to
182 // a Http2Session object and convert those into an appropriate nghttp2_option
183 // struct. This is the primary mechanism by which the Http2Session object is
184 // configured.
185 class Http2Options {
186  public:
187   Http2Options(Http2State* http2_state,
188                SessionType type);
189 
190   ~Http2Options() = default;
191 
192   nghttp2_option* operator*() const {
193     return options_.get();
194   }
195 
set_max_header_pairs(uint32_t max)196   void set_max_header_pairs(uint32_t max) {
197     max_header_pairs_ = max;
198   }
199 
max_header_pairs()200   uint32_t max_header_pairs() const {
201     return max_header_pairs_;
202   }
203 
set_padding_strategy(PaddingStrategy val)204   void set_padding_strategy(PaddingStrategy val) {
205     padding_strategy_ = val;
206   }
207 
padding_strategy()208   PaddingStrategy padding_strategy() const {
209     return padding_strategy_;
210   }
211 
set_max_outstanding_pings(size_t max)212   void set_max_outstanding_pings(size_t max) {
213     max_outstanding_pings_ = max;
214   }
215 
max_outstanding_pings()216   size_t max_outstanding_pings() const {
217     return max_outstanding_pings_;
218   }
219 
set_max_outstanding_settings(size_t max)220   void set_max_outstanding_settings(size_t max) {
221     max_outstanding_settings_ = max;
222   }
223 
max_outstanding_settings()224   size_t max_outstanding_settings() const {
225     return max_outstanding_settings_;
226   }
227 
set_max_session_memory(uint64_t max)228   void set_max_session_memory(uint64_t max) {
229     max_session_memory_ = max;
230   }
231 
max_session_memory()232   uint64_t max_session_memory() const {
233     return max_session_memory_;
234   }
235 
236  private:
237   Nghttp2OptionPointer options_;
238   uint64_t max_session_memory_ = kDefaultMaxSessionMemory;
239   uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS;
240   PaddingStrategy padding_strategy_ = PADDING_STRATEGY_NONE;
241   size_t max_outstanding_pings_ = kDefaultMaxPings;
242   size_t max_outstanding_settings_ = kDefaultMaxSettings;
243 };
244 
245 struct Http2Priority : public nghttp2_priority_spec {
246   Http2Priority(Environment* env,
247                 v8::Local<v8::Value> parent,
248                 v8::Local<v8::Value> weight,
249                 v8::Local<v8::Value> exclusive);
250 };
251 
252 class Http2StreamListener : public StreamListener {
253  public:
254   uv_buf_t OnStreamAlloc(size_t suggested_size) override;
255   void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override;
256 };
257 
258 struct Http2HeaderTraits {
259   typedef Http2RcBufferPointer rcbufferpointer_t;
260   typedef Http2Session allocator_t;
261 
262   // HTTP/2 does not support identifying header names by token id.
263   // HTTP/3 will, however, so we prepare for that now.
ToHttpHeaderNameHttp2HeaderTraits264   static const char* ToHttpHeaderName(int32_t token) { return nullptr; }
265 };
266 
267 using Http2Header = NgHeader<Http2HeaderTraits>;
268 
269 class Http2Stream : public AsyncWrap,
270                     public StreamBase {
271  public:
272   static Http2Stream* New(
273       Http2Session* session,
274       int32_t id,
275       nghttp2_headers_category category = NGHTTP2_HCAT_HEADERS,
276       int options = 0);
277   ~Http2Stream() override;
278 
279   nghttp2_stream* operator*() const;
280 
281   nghttp2_stream* stream() const;
282 
session()283   Http2Session* session() { return session_.get(); }
session()284   const Http2Session* session() const { return session_.get(); }
285 
286   // Required for StreamBase
287   int ReadStart() override;
288 
289   // Required for StreamBase
290   int ReadStop() override;
291 
292   // Required for StreamBase
293   ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override;
294   int DoShutdown(ShutdownWrap* req_wrap) override;
295 
HasWantsWrite()296   bool HasWantsWrite() const override { return true; }
297 
298   // Initiate a response on this stream.
299   int SubmitResponse(const Http2Headers& headers, int options);
300 
301   // Submit informational headers for this stream
302   int SubmitInfo(const Http2Headers& headers);
303 
304   // Submit trailing headers for this stream
305   int SubmitTrailers(const Http2Headers& headers);
306   void OnTrailers();
307 
308   // Submit a PRIORITY frame for this stream
309   int SubmitPriority(const Http2Priority& priority, bool silent = false);
310 
311   // Submits an RST_STREAM frame using the given code
312   void SubmitRstStream(const uint32_t code);
313 
314   void FlushRstStream();
315 
316   // Submits a PUSH_PROMISE frame with this stream as the parent.
317   Http2Stream* SubmitPushPromise(
318       const Http2Headers& headers,
319       int32_t* ret,
320       int options = 0);
321 
322 
323   void Close(int32_t code);
324 
325   // Destroy this stream instance and free all held memory.
326   void Destroy();
327 
is_destroyed()328   bool is_destroyed() const {
329     return flags_ & kStreamStateDestroyed;
330   }
331 
is_writable()332   bool is_writable() const {
333     return !(flags_ & kStreamStateShut);
334   }
335 
is_paused()336   bool is_paused() const {
337     return flags_ & kStreamStateReadPaused;
338   }
339 
is_closed()340   bool is_closed() const {
341     return flags_ & kStreamStateClosed;
342   }
343 
has_trailers()344   bool has_trailers() const {
345     return flags_ & kStreamStateTrailers;
346   }
347 
348   void set_has_trailers(bool on = true) {
349     if (on)
350       flags_ |= kStreamStateTrailers;
351     else
352       flags_ &= ~kStreamStateTrailers;
353   }
354 
set_closed()355   void set_closed() {
356     flags_ |= kStreamStateClosed;
357   }
358 
set_destroyed()359   void set_destroyed() {
360     flags_ |= kStreamStateDestroyed;
361   }
362 
set_not_writable()363   void set_not_writable() {
364     flags_ |= kStreamStateShut;
365   }
366 
367   void set_reading(bool on = true) {
368     if (on) {
369       flags_ |= kStreamStateReadStart;
370       set_paused(false);
371     } else {}
372   }
373 
374   void set_paused(bool on = true) {
375     if (on)
376       flags_ |= kStreamStateReadPaused;
377     else
378       flags_ &= ~kStreamStateReadPaused;
379   }
380 
381   // Returns true if this stream is in the reading state, which occurs when
382   // the kStreamStateReadStart flag has been set and the
383   // kStreamStateReadPaused flag is *not* set.
is_reading()384   bool is_reading() const {
385     return flags_ & kStreamStateReadStart && !is_paused();
386   }
387 
388   // Returns the RST_STREAM code used to close this stream
code()389   int32_t code() const { return code_; }
390 
391   // Returns the stream identifier for this stream
id()392   int32_t id() const { return id_; }
393 
394   void IncrementAvailableOutboundLength(size_t amount);
395   void DecrementAvailableOutboundLength(size_t amount);
396 
397   bool AddHeader(nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags);
398 
399   template <typename Fn>
TransferHeaders(Fn && fn)400   void TransferHeaders(Fn&& fn) {
401     size_t i = 0;
402     for (const auto& header : current_headers_ )
403       fn(header, i++);
404     current_headers_.clear();
405   }
406 
headers_count()407   size_t headers_count() const {
408     return current_headers_.size();
409   }
410 
headers_category()411   nghttp2_headers_category headers_category() const {
412     return current_headers_category_;
413   }
414 
415   void StartHeaders(nghttp2_headers_category category);
416 
417   // Required for StreamBase
IsAlive()418   bool IsAlive() override {
419     return true;
420   }
421 
422   // Required for StreamBase
IsClosing()423   bool IsClosing() override {
424     return false;
425   }
426 
GetAsyncWrap()427   AsyncWrap* GetAsyncWrap() override { return this; }
428 
429   int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count,
430               uv_stream_t* send_handle) override;
431 
432   void MemoryInfo(MemoryTracker* tracker) const override;
433   SET_MEMORY_INFO_NAME(Http2Stream)
434   SET_SELF_SIZE(Http2Stream)
435 
436   std::string diagnostic_name() const override;
437 
438   // JavaScript API
439   static void GetID(const v8::FunctionCallbackInfo<v8::Value>& args);
440   static void Destroy(const v8::FunctionCallbackInfo<v8::Value>& args);
441   static void Priority(const v8::FunctionCallbackInfo<v8::Value>& args);
442   static void PushPromise(const v8::FunctionCallbackInfo<v8::Value>& args);
443   static void RefreshState(const v8::FunctionCallbackInfo<v8::Value>& args);
444   static void Info(const v8::FunctionCallbackInfo<v8::Value>& args);
445   static void Trailers(const v8::FunctionCallbackInfo<v8::Value>& args);
446   static void Respond(const v8::FunctionCallbackInfo<v8::Value>& args);
447   static void RstStream(const v8::FunctionCallbackInfo<v8::Value>& args);
448 
449   class Provider;
450 
451   struct Statistics {
452     uint64_t start_time;
453     uint64_t end_time;
454     uint64_t first_header;     // Time first header was received
455     uint64_t first_byte;       // Time first DATA frame byte was received
456     uint64_t first_byte_sent;  // Time first DATA frame byte was sent
457     uint64_t sent_bytes;
458     uint64_t received_bytes;
459   };
460 
461   Statistics statistics_ = {};
462 
463  private:
464   Http2Stream(Http2Session* session,
465               v8::Local<v8::Object> obj,
466               int32_t id,
467               nghttp2_headers_category category,
468               int options);
469 
470   void EmitStatistics();
471 
472   BaseObjectWeakPtr<Http2Session> session_;     // The Parent HTTP/2 Session
473   int32_t id_ = 0;                              // The Stream Identifier
474   int32_t code_ = NGHTTP2_NO_ERROR;             // The RST_STREAM code (if any)
475   int flags_ = kStreamStateNone;        // Internal state flags
476 
477   uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS;
478   uint32_t max_header_length_ = DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE;
479 
480   // The Current Headers block... As headers are received for this stream,
481   // they are temporarily stored here until the OnFrameReceived is called
482   // signalling the end of the HEADERS frame
483   nghttp2_headers_category current_headers_category_ = NGHTTP2_HCAT_HEADERS;
484   uint32_t current_headers_length_ = 0;  // total number of octets
485   std::vector<Http2Header> current_headers_;
486 
487   // This keeps track of the amount of data read from the socket while the
488   // socket was in paused mode. When `ReadStart()` is called (and not before
489   // then), we tell nghttp2 that we consumed that data to get proper
490   // backpressure handling.
491   size_t inbound_consumed_data_while_paused_ = 0;
492 
493   // Outbound Data... This is the data written by the JS layer that is
494   // waiting to be written out to the socket.
495   std::queue<NgHttp2StreamWrite> queue_;
496   size_t available_outbound_length_ = 0;
497 
498   Http2StreamListener stream_listener_;
499 
500   friend class Http2Session;
501 };
502 
503 class Http2Stream::Provider {
504  public:
505   Provider(Http2Stream* stream, int options);
506   explicit Provider(int options);
507   virtual ~Provider();
508 
509   nghttp2_data_provider* operator*() {
510     return !empty_ ? &provider_ : nullptr;
511   }
512 
513   class FD;
514   class Stream;
515  protected:
516   nghttp2_data_provider provider_;
517 
518  private:
519   bool empty_ = false;
520 };
521 
522 class Http2Stream::Provider::Stream : public Http2Stream::Provider {
523  public:
524   Stream(Http2Stream* stream, int options);
525   explicit Stream(int options);
526 
527   static ssize_t OnRead(nghttp2_session* session,
528                         int32_t id,
529                         uint8_t* buf,
530                         size_t length,
531                         uint32_t* flags,
532                         nghttp2_data_source* source,
533                         void* user_data);
534 };
535 
536 struct SessionJSFields {
537   uint8_t bitfield;
538   uint8_t priority_listener_count;
539   uint8_t frame_error_listener_count;
540   uint32_t max_invalid_frames = 1000;
541   uint32_t max_rejected_streams = 100;
542 };
543 
544 // Indices for js_fields_, which serves as a way to communicate data with JS
545 // land fast. In particular, we store information about the number/presence
546 // of certain event listeners in JS, and skip calls from C++ into JS if they
547 // are missing.
548 enum SessionUint8Fields {
549   kBitfield = offsetof(SessionJSFields, bitfield),  // See below
550   kSessionPriorityListenerCount =
551       offsetof(SessionJSFields, priority_listener_count),
552   kSessionFrameErrorListenerCount =
553       offsetof(SessionJSFields, frame_error_listener_count),
554   kSessionMaxInvalidFrames = offsetof(SessionJSFields, max_invalid_frames),
555   kSessionMaxRejectedStreams = offsetof(SessionJSFields, max_rejected_streams),
556   kSessionUint8FieldCount = sizeof(SessionJSFields)
557 };
558 
559 enum SessionBitfieldFlags {
560   kSessionHasRemoteSettingsListeners,
561   kSessionRemoteSettingsIsUpToDate,
562   kSessionHasPingListeners,
563   kSessionHasAltsvcListeners
564 };
565 
566 class Http2Session : public AsyncWrap,
567                      public StreamListener,
568                      public mem::NgLibMemoryManager<Http2Session, nghttp2_mem> {
569  public:
570   Http2Session(Http2State* http2_state,
571                v8::Local<v8::Object> wrap,
572                SessionType type = NGHTTP2_SESSION_SERVER);
573   ~Http2Session() override;
574 
underlying_stream()575   StreamBase* underlying_stream() {
576     return static_cast<StreamBase*>(stream_);
577   }
578 
579   void Close(uint32_t code = NGHTTP2_NO_ERROR,
580              bool socket_closed = false);
581 
582   void Consume(v8::Local<v8::Object> stream);
583 
584   void Goaway(uint32_t code, int32_t lastStreamID,
585               const uint8_t* data, size_t len);
586 
587   void AltSvc(int32_t id,
588               uint8_t* origin,
589               size_t origin_len,
590               uint8_t* value,
591               size_t value_len);
592 
593   void Origin(const Origins& origins);
594 
595   uint8_t SendPendingData();
596 
597   // Submits a new request. If the request is a success, assigned
598   // will be a pointer to the Http2Stream instance assigned.
599   // This only works if the session is a client session.
600   Http2Stream* SubmitRequest(
601       const Http2Priority& priority,
602       const Http2Headers& headers,
603       int32_t* ret,
604       int options = 0);
605 
type()606   SessionType type() const { return session_type_; }
607 
session()608   nghttp2_session* session() const { return session_.get(); }
609 
610   nghttp2_session* operator*() { return session_.get(); }
611 
max_header_pairs()612   uint32_t max_header_pairs() const { return max_header_pairs_; }
613 
614   const char* TypeName() const;
615 
is_destroyed()616   bool is_destroyed() {
617     return (flags_ & kSessionStateClosed) || session_ == nullptr;
618   }
619 
set_destroyed()620   void set_destroyed() {
621     flags_ |= kSessionStateClosed;
622   }
623 
624 #define IS_FLAG(name, flag)                                                    \
625   bool is_##name() const { return flags_ & flag; }                             \
626   void set_##name(bool on = true) {                                            \
627     if (on)                                                                    \
628       flags_ |= flag;                                                          \
629     else                                                                       \
630       flags_ &= ~flag;                                                         \
631   }
632 
633   IS_FLAG(in_scope, kSessionStateHasScope)
634   IS_FLAG(write_scheduled, kSessionStateWriteScheduled)
635   IS_FLAG(closing, kSessionStateClosing)
636   IS_FLAG(sending, kSessionStateSending)
637   IS_FLAG(write_in_progress, kSessionStateWriteInProgress)
638   IS_FLAG(reading_stopped, kSessionStateReadingStopped)
639   IS_FLAG(receive_paused, kSessionStateReceivePaused)
640 
641 #undef IS_FLAG
642 
643   // Schedule a write if nghttp2 indicates it wants to write to the socket.
644   void MaybeScheduleWrite();
645 
646   // Stop reading if nghttp2 doesn't want to anymore.
647   void MaybeStopReading();
648 
649   // Returns pointer to the stream, or nullptr if stream does not exist
650   BaseObjectPtr<Http2Stream> FindStream(int32_t id);
651 
652   bool CanAddStream();
653 
654   // Adds a stream instance to this session
655   void AddStream(Http2Stream* stream);
656 
657   // Removes a stream instance from this session
658   BaseObjectPtr<Http2Stream> RemoveStream(int32_t id);
659 
660   // Indicates whether there currently exist outgoing buffers for this stream.
661   bool HasWritesOnSocketForStream(Http2Stream* stream);
662 
663   // Write data from stream_buf_ to the session
664   ssize_t ConsumeHTTP2Data();
665 
666   void MemoryInfo(MemoryTracker* tracker) const override;
667   SET_MEMORY_INFO_NAME(Http2Session)
668   SET_SELF_SIZE(Http2Session)
669 
670   std::string diagnostic_name() const override;
671 
672   // Schedule an RstStream for after the current write finishes.
AddPendingRstStream(int32_t stream_id)673   void AddPendingRstStream(int32_t stream_id) {
674     pending_rst_streams_.emplace_back(stream_id);
675   }
676 
has_pending_rststream(int32_t stream_id)677   bool has_pending_rststream(int32_t stream_id) {
678     return pending_rst_streams_.end() !=
679         std::find(pending_rst_streams_.begin(),
680             pending_rst_streams_.end(),
681             stream_id);
682   }
683 
684   // Handle reads/writes from the underlying network transport.
685   uv_buf_t OnStreamAlloc(size_t suggested_size) override;
686   void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override;
687   void OnStreamAfterWrite(WriteWrap* w, int status) override;
688 
689   // Implementation for mem::NgLibMemoryManager
690   void CheckAllocatedSize(size_t previous_size) const;
691   void IncreaseAllocatedSize(size_t size);
692   void DecreaseAllocatedSize(size_t size);
693 
694   // The JavaScript API
695   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
696   static void Consume(const v8::FunctionCallbackInfo<v8::Value>& args);
697   static void Receive(const v8::FunctionCallbackInfo<v8::Value>& args);
698   static void Destroy(const v8::FunctionCallbackInfo<v8::Value>& args);
699   static void Settings(const v8::FunctionCallbackInfo<v8::Value>& args);
700   static void Request(const v8::FunctionCallbackInfo<v8::Value>& args);
701   static void SetNextStreamID(const v8::FunctionCallbackInfo<v8::Value>& args);
702   static void SetLocalWindowSize(
703       const v8::FunctionCallbackInfo<v8::Value>& args);
704   static void Goaway(const v8::FunctionCallbackInfo<v8::Value>& args);
705   static void UpdateChunksSent(const v8::FunctionCallbackInfo<v8::Value>& args);
706   static void RefreshState(const v8::FunctionCallbackInfo<v8::Value>& args);
707   static void Ping(const v8::FunctionCallbackInfo<v8::Value>& args);
708   static void AltSvc(const v8::FunctionCallbackInfo<v8::Value>& args);
709   static void Origin(const v8::FunctionCallbackInfo<v8::Value>& args);
710 
711   template <get_setting fn>
712   static void RefreshSettings(const v8::FunctionCallbackInfo<v8::Value>& args);
713 
event_loop()714   uv_loop_t* event_loop() const {
715     return env()->event_loop();
716   }
717 
http2_state()718   Http2State* http2_state() const { return http2_state_.get(); }
719 
720   BaseObjectPtr<Http2Ping> PopPing();
721   bool AddPing(const uint8_t* data, v8::Local<v8::Function> callback);
722 
723   BaseObjectPtr<Http2Settings> PopSettings();
724   bool AddSettings(v8::Local<v8::Function> callback);
725 
IncrementCurrentSessionMemory(uint64_t amount)726   void IncrementCurrentSessionMemory(uint64_t amount) {
727     current_session_memory_ += amount;
728   }
729 
DecrementCurrentSessionMemory(uint64_t amount)730   void DecrementCurrentSessionMemory(uint64_t amount) {
731     DCHECK_LE(amount, current_session_memory_);
732     current_session_memory_ -= amount;
733   }
734 
735   // Tell our custom memory allocator that this rcbuf is independent of
736   // this session now, and may outlive it.
737   void StopTrackingRcbuf(nghttp2_rcbuf* buf);
738 
739   // Returns the current session memory including memory allocated by nghttp2,
740   // the current outbound storage queue, and pending writes.
current_session_memory()741   uint64_t current_session_memory() const {
742     uint64_t total = current_session_memory_ + sizeof(Http2Session);
743     total += current_nghttp2_memory_;
744     total += outgoing_storage_.size();
745     return total;
746   }
747 
748   // Return true if current_session_memory + amount is less than the max
has_available_session_memory(uint64_t amount)749   bool has_available_session_memory(uint64_t amount) const {
750     return current_session_memory() + amount <= max_session_memory_;
751   }
752 
753   struct Statistics {
754     uint64_t start_time;
755     uint64_t end_time;
756     uint64_t ping_rtt;
757     uint64_t data_sent;
758     uint64_t data_received;
759     uint32_t frame_count;
760     uint32_t frame_sent;
761     int32_t stream_count;
762     size_t max_concurrent_streams;
763     double stream_average_duration;
764   };
765 
766   Statistics statistics_ = {};
767 
768  private:
769   void EmitStatistics();
770 
771   // Frame Padding Strategies
772   ssize_t OnDWordAlignedPadding(size_t frameLength,
773                                 size_t maxPayloadLen);
774   ssize_t OnMaxFrameSizePadding(size_t frameLength,
775                                 size_t maxPayloadLen);
776 
777   // Frame Handler
778   int HandleDataFrame(const nghttp2_frame* frame);
779   void HandleGoawayFrame(const nghttp2_frame* frame);
780   void HandleHeadersFrame(const nghttp2_frame* frame);
781   void HandlePriorityFrame(const nghttp2_frame* frame);
782   void HandleSettingsFrame(const nghttp2_frame* frame);
783   void HandlePingFrame(const nghttp2_frame* frame);
784   void HandleAltSvcFrame(const nghttp2_frame* frame);
785   void HandleOriginFrame(const nghttp2_frame* frame);
786 
787   // nghttp2 callbacks
788   static int OnBeginHeadersCallback(
789       nghttp2_session* session,
790       const nghttp2_frame* frame,
791       void* user_data);
792   static int OnHeaderCallback(
793       nghttp2_session* session,
794       const nghttp2_frame* frame,
795       nghttp2_rcbuf* name,
796       nghttp2_rcbuf* value,
797       uint8_t flags,
798       void* user_data);
799   static int OnFrameReceive(
800       nghttp2_session* session,
801       const nghttp2_frame* frame,
802       void* user_data);
803   static int OnFrameNotSent(
804       nghttp2_session* session,
805       const nghttp2_frame* frame,
806       int error_code,
807       void* user_data);
808   static int OnFrameSent(
809       nghttp2_session* session,
810       const nghttp2_frame* frame,
811       void* user_data);
812   static int OnStreamClose(
813       nghttp2_session* session,
814       int32_t id,
815       uint32_t code,
816       void* user_data);
817   static int OnInvalidHeader(
818       nghttp2_session* session,
819       const nghttp2_frame* frame,
820       nghttp2_rcbuf* name,
821       nghttp2_rcbuf* value,
822       uint8_t flags,
823       void* user_data);
824   static int OnDataChunkReceived(
825       nghttp2_session* session,
826       uint8_t flags,
827       int32_t id,
828       const uint8_t* data,
829       size_t len,
830       void* user_data);
831   static ssize_t OnSelectPadding(
832       nghttp2_session* session,
833       const nghttp2_frame* frame,
834       size_t maxPayloadLen,
835       void* user_data);
836   static int OnNghttpError(
837       nghttp2_session* session,
838       const char* message,
839       size_t len,
840       void* user_data);
841   static int OnSendData(
842       nghttp2_session* session,
843       nghttp2_frame* frame,
844       const uint8_t* framehd,
845       size_t length,
846       nghttp2_data_source* source,
847       void* user_data);
848   static int OnInvalidFrame(
849       nghttp2_session* session,
850       const nghttp2_frame* frame,
851       int lib_error_code,
852       void* user_data);
853 
854   struct Callbacks {
855     explicit Callbacks(bool kHasGetPaddingCallback);
856 
857     Nghttp2SessionCallbacksPointer callbacks;
858   };
859 
860   /* Use callback_struct_saved[kHasGetPaddingCallback ? 1 : 0] */
861   static const Callbacks callback_struct_saved[2];
862 
863   // The underlying nghttp2_session handle
864   Nghttp2SessionPointer session_;
865 
866   // JS-accessible numeric fields, as indexed by SessionUint8Fields.
867   AliasedStruct<SessionJSFields> js_fields_;
868 
869   // The session type: client or server
870   SessionType session_type_;
871 
872   // The maximum number of header pairs permitted for streams on this session
873   uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS;
874 
875   // The maximum amount of memory allocated for this session
876   uint64_t max_session_memory_ = kDefaultMaxSessionMemory;
877   uint64_t current_session_memory_ = 0;
878   // The amount of memory allocated by nghttp2 internals
879   uint64_t current_nghttp2_memory_ = 0;
880 
881   // The collection of active Http2Streams associated with this session
882   std::unordered_map<int32_t, BaseObjectPtr<Http2Stream>> streams_;
883 
884   int flags_ = kSessionStateNone;
885 
886   // The StreamBase instance being used for i/o
887   PaddingStrategy padding_strategy_ = PADDING_STRATEGY_NONE;
888 
889   // use this to allow timeout tracking during long-lasting writes
890   uint32_t chunks_sent_since_last_write_ = 0;
891 
892   uv_buf_t stream_buf_ = uv_buf_init(nullptr, 0);
893   // When processing input data, either stream_buf_ab_ or stream_buf_allocation_
894   // will be set. stream_buf_ab_ is lazily created from stream_buf_allocation_.
895   v8::Global<v8::ArrayBuffer> stream_buf_ab_;
896   AllocatedBuffer stream_buf_allocation_;
897   size_t stream_buf_offset_ = 0;
898 
899   size_t max_outstanding_pings_ = kDefaultMaxPings;
900   std::queue<BaseObjectPtr<Http2Ping>> outstanding_pings_;
901 
902   size_t max_outstanding_settings_ = kDefaultMaxSettings;
903   std::queue<BaseObjectPtr<Http2Settings>> outstanding_settings_;
904 
905   std::vector<NgHttp2StreamWrite> outgoing_buffers_;
906   std::vector<uint8_t> outgoing_storage_;
907   size_t outgoing_length_ = 0;
908   std::vector<int32_t> pending_rst_streams_;
909   // Count streams that have been rejected while being opened. Exceeding a fixed
910   // limit will result in the session being destroyed, as an indication of a
911   // misbehaving peer. This counter is reset once new streams are being
912   // accepted again.
913   uint32_t rejected_stream_count_ = 0;
914   // Also use the invalid frame count as a measure for rejecting input frames.
915   uint32_t invalid_frame_count_ = 0;
916 
917   void PushOutgoingBuffer(NgHttp2StreamWrite&& write);
918 
919   BaseObjectPtr<Http2State> http2_state_;
920 
921   void CopyDataIntoOutgoing(const uint8_t* src, size_t src_length);
922   void ClearOutgoing(int status);
923 
924   friend class Http2Scope;
925   friend class Http2StreamListener;
926 };
927 
928 class Http2SessionPerformanceEntry : public performance::PerformanceEntry {
929  public:
Http2SessionPerformanceEntry(Http2State * http2_state,const Http2Session::Statistics & stats,SessionType type)930   Http2SessionPerformanceEntry(
931       Http2State* http2_state,
932       const Http2Session::Statistics& stats,
933       SessionType type) :
934           performance::PerformanceEntry(
935               http2_state->env(), "Http2Session", "http2",
936               stats.start_time,
937               stats.end_time),
938           ping_rtt_(stats.ping_rtt),
939           data_sent_(stats.data_sent),
940           data_received_(stats.data_received),
941           frame_count_(stats.frame_count),
942           frame_sent_(stats.frame_sent),
943           stream_count_(stats.stream_count),
944           max_concurrent_streams_(stats.max_concurrent_streams),
945           stream_average_duration_(stats.stream_average_duration),
946           session_type_(type),
947           http2_state_(http2_state) { }
948 
ping_rtt()949   uint64_t ping_rtt() const { return ping_rtt_; }
data_sent()950   uint64_t data_sent() const { return data_sent_; }
data_received()951   uint64_t data_received() const { return data_received_; }
frame_count()952   uint32_t frame_count() const { return frame_count_; }
frame_sent()953   uint32_t frame_sent() const { return frame_sent_; }
stream_count()954   int32_t stream_count() const { return stream_count_; }
max_concurrent_streams()955   size_t max_concurrent_streams() const { return max_concurrent_streams_; }
stream_average_duration()956   double stream_average_duration() const { return stream_average_duration_; }
type()957   SessionType type() const { return session_type_; }
http2_state()958   Http2State* http2_state() const { return http2_state_.get(); }
959 
Notify(v8::Local<v8::Value> obj)960   void Notify(v8::Local<v8::Value> obj) {
961     performance::PerformanceEntry::Notify(env(), kind(), obj);
962   }
963 
964  private:
965   uint64_t ping_rtt_;
966   uint64_t data_sent_;
967   uint64_t data_received_;
968   uint32_t frame_count_;
969   uint32_t frame_sent_;
970   int32_t stream_count_;
971   size_t max_concurrent_streams_;
972   double stream_average_duration_;
973   SessionType session_type_;
974   BaseObjectPtr<Http2State> http2_state_;
975 };
976 
977 class Http2StreamPerformanceEntry
978     : public performance::PerformanceEntry {
979  public:
Http2StreamPerformanceEntry(Http2State * http2_state,int32_t id,const Http2Stream::Statistics & stats)980   Http2StreamPerformanceEntry(
981       Http2State* http2_state,
982       int32_t id,
983       const Http2Stream::Statistics& stats) :
984           performance::PerformanceEntry(
985               http2_state->env(), "Http2Stream", "http2",
986               stats.start_time,
987               stats.end_time),
988           id_(id),
989           first_header_(stats.first_header),
990           first_byte_(stats.first_byte),
991           first_byte_sent_(stats.first_byte_sent),
992           sent_bytes_(stats.sent_bytes),
993           received_bytes_(stats.received_bytes),
994           http2_state_(http2_state) { }
995 
id()996   int32_t id() const { return id_; }
first_header()997   uint64_t first_header() const { return first_header_; }
first_byte()998   uint64_t first_byte() const { return first_byte_; }
first_byte_sent()999   uint64_t first_byte_sent() const { return first_byte_sent_; }
sent_bytes()1000   uint64_t sent_bytes() const { return sent_bytes_; }
received_bytes()1001   uint64_t received_bytes() const { return received_bytes_; }
http2_state()1002   Http2State* http2_state() const { return http2_state_.get(); }
1003 
Notify(v8::Local<v8::Value> obj)1004   void Notify(v8::Local<v8::Value> obj) {
1005     performance::PerformanceEntry::Notify(env(), kind(), obj);
1006   }
1007 
1008  private:
1009   int32_t id_;
1010   uint64_t first_header_;
1011   uint64_t first_byte_;
1012   uint64_t first_byte_sent_;
1013   uint64_t sent_bytes_;
1014   uint64_t received_bytes_;
1015   BaseObjectPtr<Http2State> http2_state_;
1016 };
1017 
1018 class Http2Ping : public AsyncWrap {
1019  public:
1020   explicit Http2Ping(
1021       Http2Session* session,
1022       v8::Local<v8::Object> obj,
1023       v8::Local<v8::Function> callback);
1024 
1025   void MemoryInfo(MemoryTracker* tracker) const override;
1026   SET_MEMORY_INFO_NAME(Http2Ping)
1027   SET_SELF_SIZE(Http2Ping)
1028 
1029   void Send(const uint8_t* payload);
1030   void Done(bool ack, const uint8_t* payload = nullptr);
1031   void DetachFromSession();
1032 
1033   v8::Local<v8::Function> callback() const;
1034 
1035  private:
1036   BaseObjectWeakPtr<Http2Session> session_;
1037   v8::Global<v8::Function> callback_;
1038   uint64_t startTime_;
1039 };
1040 
1041 // The Http2Settings class is used to parse the settings passed in for
1042 // an Http2Session, converting those into an array of nghttp2_settings_entry
1043 // structs.
1044 class Http2Settings : public AsyncWrap {
1045  public:
1046   Http2Settings(Http2Session* session,
1047                 v8::Local<v8::Object> obj,
1048                 v8::Local<v8::Function> callback,
1049                 uint64_t start_time = uv_hrtime());
1050 
1051   void MemoryInfo(MemoryTracker* tracker) const override;
1052   SET_MEMORY_INFO_NAME(Http2Settings)
1053   SET_SELF_SIZE(Http2Settings)
1054 
1055   void Send();
1056   void Done(bool ack);
1057 
1058   v8::Local<v8::Function> callback() const;
1059 
1060   // Returns a Buffer instance with the serialized SETTINGS payload
1061   v8::Local<v8::Value> Pack();
1062 
1063   static v8::Local<v8::Value> Pack(Http2State* state);
1064 
1065   // Resets the default values in the settings buffer
1066   static void RefreshDefaults(Http2State* http2_state);
1067 
1068   // Update the local or remote settings for the given session
1069   static void Update(Http2Session* session,
1070                      get_setting fn);
1071 
1072  private:
1073   static size_t Init(
1074       Http2State* http2_state,
1075       nghttp2_settings_entry* entries);
1076 
1077   static v8::Local<v8::Value> Pack(
1078       Environment* env,
1079       size_t count,
1080       const nghttp2_settings_entry* entries);
1081 
1082   BaseObjectWeakPtr<Http2Session> session_;
1083   v8::Global<v8::Function> callback_;
1084   uint64_t startTime_;
1085   size_t count_ = 0;
1086   nghttp2_settings_entry entries_[IDX_SETTINGS_COUNT];
1087 };
1088 
1089 class Origins {
1090  public:
1091   Origins(Environment* env,
1092           v8::Local<v8::String> origin_string,
1093           size_t origin_count);
1094   ~Origins() = default;
1095 
1096   const nghttp2_origin_entry* operator*() const {
1097     return reinterpret_cast<const nghttp2_origin_entry*>(buf_.data());
1098   }
1099 
length()1100   size_t length() const {
1101     return count_;
1102   }
1103 
1104  private:
1105   size_t count_;
1106   AllocatedBuffer buf_;
1107 };
1108 
1109 #define HTTP2_HIDDEN_CONSTANTS(V)                                              \
1110   V(NGHTTP2_HCAT_REQUEST)                                                      \
1111   V(NGHTTP2_HCAT_RESPONSE)                                                     \
1112   V(NGHTTP2_HCAT_PUSH_RESPONSE)                                                \
1113   V(NGHTTP2_HCAT_HEADERS)                                                      \
1114   V(NGHTTP2_NV_FLAG_NONE)                                                      \
1115   V(NGHTTP2_NV_FLAG_NO_INDEX)                                                  \
1116   V(NGHTTP2_ERR_DEFERRED)                                                      \
1117   V(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE)                                       \
1118   V(NGHTTP2_ERR_INVALID_ARGUMENT)                                              \
1119   V(NGHTTP2_ERR_STREAM_CLOSED)                                                 \
1120   V(NGHTTP2_ERR_NOMEM)                                                         \
1121   V(STREAM_OPTION_EMPTY_PAYLOAD)                                               \
1122   V(STREAM_OPTION_GET_TRAILERS)
1123 
1124 #define HTTP2_ERROR_CODES(V)                                                   \
1125   V(NGHTTP2_NO_ERROR)                                                          \
1126   V(NGHTTP2_PROTOCOL_ERROR)                                                    \
1127   V(NGHTTP2_INTERNAL_ERROR)                                                    \
1128   V(NGHTTP2_FLOW_CONTROL_ERROR)                                                \
1129   V(NGHTTP2_SETTINGS_TIMEOUT)                                                  \
1130   V(NGHTTP2_STREAM_CLOSED)                                                     \
1131   V(NGHTTP2_FRAME_SIZE_ERROR)                                                  \
1132   V(NGHTTP2_REFUSED_STREAM)                                                    \
1133   V(NGHTTP2_CANCEL)                                                            \
1134   V(NGHTTP2_COMPRESSION_ERROR)                                                 \
1135   V(NGHTTP2_CONNECT_ERROR)                                                     \
1136   V(NGHTTP2_ENHANCE_YOUR_CALM)                                                 \
1137   V(NGHTTP2_INADEQUATE_SECURITY)                                               \
1138   V(NGHTTP2_HTTP_1_1_REQUIRED)                                                 \
1139 
1140 #define HTTP2_CONSTANTS(V)                                                     \
1141   V(NGHTTP2_ERR_FRAME_SIZE_ERROR)                                              \
1142   V(NGHTTP2_SESSION_SERVER)                                                    \
1143   V(NGHTTP2_SESSION_CLIENT)                                                    \
1144   V(NGHTTP2_STREAM_STATE_IDLE)                                                 \
1145   V(NGHTTP2_STREAM_STATE_OPEN)                                                 \
1146   V(NGHTTP2_STREAM_STATE_RESERVED_LOCAL)                                       \
1147   V(NGHTTP2_STREAM_STATE_RESERVED_REMOTE)                                      \
1148   V(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL)                                    \
1149   V(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE)                                   \
1150   V(NGHTTP2_STREAM_STATE_CLOSED)                                               \
1151   V(NGHTTP2_FLAG_NONE)                                                         \
1152   V(NGHTTP2_FLAG_END_STREAM)                                                   \
1153   V(NGHTTP2_FLAG_END_HEADERS)                                                  \
1154   V(NGHTTP2_FLAG_ACK)                                                          \
1155   V(NGHTTP2_FLAG_PADDED)                                                       \
1156   V(NGHTTP2_FLAG_PRIORITY)                                                     \
1157   V(DEFAULT_SETTINGS_HEADER_TABLE_SIZE)                                        \
1158   V(DEFAULT_SETTINGS_ENABLE_PUSH)                                              \
1159   V(DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS)                                   \
1160   V(DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE)                                      \
1161   V(DEFAULT_SETTINGS_MAX_FRAME_SIZE)                                           \
1162   V(DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE)                                     \
1163   V(DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL)                                  \
1164   V(MAX_MAX_FRAME_SIZE)                                                        \
1165   V(MIN_MAX_FRAME_SIZE)                                                        \
1166   V(MAX_INITIAL_WINDOW_SIZE)                                                   \
1167   V(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE)                                        \
1168   V(NGHTTP2_SETTINGS_ENABLE_PUSH)                                              \
1169   V(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)                                   \
1170   V(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE)                                      \
1171   V(NGHTTP2_SETTINGS_MAX_FRAME_SIZE)                                           \
1172   V(NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE)                                     \
1173   V(NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL)                                  \
1174   V(PADDING_STRATEGY_NONE)                                                     \
1175   V(PADDING_STRATEGY_ALIGNED)                                                  \
1176   V(PADDING_STRATEGY_MAX)                                                      \
1177   V(PADDING_STRATEGY_CALLBACK)                                                 \
1178   HTTP2_ERROR_CODES(V)
1179 
1180 #define HTTP2_SETTINGS(V)                                                      \
1181   V(HEADER_TABLE_SIZE)                                                         \
1182   V(ENABLE_PUSH)                                                               \
1183   V(MAX_CONCURRENT_STREAMS)                                                    \
1184   V(INITIAL_WINDOW_SIZE)                                                       \
1185   V(MAX_FRAME_SIZE)                                                            \
1186   V(MAX_HEADER_LIST_SIZE)                                                      \
1187   V(ENABLE_CONNECT_PROTOCOL)                                                   \
1188 
1189 }  // namespace http2
1190 }  // namespace node
1191 
1192 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1193 
1194 #endif  // SRC_NODE_HTTP2_H_
1195