GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/node_http2.h Lines: 73 91 80.2 %
Date: 2017-10-21 Branches: 22 80 27.5 %

Line Branch Exec 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
#include "node_http2_core-inl.h"
7
#include "node_http2_state.h"
8
#include "stream_base-inl.h"
9
#include "string_bytes.h"
10
11
namespace node {
12
namespace http2 {
13
14
using v8::Array;
15
using v8::Context;
16
using v8::EscapableHandleScope;
17
using v8::Isolate;
18
using v8::MaybeLocal;
19
20
#define HTTP_KNOWN_METHODS(V)                                                 \
21
  V(ACL, "ACL")                                                               \
22
  V(BASELINE_CONTROL, "BASELINE-CONTROL")                                     \
23
  V(BIND, "BIND")                                                             \
24
  V(CHECKIN, "CHECKIN")                                                       \
25
  V(CHECKOUT, "CHECKOUT")                                                     \
26
  V(CONNECT, "CONNECT")                                                       \
27
  V(COPY, "COPY")                                                             \
28
  V(DELETE, "DELETE")                                                         \
29
  V(GET, "GET")                                                               \
30
  V(HEAD, "HEAD")                                                             \
31
  V(LABEL, "LABEL")                                                           \
32
  V(LINK, "LINK")                                                             \
33
  V(LOCK, "LOCK")                                                             \
34
  V(MERGE, "MERGE")                                                           \
35
  V(MKACTIVITY, "MKACTIVITY")                                                 \
36
  V(MKCALENDAR, "MKCALENDAR")                                                 \
37
  V(MKCOL, "MKCOL")                                                           \
38
  V(MKREDIRECTREF, "MKREDIRECTREF")                                           \
39
  V(MKWORKSPACE, "MKWORKSPACE")                                               \
40
  V(MOVE, "MOVE")                                                             \
41
  V(OPTIONS, "OPTIONS")                                                       \
42
  V(ORDERPATCH, "ORDERPATCH")                                                 \
43
  V(PATCH, "PATCH")                                                           \
44
  V(POST, "POST")                                                             \
45
  V(PRI, "PRI")                                                               \
46
  V(PROPFIND, "PROPFIND")                                                     \
47
  V(PROPPATCH, "PROPPATCH")                                                   \
48
  V(PUT, "PUT")                                                               \
49
  V(REBIND, "REBIND")                                                         \
50
  V(REPORT, "REPORT")                                                         \
51
  V(SEARCH, "SEARCH")                                                         \
52
  V(TRACE, "TRACE")                                                           \
53
  V(UNBIND, "UNBIND")                                                         \
54
  V(UNCHECKOUT, "UNCHECKOUT")                                                 \
55
  V(UNLINK, "UNLINK")                                                         \
56
  V(UNLOCK, "UNLOCK")                                                         \
57
  V(UPDATE, "UPDATE")                                                         \
58
  V(UPDATEREDIRECTREF, "UPDATEREDIRECTREF")                                   \
59
  V(VERSION_CONTROL, "VERSION-CONTROL")
60
61
#define HTTP_KNOWN_HEADERS(V)                                                 \
62
  V(STATUS, ":status")                                                        \
63
  V(METHOD, ":method")                                                        \
64
  V(AUTHORITY, ":authority")                                                  \
65
  V(SCHEME, ":scheme")                                                        \
66
  V(PATH, ":path")                                                            \
67
  V(ACCEPT_CHARSET, "accept-charset")                                         \
68
  V(ACCEPT_ENCODING, "accept-encoding")                                       \
69
  V(ACCEPT_LANGUAGE, "accept-language")                                       \
70
  V(ACCEPT_RANGES, "accept-ranges")                                           \
71
  V(ACCEPT, "accept")                                                         \
72
  V(ACCESS_CONTROL_ALLOW_CREDENTIALS, "access-control-allow-credentials")     \
73
  V(ACCESS_CONTROL_ALLOW_HEADERS, "access-control-allow-headers")             \
74
  V(ACCESS_CONTROL_ALLOW_METHODS, "access-control-allow-methods")             \
75
  V(ACCESS_CONTROL_ALLOW_ORIGIN, "access-control-allow-origin")               \
76
  V(ACCESS_CONTROL_EXPOSE_HEADERS, "access-control-expose-headers")           \
77
  V(ACCESS_CONTROL_MAX_AGE, "access-control-max-age")                         \
78
  V(ACCESS_CONTROL_REQUEST_HEADERS, "access-control-request-headers")         \
79
  V(ACCESS_CONTROL_REQUEST_METHOD, "access-control-request-method")           \
80
  V(AGE, "age")                                                               \
81
  V(ALLOW, "allow")                                                           \
82
  V(AUTHORIZATION, "authorization")                                           \
83
  V(CACHE_CONTROL, "cache-control")                                           \
84
  V(CONNECTION, "connection")                                                 \
85
  V(CONTENT_DISPOSITION, "content-disposition")                               \
86
  V(CONTENT_ENCODING, "content-encoding")                                     \
87
  V(CONTENT_LANGUAGE, "content-language")                                     \
88
  V(CONTENT_LENGTH, "content-length")                                         \
89
  V(CONTENT_LOCATION, "content-location")                                     \
90
  V(CONTENT_MD5, "content-md5")                                               \
91
  V(CONTENT_RANGE, "content-range")                                           \
92
  V(CONTENT_TYPE, "content-type")                                             \
93
  V(COOKIE, "cookie")                                                         \
94
  V(DATE, "date")                                                             \
95
  V(DNT, "dnt")                                                               \
96
  V(ETAG, "etag")                                                             \
97
  V(EXPECT, "expect")                                                         \
98
  V(EXPIRES, "expires")                                                       \
99
  V(FORWARDED, "forwarded")                                                   \
100
  V(FROM, "from")                                                             \
101
  V(HOST, "host")                                                             \
102
  V(IF_MATCH, "if-match")                                                     \
103
  V(IF_MODIFIED_SINCE, "if-modified-since")                                   \
104
  V(IF_NONE_MATCH, "if-none-match")                                           \
105
  V(IF_RANGE, "if-range")                                                     \
106
  V(IF_UNMODIFIED_SINCE, "if-unmodified-since")                               \
107
  V(LAST_MODIFIED, "last-modified")                                           \
108
  V(LINK, "link")                                                             \
109
  V(LOCATION, "location")                                                     \
110
  V(MAX_FORWARDS, "max-forwards")                                             \
111
  V(PREFER, "prefer")                                                         \
112
  V(PROXY_AUTHENTICATE, "proxy-authenticate")                                 \
113
  V(PROXY_AUTHORIZATION, "proxy-authorization")                               \
114
  V(RANGE, "range")                                                           \
115
  V(REFERER, "referer")                                                       \
116
  V(REFRESH, "refresh")                                                       \
117
  V(RETRY_AFTER, "retry-after")                                               \
118
  V(SERVER, "server")                                                         \
119
  V(SET_COOKIE, "set-cookie")                                                 \
120
  V(STRICT_TRANSPORT_SECURITY, "strict-transport-security")                   \
121
  V(TRAILER, "trailer")                                                       \
122
  V(TRANSFER_ENCODING, "transfer-encoding")                                   \
123
  V(TE, "te")                                                                 \
124
  V(TK, "tk")                                                                 \
125
  V(UPGRADE_INSECURE_REQUESTS, "upgrade-insecure-requests")                   \
126
  V(UPGRADE, "upgrade")                                                       \
127
  V(USER_AGENT, "user-agent")                                                 \
128
  V(VARY, "vary")                                                             \
129
  V(VIA, "via")                                                               \
130
  V(WARNING, "warning")                                                       \
131
  V(WWW_AUTHENTICATE, "www-authenticate")                                     \
132
  V(X_CONTENT_TYPE_OPTIONS, "x-content-type-options")                         \
133
  V(X_FRAME_OPTIONS, "x-frame-options")                                       \
134
  V(HTTP2_SETTINGS, "http2-settings")                                         \
135
  V(KEEP_ALIVE, "keep-alive")                                                 \
136
  V(PROXY_CONNECTION, "proxy-connection")
137
138
enum http_known_headers {
139
HTTP_KNOWN_HEADER_MIN,
140
#define V(name, value) HTTP_HEADER_##name,
141
HTTP_KNOWN_HEADERS(V)
142
#undef V
143
HTTP_KNOWN_HEADER_MAX
144
};
145
146
#define HTTP_STATUS_CODES(V)                                                  \
147
  V(CONTINUE, 100)                                                            \
148
  V(SWITCHING_PROTOCOLS, 101)                                                 \
149
  V(PROCESSING, 102)                                                          \
150
  V(OK, 200)                                                                  \
151
  V(CREATED, 201)                                                             \
152
  V(ACCEPTED, 202)                                                            \
153
  V(NON_AUTHORITATIVE_INFORMATION, 203)                                       \
154
  V(NO_CONTENT, 204)                                                          \
155
  V(RESET_CONTENT, 205)                                                       \
156
  V(PARTIAL_CONTENT, 206)                                                     \
157
  V(MULTI_STATUS, 207)                                                        \
158
  V(ALREADY_REPORTED, 208)                                                    \
159
  V(IM_USED, 226)                                                             \
160
  V(MULTIPLE_CHOICES, 300)                                                    \
161
  V(MOVED_PERMANENTLY, 301)                                                   \
162
  V(FOUND, 302)                                                               \
163
  V(SEE_OTHER, 303)                                                           \
164
  V(NOT_MODIFIED, 304)                                                        \
165
  V(USE_PROXY, 305)                                                           \
166
  V(TEMPORARY_REDIRECT, 307)                                                  \
167
  V(PERMANENT_REDIRECT, 308)                                                  \
168
  V(BAD_REQUEST, 400)                                                         \
169
  V(UNAUTHORIZED, 401)                                                        \
170
  V(PAYMENT_REQUIRED, 402)                                                    \
171
  V(FORBIDDEN, 403)                                                           \
172
  V(NOT_FOUND, 404)                                                           \
173
  V(METHOD_NOT_ALLOWED, 405)                                                  \
174
  V(NOT_ACCEPTABLE, 406)                                                      \
175
  V(PROXY_AUTHENTICATION_REQUIRED, 407)                                       \
176
  V(REQUEST_TIMEOUT, 408)                                                     \
177
  V(CONFLICT, 409)                                                            \
178
  V(GONE, 410)                                                                \
179
  V(LENGTH_REQUIRED, 411)                                                     \
180
  V(PRECONDITION_FAILED, 412)                                                 \
181
  V(PAYLOAD_TOO_LARGE, 413)                                                   \
182
  V(URI_TOO_LONG, 414)                                                        \
183
  V(UNSUPPORTED_MEDIA_TYPE, 415)                                              \
184
  V(RANGE_NOT_SATISFIABLE, 416)                                               \
185
  V(EXPECTATION_FAILED, 417)                                                  \
186
  V(TEAPOT, 418)                                                              \
187
  V(MISDIRECTED_REQUEST, 421)                                                 \
188
  V(UNPROCESSABLE_ENTITY, 422)                                                \
189
  V(LOCKED, 423)                                                              \
190
  V(FAILED_DEPENDENCY, 424)                                                   \
191
  V(UNORDERED_COLLECTION, 425)                                                \
192
  V(UPGRADE_REQUIRED, 426)                                                    \
193
  V(PRECONDITION_REQUIRED, 428)                                               \
194
  V(TOO_MANY_REQUESTS, 429)                                                   \
195
  V(REQUEST_HEADER_FIELDS_TOO_LARGE, 431)                                     \
196
  V(UNAVAILABLE_FOR_LEGAL_REASONS, 451)                                       \
197
  V(INTERNAL_SERVER_ERROR, 500)                                               \
198
  V(NOT_IMPLEMENTED, 501)                                                     \
199
  V(BAD_GATEWAY, 502)                                                         \
200
  V(SERVICE_UNAVAILABLE, 503)                                                 \
201
  V(GATEWAY_TIMEOUT, 504)                                                     \
202
  V(HTTP_VERSION_NOT_SUPPORTED, 505)                                          \
203
  V(VARIANT_ALSO_NEGOTIATES, 506)                                             \
204
  V(INSUFFICIENT_STORAGE, 507)                                                \
205
  V(LOOP_DETECTED, 508)                                                       \
206
  V(BANDWIDTH_LIMIT_EXCEEDED, 509)                                            \
207
  V(NOT_EXTENDED, 510)                                                        \
208
  V(NETWORK_AUTHENTICATION_REQUIRED, 511)
209
210
enum http_status_codes {
211
#define V(name, code) HTTP_STATUS_##name = code,
212
HTTP_STATUS_CODES(V)
213
#undef V
214
};
215
216
enum padding_strategy_type {
217
  // No padding strategy
218
  PADDING_STRATEGY_NONE,
219
  // Padding will ensure all data frames are maxFrameSize
220
  PADDING_STRATEGY_MAX,
221
  // Padding will be determined via JS callback
222
  PADDING_STRATEGY_CALLBACK
223
};
224
225
#define NGHTTP2_ERROR_CODES(V)                                                 \
226
  V(NGHTTP2_ERR_INVALID_ARGUMENT)                                              \
227
  V(NGHTTP2_ERR_BUFFER_ERROR)                                                  \
228
  V(NGHTTP2_ERR_UNSUPPORTED_VERSION)                                           \
229
  V(NGHTTP2_ERR_WOULDBLOCK)                                                    \
230
  V(NGHTTP2_ERR_PROTO)                                                         \
231
  V(NGHTTP2_ERR_INVALID_FRAME)                                                 \
232
  V(NGHTTP2_ERR_EOF)                                                           \
233
  V(NGHTTP2_ERR_DEFERRED)                                                      \
234
  V(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE)                                       \
235
  V(NGHTTP2_ERR_STREAM_CLOSED)                                                 \
236
  V(NGHTTP2_ERR_STREAM_CLOSING)                                                \
237
  V(NGHTTP2_ERR_STREAM_SHUT_WR)                                                \
238
  V(NGHTTP2_ERR_INVALID_STREAM_ID)                                             \
239
  V(NGHTTP2_ERR_INVALID_STREAM_STATE)                                          \
240
  V(NGHTTP2_ERR_DEFERRED_DATA_EXIST)                                           \
241
  V(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED)                                      \
242
  V(NGHTTP2_ERR_GOAWAY_ALREADY_SENT)                                           \
243
  V(NGHTTP2_ERR_INVALID_HEADER_BLOCK)                                          \
244
  V(NGHTTP2_ERR_INVALID_STATE)                                                 \
245
  V(NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE)                                     \
246
  V(NGHTTP2_ERR_FRAME_SIZE_ERROR)                                              \
247
  V(NGHTTP2_ERR_HEADER_COMP)                                                   \
248
  V(NGHTTP2_ERR_FLOW_CONTROL)                                                  \
249
  V(NGHTTP2_ERR_INSUFF_BUFSIZE)                                                \
250
  V(NGHTTP2_ERR_PAUSE)                                                         \
251
  V(NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS)                                    \
252
  V(NGHTTP2_ERR_PUSH_DISABLED)                                                 \
253
  V(NGHTTP2_ERR_DATA_EXIST)                                                    \
254
  V(NGHTTP2_ERR_SESSION_CLOSING)                                               \
255
  V(NGHTTP2_ERR_HTTP_HEADER)                                                   \
256
  V(NGHTTP2_ERR_HTTP_MESSAGING)                                                \
257
  V(NGHTTP2_ERR_REFUSED_STREAM)                                                \
258
  V(NGHTTP2_ERR_INTERNAL)                                                      \
259
  V(NGHTTP2_ERR_CANCEL)                                                        \
260
  V(NGHTTP2_ERR_FATAL)                                                         \
261
  V(NGHTTP2_ERR_NOMEM)                                                         \
262
  V(NGHTTP2_ERR_CALLBACK_FAILURE)                                              \
263
  V(NGHTTP2_ERR_BAD_CLIENT_MAGIC)                                              \
264
  V(NGHTTP2_ERR_FLOODED)
265
266
const char* nghttp2_errname(int rv) {
267
  switch (rv) {
268
#define V(code) case code: return #code;
269
  NGHTTP2_ERROR_CODES(V)
270
#undef V
271
    default:
272
      return "NGHTTP2_UNKNOWN_ERROR";
273
  }
274
}
275
276
#define DEFAULT_SETTINGS_HEADER_TABLE_SIZE 4096
277
#define DEFAULT_SETTINGS_ENABLE_PUSH 1
278
#define DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE 65535
279
#define DEFAULT_SETTINGS_MAX_FRAME_SIZE 16384
280
#define MAX_MAX_FRAME_SIZE 16777215
281
#define MIN_MAX_FRAME_SIZE DEFAULT_SETTINGS_MAX_FRAME_SIZE
282
#define MAX_INITIAL_WINDOW_SIZE 2147483647
283
284
class Http2Options {
285
 public:
286
  explicit Http2Options(Environment* env);
287
288
467
  ~Http2Options() {
289
467
    nghttp2_option_del(options_);
290
467
  }
291
292
467
  nghttp2_option* operator*() const {
293
467
    return options_;
294
  }
295
296
2
  void SetPaddingStrategy(padding_strategy_type val) {
297
2
    CHECK_LE(val, PADDING_STRATEGY_CALLBACK);
298
2
    padding_strategy_ = static_cast<padding_strategy_type>(val);
299
2
  }
300
301
467
  padding_strategy_type GetPaddingStrategy() {
302
467
    return padding_strategy_;
303
  }
304
305
 private:
306
  nghttp2_option* options_;
307
  padding_strategy_type padding_strategy_ = PADDING_STRATEGY_NONE;
308
};
309
310
static const size_t kAllocBufferSize = 64 * 1024;
311
312
////
313
typedef uint32_t(*get_setting)(nghttp2_session* session,
314
                               nghttp2_settings_id id);
315
316
class Http2Session : public AsyncWrap,
317
                     public StreamBase,
318
                     public Nghttp2Session {
319
 public:
320
467
  Http2Session(Environment* env,
321
               Local<Object> wrap,
322
               nghttp2_session_type type) :
323
               AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
324
467
               StreamBase(env) {
325
467
    Wrap(object(), this);
326
327
467
    Http2Options opts(env);
328
329
467
    padding_strategy_ = opts.GetPaddingStrategy();
330
331
467
    Init(env->event_loop(), type, *opts);
332
467
  }
333
334
934
  ~Http2Session() override {
335
934
    CHECK_EQ(false, persistent().IsEmpty());
336
467
    ClearWrap(object());
337
467
    persistent().Reset();
338
934
    CHECK_EQ(true, persistent().IsEmpty());
339
467
  }
340
341
  static void OnStreamAllocImpl(size_t suggested_size,
342
                                uv_buf_t* buf,
343
                                void* ctx);
344
  static void OnStreamReadImpl(ssize_t nread,
345
                               const uv_buf_t* bufs,
346
                               uv_handle_type pending,
347
                               void* ctx);
348
 protected:
349
  void OnFreeSession() override;
350
351
  ssize_t OnMaxFrameSizePadding(size_t frameLength,
352
                                size_t maxPayloadLen);
353
354
  ssize_t OnCallbackPadding(size_t frame,
355
                            size_t maxPayloadLen);
356
357
470
  bool HasGetPaddingCallback() override {
358

940
    return padding_strategy_ == PADDING_STRATEGY_MAX ||
359
940
           padding_strategy_ == PADDING_STRATEGY_CALLBACK;
360
  }
361
362
3
  ssize_t GetPadding(size_t frameLength, size_t maxPayloadLen) override {
363
3
    if (padding_strategy_ == PADDING_STRATEGY_MAX) {
364
      return OnMaxFrameSizePadding(frameLength, maxPayloadLen);
365
    }
366
367
3
    CHECK_EQ(padding_strategy_, PADDING_STRATEGY_CALLBACK);
368
369
3
    return OnCallbackPadding(frameLength, maxPayloadLen);
370
  }
371
372
  void OnHeaders(Nghttp2Stream* stream,
373
                 nghttp2_header_list* headers,
374
                 nghttp2_headers_category cat,
375
                 uint8_t flags) override;
376
  void OnStreamClose(int32_t id, uint32_t code) override;
377
  void Send(uv_buf_t* bufs, size_t total) override;
378
  void OnDataChunk(Nghttp2Stream* stream, nghttp2_data_chunk_t* chunk) override;
379
  void OnSettings(bool ack) override;
380
  void OnPriority(int32_t stream,
381
                  int32_t parent,
382
                  int32_t weight,
383
                  int8_t exclusive) override;
384
  void OnGoAway(int32_t lastStreamID,
385
                uint32_t errorCode,
386
                uint8_t* data,
387
                size_t length) override;
388
  void OnFrameError(int32_t id, uint8_t type, int error_code) override;
389
  void OnTrailers(Nghttp2Stream* stream,
390
                  const SubmitTrailers& submit_trailers) override;
391
  void AllocateSend(size_t recommended, uv_buf_t* buf) override;
392
393
  int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count,
394
              uv_stream_t* send_handle) override;
395
396
6236
  AsyncWrap* GetAsyncWrap() override {
397
6236
    return static_cast<AsyncWrap*>(this);
398
  }
399
400
  void* Cast() override {
401
    return reinterpret_cast<void*>(this);
402
  }
403
404
  // Required for StreamBase
405
1937
  bool IsAlive() override {
406
1937
    return true;
407
  }
408
409
  // Required for StreamBase
410
  bool IsClosing() override {
411
    return false;
412
  }
413
414
  // Required for StreamBase
415
  int ReadStart() override { return 0; }
416
417
  // Required for StreamBase
418
  int ReadStop() override { return 0; }
419
420
  // Required for StreamBase
421
  int DoShutdown(ShutdownWrap* req_wrap) override {
422
    return 0;
423
  }
424
425
 public:
426
  void Consume(Local<External> external);
427
  void Unconsume();
428
429
  static void New(const FunctionCallbackInfo<Value>& args);
430
  static void Consume(const FunctionCallbackInfo<Value>& args);
431
  static void Unconsume(const FunctionCallbackInfo<Value>& args);
432
  static void Destroying(const FunctionCallbackInfo<Value>& args);
433
  static void Destroy(const FunctionCallbackInfo<Value>& args);
434
  static void SubmitSettings(const FunctionCallbackInfo<Value>& args);
435
  static void SubmitRstStream(const FunctionCallbackInfo<Value>& args);
436
  static void SubmitResponse(const FunctionCallbackInfo<Value>& args);
437
  static void SubmitFile(const FunctionCallbackInfo<Value>& args);
438
  static void SubmitRequest(const FunctionCallbackInfo<Value>& args);
439
  static void SubmitPushPromise(const FunctionCallbackInfo<Value>& args);
440
  static void SubmitPriority(const FunctionCallbackInfo<Value>& args);
441
  static void SendHeaders(const FunctionCallbackInfo<Value>& args);
442
  static void ShutdownStream(const FunctionCallbackInfo<Value>& args);
443
  static void StreamWrite(const FunctionCallbackInfo<Value>& args);
444
  static void StreamReadStart(const FunctionCallbackInfo<Value>& args);
445
  static void StreamReadStop(const FunctionCallbackInfo<Value>& args);
446
  static void SetNextStreamID(const FunctionCallbackInfo<Value>& args);
447
  static void SendShutdownNotice(const FunctionCallbackInfo<Value>& args);
448
  static void SubmitGoaway(const FunctionCallbackInfo<Value>& args);
449
  static void DestroyStream(const FunctionCallbackInfo<Value>& args);
450
451
  template <get_setting fn>
452
  static void GetSettings(const FunctionCallbackInfo<Value>& args);
453
454
  size_t self_size() const override {
455
    return sizeof(*this);
456
  }
457
458
3459
  char* stream_alloc() {
459
3459
    return stream_buf_;
460
  }
461
462
 private:
463
  StreamBase* stream_;
464
  StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_;
465
  StreamResource::Callback<StreamResource::ReadCb> prev_read_cb_;
466
  padding_strategy_type padding_strategy_ = PADDING_STRATEGY_NONE;
467
468
  char stream_buf_[kAllocBufferSize];
469
};
470
471
class ExternalHeader :
472
    public String::ExternalOneByteStringResource {
473
 public:
474
1254
  explicit ExternalHeader(nghttp2_rcbuf* buf)
475
1254
     : buf_(buf), vec_(nghttp2_rcbuf_get_buf(buf)) {
476
1254
  }
477
478
3762
  ~ExternalHeader() override {
479
1254
    nghttp2_rcbuf_decref(buf_);
480
1254
    buf_ = nullptr;
481
2508
  }
482
483
2612
  const char* data() const override {
484
2612
    return const_cast<const char*>(reinterpret_cast<char*>(vec_.base));
485
  }
486
487
3762
  size_t length() const override {
488
3762
    return vec_.len;
489
  }
490
491
  static inline
492
1165
  MaybeLocal<String> GetInternalizedString(Environment* env,
493
                                           const nghttp2_vec& vec) {
494
    return String::NewFromOneByte(env->isolate(),
495
                                  vec.base,
496
                                  v8::NewStringType::kInternalized,
497
1165
                                  vec.len);
498
  }
499
500
  template<bool may_internalize>
501
5548
  static MaybeLocal<String> New(Environment* env, nghttp2_rcbuf* buf) {
502

5548
    if (nghttp2_rcbuf_is_static(buf)) {
503
4249
      auto& static_str_map = env->isolate_data()->http2_static_strs;
504
4249
      v8::Eternal<v8::String>& eternal = static_str_map[buf];
505

4249
      if (eternal.IsEmpty()) {
506
        Local<String> str =
507
2240
            GetInternalizedString(env, nghttp2_rcbuf_get_buf(buf))
508
2240
                .ToLocalChecked();
509
1120
        eternal.Set(env->isolate(), str);
510
1120
        return str;
511
      }
512
6258
      return eternal.Get(env->isolate());
513
    }
514
515
1299
    nghttp2_vec vec = nghttp2_rcbuf_get_buf(buf);
516

1299
    if (vec.len == 0) {
517
      nghttp2_rcbuf_decref(buf);
518
      return String::Empty(env->isolate());
519
    }
520
521
45
    if (may_internalize && vec.len < 64) {
522
      // This is a short header name, so there is a good chance V8 already has
523
      // it internalized.
524
45
      return GetInternalizedString(env, vec);
525
    }
526
527
1254
    ExternalHeader* h_str = new ExternalHeader(buf);
528
1254
    MaybeLocal<String> str = String::NewExternalOneByte(env->isolate(), h_str);
529

1254
    if (str.IsEmpty())
530
      delete h_str;
531
532
1254
    return str;
533
  }
534
535
 private:
536
  nghttp2_rcbuf* buf_;
537
  nghttp2_vec vec_;
538
};
539
540
class Headers {
541
 public:
542
  Headers(Isolate* isolate, Local<Context> context, Local<Array> headers);
543
898
  ~Headers() {}
544
545
898
  nghttp2_nv* operator*() {
546
898
    return reinterpret_cast<nghttp2_nv*>(*buf_);
547
  }
548
549
898
  size_t length() const {
550
898
    return count_;
551
  }
552
553
 private:
554
  size_t count_;
555
  MaybeStackBuffer<char, 3000> buf_;
556
};
557
558
}  // namespace http2
559
}  // namespace node
560
561
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
562
563
#endif  // SRC_NODE_HTTP2_H_