• 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     ClearHeaders();
405   }
406 
ClearHeaders()407   void ClearHeaders() {
408     current_headers_.clear();
409   }
410 
headers_count()411   size_t headers_count() const {
412     return current_headers_.size();
413   }
414 
headers_category()415   nghttp2_headers_category headers_category() const {
416     return current_headers_category_;
417   }
418 
419   void StartHeaders(nghttp2_headers_category category);
420 
421   // Required for StreamBase
IsAlive()422   bool IsAlive() override {
423     return true;
424   }
425 
426   // Required for StreamBase
IsClosing()427   bool IsClosing() override {
428     return false;
429   }
430 
GetAsyncWrap()431   AsyncWrap* GetAsyncWrap() override { return this; }
432 
433   int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count,
434               uv_stream_t* send_handle) override;
435 
436   void MemoryInfo(MemoryTracker* tracker) const override;
437   SET_MEMORY_INFO_NAME(Http2Stream)
438   SET_SELF_SIZE(Http2Stream)
439 
440   std::string diagnostic_name() const override;
441 
442   // JavaScript API
443   static void GetID(const v8::FunctionCallbackInfo<v8::Value>& args);
444   static void Destroy(const v8::FunctionCallbackInfo<v8::Value>& args);
445   static void Priority(const v8::FunctionCallbackInfo<v8::Value>& args);
446   static void PushPromise(const v8::FunctionCallbackInfo<v8::Value>& args);
447   static void RefreshState(const v8::FunctionCallbackInfo<v8::Value>& args);
448   static void Info(const v8::FunctionCallbackInfo<v8::Value>& args);
449   static void Trailers(const v8::FunctionCallbackInfo<v8::Value>& args);
450   static void Respond(const v8::FunctionCallbackInfo<v8::Value>& args);
451   static void RstStream(const v8::FunctionCallbackInfo<v8::Value>& args);
452 
453   class Provider;
454 
455   struct Statistics {
456     uint64_t start_time;
457     uint64_t end_time;
458     uint64_t first_header;     // Time first header was received
459     uint64_t first_byte;       // Time first DATA frame byte was received
460     uint64_t first_byte_sent;  // Time first DATA frame byte was sent
461     uint64_t sent_bytes;
462     uint64_t received_bytes;
463   };
464 
465   Statistics statistics_ = {};
466 
467  private:
468   Http2Stream(Http2Session* session,
469               v8::Local<v8::Object> obj,
470               int32_t id,
471               nghttp2_headers_category category,
472               int options);
473 
474   void EmitStatistics();
475 
476   BaseObjectWeakPtr<Http2Session> session_;     // The Parent HTTP/2 Session
477   int32_t id_ = 0;                              // The Stream Identifier
478   int32_t code_ = NGHTTP2_NO_ERROR;             // The RST_STREAM code (if any)
479   int flags_ = kStreamStateNone;        // Internal state flags
480 
481   uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS;
482   uint32_t max_header_length_ = DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE;
483 
484   // The Current Headers block... As headers are received for this stream,
485   // they are temporarily stored here until the OnFrameReceived is called
486   // signalling the end of the HEADERS frame
487   nghttp2_headers_category current_headers_category_ = NGHTTP2_HCAT_HEADERS;
488   uint32_t current_headers_length_ = 0;  // total number of octets
489   std::vector<Http2Header> current_headers_;
490 
491   // This keeps track of the amount of data read from the socket while the
492   // socket was in paused mode. When `ReadStart()` is called (and not before
493   // then), we tell nghttp2 that we consumed that data to get proper
494   // backpressure handling.
495   size_t inbound_consumed_data_while_paused_ = 0;
496 
497   // Outbound Data... This is the data written by the JS layer that is
498   // waiting to be written out to the socket.
499   std::queue<NgHttp2StreamWrite> queue_;
500   size_t available_outbound_length_ = 0;
501 
502   Http2StreamListener stream_listener_;
503 
504   friend class Http2Session;
505 };
506 
507 class Http2Stream::Provider {
508  public:
509   Provider(Http2Stream* stream, int options);
510   explicit Provider(int options);
511   virtual ~Provider();
512 
513   nghttp2_data_provider* operator*() {
514     return !empty_ ? &provider_ : nullptr;
515   }
516 
517   class FD;
518   class Stream;
519  protected:
520   nghttp2_data_provider provider_;
521 
522  private:
523   bool empty_ = false;
524 };
525 
526 class Http2Stream::Provider::Stream : public Http2Stream::Provider {
527  public:
528   Stream(Http2Stream* stream, int options);
529   explicit Stream(int options);
530 
531   static ssize_t OnRead(nghttp2_session* session,
532                         int32_t id,
533                         uint8_t* buf,
534                         size_t length,
535                         uint32_t* flags,
536                         nghttp2_data_source* source,
537                         void* user_data);
538 };
539 
540 struct SessionJSFields {
541   uint8_t bitfield;
542   uint8_t priority_listener_count;
543   uint8_t frame_error_listener_count;
544   uint32_t max_invalid_frames = 1000;
545   uint32_t max_rejected_streams = 100;
546 };
547 
548 // Indices for js_fields_, which serves as a way to communicate data with JS
549 // land fast. In particular, we store information about the number/presence
550 // of certain event listeners in JS, and skip calls from C++ into JS if they
551 // are missing.
552 enum SessionUint8Fields {
553   kBitfield = offsetof(SessionJSFields, bitfield),  // See below
554   kSessionPriorityListenerCount =
555       offsetof(SessionJSFields, priority_listener_count),
556   kSessionFrameErrorListenerCount =
557       offsetof(SessionJSFields, frame_error_listener_count),
558   kSessionMaxInvalidFrames = offsetof(SessionJSFields, max_invalid_frames),
559   kSessionMaxRejectedStreams = offsetof(SessionJSFields, max_rejected_streams),
560   kSessionUint8FieldCount = sizeof(SessionJSFields)
561 };
562 
563 enum SessionBitfieldFlags {
564   kSessionHasRemoteSettingsListeners,
565   kSessionRemoteSettingsIsUpToDate,
566   kSessionHasPingListeners,
567   kSessionHasAltsvcListeners
568 };
569 
570 class Http2Session : public AsyncWrap,
571                      public StreamListener,
572                      public mem::NgLibMemoryManager<Http2Session, nghttp2_mem> {
573  public:
574   Http2Session(Http2State* http2_state,
575                v8::Local<v8::Object> wrap,
576                SessionType type = NGHTTP2_SESSION_SERVER);
577   ~Http2Session() override;
578 
underlying_stream()579   StreamBase* underlying_stream() {
580     return static_cast<StreamBase*>(stream_);
581   }
582 
583   void Close(uint32_t code = NGHTTP2_NO_ERROR,
584              bool socket_closed = false);
585 
586   void Consume(v8::Local<v8::Object> stream);
587 
588   void Goaway(uint32_t code, int32_t lastStreamID,
589               const uint8_t* data, size_t len);
590 
591   void AltSvc(int32_t id,
592               uint8_t* origin,
593               size_t origin_len,
594               uint8_t* value,
595               size_t value_len);
596 
597   void Origin(const Origins& origins);
598 
599   uint8_t SendPendingData();
600 
601   // Submits a new request. If the request is a success, assigned
602   // will be a pointer to the Http2Stream instance assigned.
603   // This only works if the session is a client session.
604   Http2Stream* SubmitRequest(
605       const Http2Priority& priority,
606       const Http2Headers& headers,
607       int32_t* ret,
608       int options = 0);
609 
type()610   SessionType type() const { return session_type_; }
611 
session()612   nghttp2_session* session() const { return session_.get(); }
613 
614   nghttp2_session* operator*() { return session_.get(); }
615 
max_header_pairs()616   uint32_t max_header_pairs() const { return max_header_pairs_; }
617 
618   const char* TypeName() const;
619 
is_destroyed()620   bool is_destroyed() {
621     return (flags_ & kSessionStateClosed) || session_ == nullptr;
622   }
623 
set_destroyed()624   void set_destroyed() {
625     flags_ |= kSessionStateClosed;
626   }
627 
628 #define IS_FLAG(name, flag)                                                    \
629   bool is_##name() const { return flags_ & flag; }                             \
630   void set_##name(bool on = true) {                                            \
631     if (on)                                                                    \
632       flags_ |= flag;                                                          \
633     else                                                                       \
634       flags_ &= ~flag;                                                         \
635   }
636 
637   IS_FLAG(in_scope, kSessionStateHasScope)
638   IS_FLAG(write_scheduled, kSessionStateWriteScheduled)
639   IS_FLAG(closing, kSessionStateClosing)
640   IS_FLAG(sending, kSessionStateSending)
641   IS_FLAG(write_in_progress, kSessionStateWriteInProgress)
642   IS_FLAG(reading_stopped, kSessionStateReadingStopped)
643   IS_FLAG(receive_paused, kSessionStateReceivePaused)
644 
645 #undef IS_FLAG
646 
647   // Schedule a write if nghttp2 indicates it wants to write to the socket.
648   void MaybeScheduleWrite();
649 
650   // Stop reading if nghttp2 doesn't want to anymore.
651   void MaybeStopReading();
652 
653   // Returns pointer to the stream, or nullptr if stream does not exist
654   BaseObjectPtr<Http2Stream> FindStream(int32_t id);
655 
656   bool CanAddStream();
657 
658   // Adds a stream instance to this session
659   void AddStream(Http2Stream* stream);
660 
661   // Removes a stream instance from this session
662   BaseObjectPtr<Http2Stream> RemoveStream(int32_t id);
663 
664   // Indicates whether there currently exist outgoing buffers for this stream.
665   bool HasWritesOnSocketForStream(Http2Stream* stream);
666 
667   // Write data from stream_buf_ to the session
668   ssize_t ConsumeHTTP2Data();
669 
670   void MemoryInfo(MemoryTracker* tracker) const override;
671   SET_MEMORY_INFO_NAME(Http2Session)
672   SET_SELF_SIZE(Http2Session)
673 
674   std::string diagnostic_name() const override;
675 
676   // Schedule an RstStream for after the current write finishes.
AddPendingRstStream(int32_t stream_id)677   void AddPendingRstStream(int32_t stream_id) {
678     pending_rst_streams_.emplace_back(stream_id);
679   }
680 
has_pending_rststream(int32_t stream_id)681   bool has_pending_rststream(int32_t stream_id) {
682     return pending_rst_streams_.end() !=
683         std::find(pending_rst_streams_.begin(),
684             pending_rst_streams_.end(),
685             stream_id);
686   }
687 
688   // Handle reads/writes from the underlying network transport.
689   uv_buf_t OnStreamAlloc(size_t suggested_size) override;
690   void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override;
691   void OnStreamAfterWrite(WriteWrap* w, int status) override;
692 
693   // Implementation for mem::NgLibMemoryManager
694   void CheckAllocatedSize(size_t previous_size) const;
695   void IncreaseAllocatedSize(size_t size);
696   void DecreaseAllocatedSize(size_t size);
697 
698   // The JavaScript API
699   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
700   static void Consume(const v8::FunctionCallbackInfo<v8::Value>& args);
701   static void Receive(const v8::FunctionCallbackInfo<v8::Value>& args);
702   static void Destroy(const v8::FunctionCallbackInfo<v8::Value>& args);
703   static void Settings(const v8::FunctionCallbackInfo<v8::Value>& args);
704   static void Request(const v8::FunctionCallbackInfo<v8::Value>& args);
705   static void SetNextStreamID(const v8::FunctionCallbackInfo<v8::Value>& args);
706   static void SetLocalWindowSize(
707       const v8::FunctionCallbackInfo<v8::Value>& args);
708   static void Goaway(const v8::FunctionCallbackInfo<v8::Value>& args);
709   static void UpdateChunksSent(const v8::FunctionCallbackInfo<v8::Value>& args);
710   static void RefreshState(const v8::FunctionCallbackInfo<v8::Value>& args);
711   static void Ping(const v8::FunctionCallbackInfo<v8::Value>& args);
712   static void AltSvc(const v8::FunctionCallbackInfo<v8::Value>& args);
713   static void Origin(const v8::FunctionCallbackInfo<v8::Value>& args);
714 
715   template <get_setting fn>
716   static void RefreshSettings(const v8::FunctionCallbackInfo<v8::Value>& args);
717 
event_loop()718   uv_loop_t* event_loop() const {
719     return env()->event_loop();
720   }
721 
http2_state()722   Http2State* http2_state() const { return http2_state_.get(); }
723 
724   BaseObjectPtr<Http2Ping> PopPing();
725   bool AddPing(const uint8_t* data, v8::Local<v8::Function> callback);
726 
727   BaseObjectPtr<Http2Settings> PopSettings();
728   bool AddSettings(v8::Local<v8::Function> callback);
729 
IncrementCurrentSessionMemory(uint64_t amount)730   void IncrementCurrentSessionMemory(uint64_t amount) {
731     current_session_memory_ += amount;
732   }
733 
DecrementCurrentSessionMemory(uint64_t amount)734   void DecrementCurrentSessionMemory(uint64_t amount) {
735     DCHECK_LE(amount, current_session_memory_);
736     current_session_memory_ -= amount;
737   }
738 
739   // Tell our custom memory allocator that this rcbuf is independent of
740   // this session now, and may outlive it.
741   void StopTrackingRcbuf(nghttp2_rcbuf* buf);
742 
743   // Returns the current session memory including memory allocated by nghttp2,
744   // the current outbound storage queue, and pending writes.
current_session_memory()745   uint64_t current_session_memory() const {
746     uint64_t total = current_session_memory_ + sizeof(Http2Session);
747     total += current_nghttp2_memory_;
748     total += outgoing_storage_.size();
749     return total;
750   }
751 
752   // Return true if current_session_memory + amount is less than the max
has_available_session_memory(uint64_t amount)753   bool has_available_session_memory(uint64_t amount) const {
754     return current_session_memory() + amount <= max_session_memory_;
755   }
756 
757   struct Statistics {
758     uint64_t start_time;
759     uint64_t end_time;
760     uint64_t ping_rtt;
761     uint64_t data_sent;
762     uint64_t data_received;
763     uint32_t frame_count;
764     uint32_t frame_sent;
765     int32_t stream_count;
766     size_t max_concurrent_streams;
767     double stream_average_duration;
768   };
769 
770   Statistics statistics_ = {};
771 
772  private:
773   void EmitStatistics();
774 
775   // Frame Padding Strategies
776   ssize_t OnDWordAlignedPadding(size_t frameLength,
777                                 size_t maxPayloadLen);
778   ssize_t OnMaxFrameSizePadding(size_t frameLength,
779                                 size_t maxPayloadLen);
780 
781   // Frame Handler
782   int HandleDataFrame(const nghttp2_frame* frame);
783   void HandleGoawayFrame(const nghttp2_frame* frame);
784   void HandleHeadersFrame(const nghttp2_frame* frame);
785   void HandlePriorityFrame(const nghttp2_frame* frame);
786   void HandleSettingsFrame(const nghttp2_frame* frame);
787   void HandlePingFrame(const nghttp2_frame* frame);
788   void HandleAltSvcFrame(const nghttp2_frame* frame);
789   void HandleOriginFrame(const nghttp2_frame* frame);
790 
791   void DecrefHeaders(const nghttp2_frame* frame);
792 
793   // nghttp2 callbacks
794   static int OnBeginHeadersCallback(
795       nghttp2_session* session,
796       const nghttp2_frame* frame,
797       void* user_data);
798   static int OnHeaderCallback(
799       nghttp2_session* session,
800       const nghttp2_frame* frame,
801       nghttp2_rcbuf* name,
802       nghttp2_rcbuf* value,
803       uint8_t flags,
804       void* user_data);
805   static int OnFrameReceive(
806       nghttp2_session* session,
807       const nghttp2_frame* frame,
808       void* user_data);
809   static int OnFrameNotSent(
810       nghttp2_session* session,
811       const nghttp2_frame* frame,
812       int error_code,
813       void* user_data);
814   static int OnFrameSent(
815       nghttp2_session* session,
816       const nghttp2_frame* frame,
817       void* user_data);
818   static int OnStreamClose(
819       nghttp2_session* session,
820       int32_t id,
821       uint32_t code,
822       void* user_data);
823   static int OnInvalidHeader(
824       nghttp2_session* session,
825       const nghttp2_frame* frame,
826       nghttp2_rcbuf* name,
827       nghttp2_rcbuf* value,
828       uint8_t flags,
829       void* user_data);
830   static int OnDataChunkReceived(
831       nghttp2_session* session,
832       uint8_t flags,
833       int32_t id,
834       const uint8_t* data,
835       size_t len,
836       void* user_data);
837   static ssize_t OnSelectPadding(
838       nghttp2_session* session,
839       const nghttp2_frame* frame,
840       size_t maxPayloadLen,
841       void* user_data);
842   static int OnNghttpError(
843       nghttp2_session* session,
844       const char* message,
845       size_t len,
846       void* user_data);
847   static int OnSendData(
848       nghttp2_session* session,
849       nghttp2_frame* frame,
850       const uint8_t* framehd,
851       size_t length,
852       nghttp2_data_source* source,
853       void* user_data);
854   static int OnInvalidFrame(
855       nghttp2_session* session,
856       const nghttp2_frame* frame,
857       int lib_error_code,
858       void* user_data);
859 
860   struct Callbacks {
861     explicit Callbacks(bool kHasGetPaddingCallback);
862 
863     Nghttp2SessionCallbacksPointer callbacks;
864   };
865 
866   /* Use callback_struct_saved[kHasGetPaddingCallback ? 1 : 0] */
867   static const Callbacks callback_struct_saved[2];
868 
869   // The underlying nghttp2_session handle
870   Nghttp2SessionPointer session_;
871 
872   // JS-accessible numeric fields, as indexed by SessionUint8Fields.
873   AliasedStruct<SessionJSFields> js_fields_;
874 
875   // The session type: client or server
876   SessionType session_type_;
877 
878   // The maximum number of header pairs permitted for streams on this session
879   uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS;
880 
881   // The maximum amount of memory allocated for this session
882   uint64_t max_session_memory_ = kDefaultMaxSessionMemory;
883   uint64_t current_session_memory_ = 0;
884   // The amount of memory allocated by nghttp2 internals
885   uint64_t current_nghttp2_memory_ = 0;
886 
887   // The collection of active Http2Streams associated with this session
888   std::unordered_map<int32_t, BaseObjectPtr<Http2Stream>> streams_;
889 
890   int flags_ = kSessionStateNone;
891 
892   // The StreamBase instance being used for i/o
893   PaddingStrategy padding_strategy_ = PADDING_STRATEGY_NONE;
894 
895   // use this to allow timeout tracking during long-lasting writes
896   uint32_t chunks_sent_since_last_write_ = 0;
897 
898   uv_buf_t stream_buf_ = uv_buf_init(nullptr, 0);
899   // When processing input data, either stream_buf_ab_ or stream_buf_allocation_
900   // will be set. stream_buf_ab_ is lazily created from stream_buf_allocation_.
901   v8::Global<v8::ArrayBuffer> stream_buf_ab_;
902   AllocatedBuffer stream_buf_allocation_;
903   size_t stream_buf_offset_ = 0;
904 
905   size_t max_outstanding_pings_ = kDefaultMaxPings;
906   std::queue<BaseObjectPtr<Http2Ping>> outstanding_pings_;
907 
908   size_t max_outstanding_settings_ = kDefaultMaxSettings;
909   std::queue<BaseObjectPtr<Http2Settings>> outstanding_settings_;
910 
911   std::vector<NgHttp2StreamWrite> outgoing_buffers_;
912   std::vector<uint8_t> outgoing_storage_;
913   size_t outgoing_length_ = 0;
914   std::vector<int32_t> pending_rst_streams_;
915   // Count streams that have been rejected while being opened. Exceeding a fixed
916   // limit will result in the session being destroyed, as an indication of a
917   // misbehaving peer. This counter is reset once new streams are being
918   // accepted again.
919   uint32_t rejected_stream_count_ = 0;
920   // Also use the invalid frame count as a measure for rejecting input frames.
921   uint32_t invalid_frame_count_ = 0;
922 
923   void PushOutgoingBuffer(NgHttp2StreamWrite&& write);
924 
925   BaseObjectPtr<Http2State> http2_state_;
926 
927   void CopyDataIntoOutgoing(const uint8_t* src, size_t src_length);
928   void ClearOutgoing(int status);
929 
930   friend class Http2Scope;
931   friend class Http2StreamListener;
932 };
933 
934 class Http2SessionPerformanceEntry : public performance::PerformanceEntry {
935  public:
Http2SessionPerformanceEntry(Http2State * http2_state,const Http2Session::Statistics & stats,SessionType type)936   Http2SessionPerformanceEntry(
937       Http2State* http2_state,
938       const Http2Session::Statistics& stats,
939       SessionType type) :
940           performance::PerformanceEntry(
941               http2_state->env(), "Http2Session", "http2",
942               stats.start_time,
943               stats.end_time),
944           ping_rtt_(stats.ping_rtt),
945           data_sent_(stats.data_sent),
946           data_received_(stats.data_received),
947           frame_count_(stats.frame_count),
948           frame_sent_(stats.frame_sent),
949           stream_count_(stats.stream_count),
950           max_concurrent_streams_(stats.max_concurrent_streams),
951           stream_average_duration_(stats.stream_average_duration),
952           session_type_(type),
953           http2_state_(http2_state) { }
954 
ping_rtt()955   uint64_t ping_rtt() const { return ping_rtt_; }
data_sent()956   uint64_t data_sent() const { return data_sent_; }
data_received()957   uint64_t data_received() const { return data_received_; }
frame_count()958   uint32_t frame_count() const { return frame_count_; }
frame_sent()959   uint32_t frame_sent() const { return frame_sent_; }
stream_count()960   int32_t stream_count() const { return stream_count_; }
max_concurrent_streams()961   size_t max_concurrent_streams() const { return max_concurrent_streams_; }
stream_average_duration()962   double stream_average_duration() const { return stream_average_duration_; }
type()963   SessionType type() const { return session_type_; }
http2_state()964   Http2State* http2_state() const { return http2_state_.get(); }
965 
Notify(v8::Local<v8::Value> obj)966   void Notify(v8::Local<v8::Value> obj) {
967     performance::PerformanceEntry::Notify(env(), kind(), obj);
968   }
969 
970  private:
971   uint64_t ping_rtt_;
972   uint64_t data_sent_;
973   uint64_t data_received_;
974   uint32_t frame_count_;
975   uint32_t frame_sent_;
976   int32_t stream_count_;
977   size_t max_concurrent_streams_;
978   double stream_average_duration_;
979   SessionType session_type_;
980   BaseObjectPtr<Http2State> http2_state_;
981 };
982 
983 class Http2StreamPerformanceEntry
984     : public performance::PerformanceEntry {
985  public:
Http2StreamPerformanceEntry(Http2State * http2_state,int32_t id,const Http2Stream::Statistics & stats)986   Http2StreamPerformanceEntry(
987       Http2State* http2_state,
988       int32_t id,
989       const Http2Stream::Statistics& stats) :
990           performance::PerformanceEntry(
991               http2_state->env(), "Http2Stream", "http2",
992               stats.start_time,
993               stats.end_time),
994           id_(id),
995           first_header_(stats.first_header),
996           first_byte_(stats.first_byte),
997           first_byte_sent_(stats.first_byte_sent),
998           sent_bytes_(stats.sent_bytes),
999           received_bytes_(stats.received_bytes),
1000           http2_state_(http2_state) { }
1001 
id()1002   int32_t id() const { return id_; }
first_header()1003   uint64_t first_header() const { return first_header_; }
first_byte()1004   uint64_t first_byte() const { return first_byte_; }
first_byte_sent()1005   uint64_t first_byte_sent() const { return first_byte_sent_; }
sent_bytes()1006   uint64_t sent_bytes() const { return sent_bytes_; }
received_bytes()1007   uint64_t received_bytes() const { return received_bytes_; }
http2_state()1008   Http2State* http2_state() const { return http2_state_.get(); }
1009 
Notify(v8::Local<v8::Value> obj)1010   void Notify(v8::Local<v8::Value> obj) {
1011     performance::PerformanceEntry::Notify(env(), kind(), obj);
1012   }
1013 
1014  private:
1015   int32_t id_;
1016   uint64_t first_header_;
1017   uint64_t first_byte_;
1018   uint64_t first_byte_sent_;
1019   uint64_t sent_bytes_;
1020   uint64_t received_bytes_;
1021   BaseObjectPtr<Http2State> http2_state_;
1022 };
1023 
1024 class Http2Ping : public AsyncWrap {
1025  public:
1026   explicit Http2Ping(
1027       Http2Session* session,
1028       v8::Local<v8::Object> obj,
1029       v8::Local<v8::Function> callback);
1030 
1031   void MemoryInfo(MemoryTracker* tracker) const override;
1032   SET_MEMORY_INFO_NAME(Http2Ping)
1033   SET_SELF_SIZE(Http2Ping)
1034 
1035   void Send(const uint8_t* payload);
1036   void Done(bool ack, const uint8_t* payload = nullptr);
1037   void DetachFromSession();
1038 
1039   v8::Local<v8::Function> callback() const;
1040 
1041  private:
1042   BaseObjectWeakPtr<Http2Session> session_;
1043   v8::Global<v8::Function> callback_;
1044   uint64_t startTime_;
1045 };
1046 
1047 // The Http2Settings class is used to parse the settings passed in for
1048 // an Http2Session, converting those into an array of nghttp2_settings_entry
1049 // structs.
1050 class Http2Settings : public AsyncWrap {
1051  public:
1052   Http2Settings(Http2Session* session,
1053                 v8::Local<v8::Object> obj,
1054                 v8::Local<v8::Function> callback,
1055                 uint64_t start_time = uv_hrtime());
1056 
1057   void MemoryInfo(MemoryTracker* tracker) const override;
1058   SET_MEMORY_INFO_NAME(Http2Settings)
1059   SET_SELF_SIZE(Http2Settings)
1060 
1061   void Send();
1062   void Done(bool ack);
1063 
1064   v8::Local<v8::Function> callback() const;
1065 
1066   // Returns a Buffer instance with the serialized SETTINGS payload
1067   v8::Local<v8::Value> Pack();
1068 
1069   static v8::Local<v8::Value> Pack(Http2State* state);
1070 
1071   // Resets the default values in the settings buffer
1072   static void RefreshDefaults(Http2State* http2_state);
1073 
1074   // Update the local or remote settings for the given session
1075   static void Update(Http2Session* session,
1076                      get_setting fn);
1077 
1078  private:
1079   static size_t Init(
1080       Http2State* http2_state,
1081       nghttp2_settings_entry* entries);
1082 
1083   static v8::Local<v8::Value> Pack(
1084       Environment* env,
1085       size_t count,
1086       const nghttp2_settings_entry* entries);
1087 
1088   BaseObjectWeakPtr<Http2Session> session_;
1089   v8::Global<v8::Function> callback_;
1090   uint64_t startTime_;
1091   size_t count_ = 0;
1092   nghttp2_settings_entry entries_[IDX_SETTINGS_COUNT];
1093 };
1094 
1095 class Origins {
1096  public:
1097   Origins(Environment* env,
1098           v8::Local<v8::String> origin_string,
1099           size_t origin_count);
1100   ~Origins() = default;
1101 
1102   const nghttp2_origin_entry* operator*() const {
1103     return reinterpret_cast<const nghttp2_origin_entry*>(buf_.data());
1104   }
1105 
length()1106   size_t length() const {
1107     return count_;
1108   }
1109 
1110  private:
1111   size_t count_;
1112   AllocatedBuffer buf_;
1113 };
1114 
1115 #define HTTP2_HIDDEN_CONSTANTS(V)                                              \
1116   V(NGHTTP2_HCAT_REQUEST)                                                      \
1117   V(NGHTTP2_HCAT_RESPONSE)                                                     \
1118   V(NGHTTP2_HCAT_PUSH_RESPONSE)                                                \
1119   V(NGHTTP2_HCAT_HEADERS)                                                      \
1120   V(NGHTTP2_NV_FLAG_NONE)                                                      \
1121   V(NGHTTP2_NV_FLAG_NO_INDEX)                                                  \
1122   V(NGHTTP2_ERR_DEFERRED)                                                      \
1123   V(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE)                                       \
1124   V(NGHTTP2_ERR_INVALID_ARGUMENT)                                              \
1125   V(NGHTTP2_ERR_STREAM_CLOSED)                                                 \
1126   V(NGHTTP2_ERR_NOMEM)                                                         \
1127   V(STREAM_OPTION_EMPTY_PAYLOAD)                                               \
1128   V(STREAM_OPTION_GET_TRAILERS)
1129 
1130 #define HTTP2_ERROR_CODES(V)                                                   \
1131   V(NGHTTP2_NO_ERROR)                                                          \
1132   V(NGHTTP2_PROTOCOL_ERROR)                                                    \
1133   V(NGHTTP2_INTERNAL_ERROR)                                                    \
1134   V(NGHTTP2_FLOW_CONTROL_ERROR)                                                \
1135   V(NGHTTP2_SETTINGS_TIMEOUT)                                                  \
1136   V(NGHTTP2_STREAM_CLOSED)                                                     \
1137   V(NGHTTP2_FRAME_SIZE_ERROR)                                                  \
1138   V(NGHTTP2_REFUSED_STREAM)                                                    \
1139   V(NGHTTP2_CANCEL)                                                            \
1140   V(NGHTTP2_COMPRESSION_ERROR)                                                 \
1141   V(NGHTTP2_CONNECT_ERROR)                                                     \
1142   V(NGHTTP2_ENHANCE_YOUR_CALM)                                                 \
1143   V(NGHTTP2_INADEQUATE_SECURITY)                                               \
1144   V(NGHTTP2_HTTP_1_1_REQUIRED)                                                 \
1145 
1146 #define HTTP2_CONSTANTS(V)                                                     \
1147   V(NGHTTP2_ERR_FRAME_SIZE_ERROR)                                              \
1148   V(NGHTTP2_SESSION_SERVER)                                                    \
1149   V(NGHTTP2_SESSION_CLIENT)                                                    \
1150   V(NGHTTP2_STREAM_STATE_IDLE)                                                 \
1151   V(NGHTTP2_STREAM_STATE_OPEN)                                                 \
1152   V(NGHTTP2_STREAM_STATE_RESERVED_LOCAL)                                       \
1153   V(NGHTTP2_STREAM_STATE_RESERVED_REMOTE)                                      \
1154   V(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL)                                    \
1155   V(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE)                                   \
1156   V(NGHTTP2_STREAM_STATE_CLOSED)                                               \
1157   V(NGHTTP2_FLAG_NONE)                                                         \
1158   V(NGHTTP2_FLAG_END_STREAM)                                                   \
1159   V(NGHTTP2_FLAG_END_HEADERS)                                                  \
1160   V(NGHTTP2_FLAG_ACK)                                                          \
1161   V(NGHTTP2_FLAG_PADDED)                                                       \
1162   V(NGHTTP2_FLAG_PRIORITY)                                                     \
1163   V(DEFAULT_SETTINGS_HEADER_TABLE_SIZE)                                        \
1164   V(DEFAULT_SETTINGS_ENABLE_PUSH)                                              \
1165   V(DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS)                                   \
1166   V(DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE)                                      \
1167   V(DEFAULT_SETTINGS_MAX_FRAME_SIZE)                                           \
1168   V(DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE)                                     \
1169   V(DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL)                                  \
1170   V(MAX_MAX_FRAME_SIZE)                                                        \
1171   V(MIN_MAX_FRAME_SIZE)                                                        \
1172   V(MAX_INITIAL_WINDOW_SIZE)                                                   \
1173   V(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE)                                        \
1174   V(NGHTTP2_SETTINGS_ENABLE_PUSH)                                              \
1175   V(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)                                   \
1176   V(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE)                                      \
1177   V(NGHTTP2_SETTINGS_MAX_FRAME_SIZE)                                           \
1178   V(NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE)                                     \
1179   V(NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL)                                  \
1180   V(PADDING_STRATEGY_NONE)                                                     \
1181   V(PADDING_STRATEGY_ALIGNED)                                                  \
1182   V(PADDING_STRATEGY_MAX)                                                      \
1183   V(PADDING_STRATEGY_CALLBACK)                                                 \
1184   HTTP2_ERROR_CODES(V)
1185 
1186 #define HTTP2_SETTINGS(V)                                                      \
1187   V(HEADER_TABLE_SIZE)                                                         \
1188   V(ENABLE_PUSH)                                                               \
1189   V(MAX_CONCURRENT_STREAMS)                                                    \
1190   V(INITIAL_WINDOW_SIZE)                                                       \
1191   V(MAX_FRAME_SIZE)                                                            \
1192   V(MAX_HEADER_LIST_SIZE)                                                      \
1193   V(ENABLE_CONNECT_PROTOCOL)                                                   \
1194 
1195 }  // namespace http2
1196 }  // namespace node
1197 
1198 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1199 
1200 #endif  // SRC_NODE_HTTP2_H_
1201