Coverage Report

Created: 2025-12-10 07:58

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