GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_http_parser.cc Lines: 532 590 90.2 %
Date: 2022-05-23 04:15:47 Branches: 242 326 74.2 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "node.h"
23
#include "node_buffer.h"
24
#include "util.h"
25
26
#include "async_wrap-inl.h"
27
#include "env-inl.h"
28
#include "memory_tracker-inl.h"
29
#include "stream_base-inl.h"
30
#include "v8.h"
31
#include "llhttp.h"
32
33
#include <cstdlib>  // free()
34
#include <cstring>  // strdup(), strchr()
35
36
37
// This is a binding to llhttp (https://github.com/nodejs/llhttp)
38
// The goal is to decouple sockets from parsing for more javascript-level
39
// agility. A Buffer is read from a socket and passed to parser.execute().
40
// The parser then issues callbacks with slices of the data
41
//     parser.onMessageBegin
42
//     parser.onPath
43
//     parser.onBody
44
//     ...
45
// No copying is performed when slicing the buffer, only small reference
46
// allocations.
47
48
49
namespace node {
50
namespace {  // NOLINT(build/namespaces)
51
52
using v8::Array;
53
using v8::Boolean;
54
using v8::Context;
55
using v8::EscapableHandleScope;
56
using v8::Exception;
57
using v8::Function;
58
using v8::FunctionCallbackInfo;
59
using v8::FunctionTemplate;
60
using v8::HandleScope;
61
using v8::Int32;
62
using v8::Integer;
63
using v8::Isolate;
64
using v8::Local;
65
using v8::MaybeLocal;
66
using v8::Number;
67
using v8::Object;
68
using v8::String;
69
using v8::Uint32;
70
using v8::Undefined;
71
using v8::Value;
72
73
const uint32_t kOnMessageBegin = 0;
74
const uint32_t kOnHeaders = 1;
75
const uint32_t kOnHeadersComplete = 2;
76
const uint32_t kOnBody = 3;
77
const uint32_t kOnMessageComplete = 4;
78
const uint32_t kOnExecute = 5;
79
const uint32_t kOnTimeout = 6;
80
// Any more fields than this will be flushed into JS
81
const size_t kMaxHeaderFieldsCount = 32;
82
83
const uint32_t kLenientNone = 0;
84
const uint32_t kLenientHeaders = 1 << 0;
85
const uint32_t kLenientChunkedLength = 1 << 1;
86
const uint32_t kLenientKeepAlive = 1 << 2;
87
const uint32_t kLenientAll = kLenientHeaders | kLenientChunkedLength |
88
  kLenientKeepAlive;
89
90
18812
inline bool IsOWS(char c) {
91

18812
  return c == ' ' || c == '\t';
92
}
93
94
class BindingData : public BaseObject {
95
 public:
96
1045
  BindingData(Environment* env, Local<Object> obj)
97
1045
      : BaseObject(env, obj) {}
98
99
  static constexpr FastStringKey type_name { "http_parser" };
100
101
  std::vector<char> parser_buffer;
102
  bool parser_buffer_in_use = false;
103
104
3
  void MemoryInfo(MemoryTracker* tracker) const override {
105
3
    tracker->TrackField("parser_buffer", parser_buffer);
106
3
  }
107
3
  SET_SELF_SIZE(BindingData)
108
3
  SET_MEMORY_INFO_NAME(BindingData)
109
};
110
111
// helper class for the Parser
112
struct StringPtr {
113
340626
  StringPtr() {
114
340626
    on_heap_ = false;
115
340626
    Reset();
116
340626
  }
117
118
119
674520
  ~StringPtr() {
120
337260
    Reset();
121
337260
  }
122
123
124
  // If str_ does not point to a heap string yet, this function makes it do
125
  // so. This is called at the end of each http_parser_execute() so as not
126
  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
127
15894
  void Save() {
128

15894
    if (!on_heap_ && size_ > 0) {
129
6672
      char* s = new char[size_];
130
6672
      memcpy(s, str_, size_);
131
6672
      str_ = s;
132
6672
      on_heap_ = true;
133
    }
134
15894
  }
135
136
137
764178
  void Reset() {
138
764178
    if (on_heap_) {
139
6620
      delete[] str_;
140
6620
      on_heap_ = false;
141
    }
142
143
764178
    str_ = nullptr;
144
764178
    size_ = 0;
145
764178
  }
146
147
148
55456
  void Update(const char* str, size_t size) {
149
55456
    if (str_ == nullptr) {
150
55396
      str_ = str;
151

60
    } else if (on_heap_ || str_ + size_ != str) {
152
      // Non-consecutive input, make a copy on the heap.
153
      // TODO(bnoordhuis) Use slab allocation, O(n) allocs is bad.
154
60
      char* s = new char[size_ + size];
155
60
      memcpy(s, str_, size_);
156
60
      memcpy(s + size_, str, size);
157
158
60
      if (on_heap_)
159
59
        delete[] str_;
160
      else
161
1
        on_heap_ = true;
162
163
60
      str_ = s;
164
    }
165
55456
    size_ += size;
166
55456
  }
167
168
169
55302
  Local<String> ToString(Environment* env) const {
170
55302
    if (size_ != 0)
171
55238
      return OneByteString(env->isolate(), str_, size_);
172
    else
173
128
      return String::Empty(env->isolate());
174
  }
175
176
177
  // Strip trailing OWS (SPC or HTAB) from string.
178
18814
  Local<String> ToTrimmedString(Environment* env) {
179

18814
    while (size_ > 0 && IsOWS(str_[size_ - 1])) {
180
11
      size_--;
181
    }
182
18803
    return ToString(env);
183
  }
184
185
186
  const char* str_;
187
  bool on_heap_;
188
  size_t size_;
189
};
190
191
class Parser;
192
193
struct ParserComparator {
194
  bool operator()(const Parser* lhs, const Parser* rhs) const;
195
};
196
197
class ConnectionsList : public BaseObject {
198
 public:
199
    static void New(const FunctionCallbackInfo<Value>& args);
200
201
    static void All(const FunctionCallbackInfo<Value>& args);
202
203
    static void Idle(const FunctionCallbackInfo<Value>& args);
204
205
    static void Active(const FunctionCallbackInfo<Value>& args);
206
207
    static void Expired(const FunctionCallbackInfo<Value>& args);
208
209
30483
    void Push(Parser* parser) {
210
30483
      all_connections_.insert(parser);
211
30483
    }
212
213
30468
    void Pop(Parser* parser) {
214
30468
      all_connections_.erase(parser);
215
30468
    }
216
217
16504
    void PushActive(Parser* parser) {
218
16504
      active_connections_.insert(parser);
219
16504
    }
220
221
30468
    void PopActive(Parser* parser) {
222
30468
      active_connections_.erase(parser);
223
30468
    }
224
225
    SET_NO_MEMORY_INFO()
226
    SET_MEMORY_INFO_NAME(ConnectionsList)
227
    SET_SELF_SIZE(ConnectionsList)
228
229
 private:
230
561
    ConnectionsList(Environment* env, Local<Object> object)
231
561
      : BaseObject(env, object) {
232
561
        MakeWeak();
233
561
      }
234
235
    std::set<Parser*, ParserComparator> all_connections_;
236
    std::set<Parser*, ParserComparator> active_connections_;
237
};
238
239
class Parser : public AsyncWrap, public StreamListener {
240
  friend class ConnectionsList;
241
  friend struct ParserComparator;
242
243
 public:
244
5161
  Parser(BindingData* binding_data, Local<Object> wrap)
245
5161
      : AsyncWrap(binding_data->env(), wrap),
246
        current_buffer_len_(0),
247
        current_buffer_data_(nullptr),
248

335465
        binding_data_(binding_data) {
249
5161
  }
250
251
252
  void MemoryInfo(MemoryTracker* tracker) const override {
253
    tracker->TrackField("current_buffer", current_buffer_);
254
  }
255
256
  SET_MEMORY_INFO_NAME(Parser)
257
  SET_SELF_SIZE(Parser)
258
259
17693
  int on_message_begin() {
260
    // Important: Pop from the lists BEFORE resetting the last_message_start_
261
    // otherwise std::set.erase will fail.
262
17693
    if (connectionsList_ != nullptr) {
263
14037
      connectionsList_->Pop(this);
264
14037
      connectionsList_->PopActive(this);
265
    }
266
267
17693
    num_fields_ = num_values_ = 0;
268
17693
    headers_completed_ = false;
269
17693
    last_message_start_ = uv_hrtime();
270
17693
    url_.Reset();
271
17693
    status_message_.Reset();
272
273
17693
    if (connectionsList_ != nullptr) {
274
14037
      connectionsList_->Push(this);
275
14037
      connectionsList_->PushActive(this);
276
    }
277
278
35386
    Local<Value> cb = object()->Get(env()->context(), kOnMessageBegin)
279
17693
                              .ToLocalChecked();
280
17693
    if (cb->IsFunction()) {
281
      InternalCallbackScope callback_scope(
282
        this, InternalCallbackScope::kSkipTaskQueues);
283
284
      MaybeLocal<Value> r = cb.As<Function>()->Call(
285
        env()->context(), object(), 0, nullptr);
286
287
      if (r.IsEmpty()) callback_scope.MarkAsFailed();
288
    }
289
290
17693
    return 0;
291
  }
292
293
294
14203
  int on_url(const char* at, size_t length) {
295
14203
    int rv = TrackHeader(length);
296
14203
    if (rv != 0) {
297
      return rv;
298
    }
299
300
14203
    url_.Update(at, length);
301
14203
    return 0;
302
  }
303
304
305
3482
  int on_status(const char* at, size_t length) {
306
3482
    int rv = TrackHeader(length);
307
3482
    if (rv != 0) {
308
      return rv;
309
    }
310
311
3482
    status_message_.Update(at, length);
312
3482
    return 0;
313
  }
314
315
316
18904
  int on_header_field(const char* at, size_t length) {
317
18904
    int rv = TrackHeader(length);
318
18904
    if (rv != 0) {
319
      return rv;
320
    }
321
322
18904
    if (num_fields_ == num_values_) {
323
      // start of new field name
324
18875
      num_fields_++;
325
18875
      if (num_fields_ == kMaxHeaderFieldsCount) {
326
        // ran out of space - flush to javascript land
327
47
        Flush();
328
47
        num_fields_ = 1;
329
47
        num_values_ = 0;
330
      }
331
18875
      fields_[num_fields_ - 1].Reset();
332
    }
333
334
18904
    CHECK_LT(num_fields_, kMaxHeaderFieldsCount);
335
18904
    CHECK_EQ(num_fields_, num_values_ + 1);
336
337
18904
    fields_[num_fields_ - 1].Update(at, length);
338
339
18904
    return 0;
340
  }
341
342
343
18884
  int on_header_value(const char* at, size_t length) {
344
18884
    int rv = TrackHeader(length);
345
18884
    if (rv != 0) {
346
17
      return rv;
347
    }
348
349
18867
    if (num_values_ != num_fields_) {
350
      // start of new header value
351
18844
      num_values_++;
352
18844
      values_[num_values_ - 1].Reset();
353
    }
354
355
18867
    CHECK_LT(num_values_, arraysize(values_));
356
18867
    CHECK_EQ(num_values_, num_fields_);
357
358
18867
    values_[num_values_ - 1].Update(at, length);
359
360
18867
    return 0;
361
  }
362
363
364
17637
  int on_headers_complete() {
365
17637
    headers_completed_ = true;
366
17637
    header_nread_ = 0;
367
368
    // Arguments for the on-headers-complete javascript callback. This
369
    // list needs to be kept in sync with the actual argument list for
370
    // `parserOnHeadersComplete` in lib/_http_common.js.
371
    enum on_headers_complete_arg_index {
372
      A_VERSION_MAJOR = 0,
373
      A_VERSION_MINOR,
374
      A_HEADERS,
375
      A_METHOD,
376
      A_URL,
377
      A_STATUS_CODE,
378
      A_STATUS_MESSAGE,
379
      A_UPGRADE,
380
      A_SHOULD_KEEP_ALIVE,
381
      A_MAX
382
    };
383
384
176370
    Local<Value> argv[A_MAX];
385
17637
    Local<Object> obj = object();
386
17637
    Local<Value> cb = obj->Get(env()->context(),
387
35274
                               kOnHeadersComplete).ToLocalChecked();
388
389
17637
    if (!cb->IsFunction())
390
      return 0;
391
392
17637
    Local<Value> undefined = Undefined(env()->isolate());
393
176370
    for (size_t i = 0; i < arraysize(argv); i++)
394
158733
      argv[i] = undefined;
395
396
17637
    if (have_flushed_) {
397
      // Slow case, flush remaining headers.
398
16
      Flush();
399
    } else {
400
      // Fast case, pass headers and URL to JS land.
401
17621
      argv[A_HEADERS] = CreateHeaders();
402
17621
      if (parser_.type == HTTP_REQUEST)
403
28312
        argv[A_URL] = url_.ToString(env());
404
    }
405
406
17637
    num_fields_ = 0;
407
17637
    num_values_ = 0;
408
409
    // METHOD
410
17637
    if (parser_.type == HTTP_REQUEST) {
411
28328
      argv[A_METHOD] =
412
14164
          Uint32::NewFromUnsigned(env()->isolate(), parser_.method);
413
    }
414
415
    // STATUS
416
17637
    if (parser_.type == HTTP_RESPONSE) {
417
3473
      argv[A_STATUS_CODE] =
418
3473
          Integer::New(env()->isolate(), parser_.status_code);
419
6946
      argv[A_STATUS_MESSAGE] = status_message_.ToString(env());
420
    }
421
422
    // VERSION
423
17637
    argv[A_VERSION_MAJOR] = Integer::New(env()->isolate(), parser_.http_major);
424
17637
    argv[A_VERSION_MINOR] = Integer::New(env()->isolate(), parser_.http_minor);
425
426
    bool should_keep_alive;
427
17637
    should_keep_alive = llhttp_should_keep_alive(&parser_);
428
429
17637
    argv[A_SHOULD_KEEP_ALIVE] =
430
        Boolean::New(env()->isolate(), should_keep_alive);
431
432
35274
    argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade);
433
434
    MaybeLocal<Value> head_response;
435
    {
436
      InternalCallbackScope callback_scope(
437
35272
          this, InternalCallbackScope::kSkipTaskQueues);
438
17637
      head_response = cb.As<Function>()->Call(
439
35274
          env()->context(), object(), arraysize(argv), argv);
440
17635
      if (head_response.IsEmpty()) callback_scope.MarkAsFailed();
441
    }
442
443
    int64_t val;
444
445
52889
    if (head_response.IsEmpty() || !head_response.ToLocalChecked()
446
35262
                                        ->IntegerValue(env()->context())
447
17627
                                        .To(&val)) {
448
8
      got_exception_ = true;
449
8
      return -1;
450
    }
451
452
17627
    return static_cast<int>(val);
453
  }
454
455
456
11464
  int on_body(const char* at, size_t length) {
457
11464
    EscapableHandleScope scope(env()->isolate());
458
459
11464
    Local<Object> obj = object();
460
22928
    Local<Value> cb = obj->Get(env()->context(), kOnBody).ToLocalChecked();
461
462
11464
    if (!cb->IsFunction())
463
      return 0;
464
465
    // We came from consumed stream
466
11464
    if (current_buffer_.IsEmpty()) {
467
      // Make sure Buffer will be in parent HandleScope
468
538
      current_buffer_ = scope.Escape(Buffer::Copy(
469
          env()->isolate(),
470
          current_buffer_data_,
471
1076
          current_buffer_len_).ToLocalChecked());
472
    }
473
474
    Local<Value> argv[3] = {
475
        current_buffer_,
476
        Integer::NewFromUnsigned(
477
11464
            env()->isolate(), static_cast<uint32_t>(at - current_buffer_data_)),
478
22928
        Integer::NewFromUnsigned(env()->isolate(), length)};
479
480
    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
481
11464
                                       arraysize(argv),
482
22928
                                       argv);
483
484
11464
    if (r.IsEmpty()) {
485
      got_exception_ = true;
486
      llhttp_set_error_reason(&parser_, "HPE_JS_EXCEPTION:JS Exception");
487
      return HPE_USER;
488
    }
489
490
11464
    return 0;
491
  }
492
493
494
16427
  int on_message_complete() {
495
32854
    HandleScope scope(env()->isolate());
496
497
    // Important: Pop from the lists BEFORE resetting the last_message_start_
498
    // otherwise std::set.erase will fail.
499
16427
    if (connectionsList_ != nullptr) {
500
13979
      connectionsList_->Pop(this);
501
13979
      connectionsList_->PopActive(this);
502
    }
503
504
16427
    last_message_start_ = 0;
505
506
16427
    if (connectionsList_ != nullptr) {
507
13979
      connectionsList_->Push(this);
508
    }
509
510
16427
    if (num_fields_)
511
4
      Flush();  // Flush trailing HTTP headers.
512
513
16427
    Local<Object> obj = object();
514
16427
    Local<Value> cb = obj->Get(env()->context(),
515
32854
                               kOnMessageComplete).ToLocalChecked();
516
517
16427
    if (!cb->IsFunction())
518
2
      return 0;
519
520
    MaybeLocal<Value> r;
521
    {
522
      InternalCallbackScope callback_scope(
523
32850
          this, InternalCallbackScope::kSkipTaskQueues);
524
32850
      r = cb.As<Function>()->Call(env()->context(), object(), 0, nullptr);
525
16425
      if (r.IsEmpty()) callback_scope.MarkAsFailed();
526
    }
527
528
16425
    if (r.IsEmpty()) {
529
      got_exception_ = true;
530
      return -1;
531
    }
532
533
16425
    return 0;
534
  }
535
536
  // Reset nread for the next chunk
537
11646
  int on_chunk_header() {
538
11646
    header_nread_ = 0;
539
11646
    return 0;
540
  }
541
542
543
  // Reset nread for the next chunk
544
11492
  int on_chunk_complete() {
545
11492
    header_nread_ = 0;
546
11492
    return 0;
547
  }
548
549
5161
  static void New(const FunctionCallbackInfo<Value>& args) {
550
5161
    BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
551
5161
    new Parser(binding_data, args.This());
552
5161
  }
553
554
555
3
  static void Close(const FunctionCallbackInfo<Value>& args) {
556
    Parser* parser;
557
3
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
558
559
3
    delete parser;
560
  }
561
562
563
6363
  static void Free(const FunctionCallbackInfo<Value>& args) {
564
    Parser* parser;
565
6363
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
566
567
6363
    if (parser->connectionsList_ != nullptr) {
568
2452
      parser->connectionsList_->Pop(parser);
569
2452
      parser->connectionsList_->PopActive(parser);
570
    }
571
572
    // Since the Parser destructor isn't going to run the destroy() callbacks
573
    // it needs to be triggered manually.
574
6363
    parser->EmitTraceEventDestroy();
575
6363
    parser->EmitDestroy();
576
  }
577
578
579
7798
  void Save() {
580
7798
    url_.Save();
581
7798
    status_message_.Save();
582
583
7980
    for (size_t i = 0; i < num_fields_; i++) {
584
182
      fields_[i].Save();
585
    }
586
587
7914
    for (size_t i = 0; i < num_values_; i++) {
588
116
      values_[i].Save();
589
    }
590
7798
  }
591
592
  // var bytesParsed = parser->execute(buffer);
593
3550
  static void Execute(const FunctionCallbackInfo<Value>& args) {
594
    Parser* parser;
595
3550
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
596
3550
    CHECK(parser->current_buffer_.IsEmpty());
597
3550
    CHECK_EQ(parser->current_buffer_len_, 0);
598
3550
    CHECK_NULL(parser->current_buffer_data_);
599
600
3550
    ArrayBufferViewContents<char> buffer(args[0]);
601
602
    // This is a hack to get the current_buffer to the callbacks with the least
603
    // amount of overhead. Nothing else will run while http_parser_execute()
604
    // runs, therefore this pointer can be set and used for the execution.
605
3550
    parser->current_buffer_ = args[0].As<Object>();
606
607
3550
    Local<Value> ret = parser->Execute(buffer.data(), buffer.length());
608
609
3549
    if (!ret.IsEmpty())
610
7092
      args.GetReturnValue().Set(ret);
611
  }
612
613
614
887
  static void Finish(const FunctionCallbackInfo<Value>& args) {
615
    Parser* parser;
616
887
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
617
618
887
    CHECK(parser->current_buffer_.IsEmpty());
619
887
    Local<Value> ret = parser->Execute(nullptr, 0);
620
621
887
    if (!ret.IsEmpty())
622
66
      args.GetReturnValue().Set(ret);
623
  }
624
625
626
6560
  static void Initialize(const FunctionCallbackInfo<Value>& args) {
627
6560
    Environment* env = Environment::GetCurrent(args);
628
629
6560
    uint64_t max_http_header_size = 0;
630
6560
    uint32_t lenient_flags = kLenientNone;
631
6560
    ConnectionsList* connectionsList = nullptr;
632
633
6560
    CHECK(args[0]->IsInt32());
634
6560
    CHECK(args[1]->IsObject());
635
636
6560
    if (args.Length() > 2) {
637
5390
      CHECK(args[2]->IsNumber());
638
5390
      max_http_header_size =
639
10780
          static_cast<uint64_t>(args[2].As<Number>()->Value());
640
    }
641
6560
    if (max_http_header_size == 0) {
642
6556
      max_http_header_size = env->options()->max_http_header_size;
643
    }
644
645
6560
    if (args.Length() > 3) {
646
5390
      CHECK(args[3]->IsInt32());
647
10780
      lenient_flags = args[3].As<Int32>()->Value();
648
    }
649
650

11498
    if (args.Length() > 4 && !args[4]->IsNullOrUndefined()) {
651
2467
      CHECK(args[4]->IsObject());
652
2467
      ASSIGN_OR_RETURN_UNWRAP(&connectionsList, args[4]);
653
    }
654
655
    llhttp_type_t type =
656
13120
        static_cast<llhttp_type_t>(args[0].As<Int32>()->Value());
657
658

6560
    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
659
    Parser* parser;
660
6560
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
661
    // Should always be called from the same context.
662
6560
    CHECK_EQ(env, parser->env());
663
664
6560
    AsyncWrap::ProviderType provider =
665
6560
        (type == HTTP_REQUEST ?
666
            AsyncWrap::PROVIDER_HTTPINCOMINGMESSAGE
667
            : AsyncWrap::PROVIDER_HTTPCLIENTREQUEST);
668
669
6560
    parser->set_provider_type(provider);
670
19680
    parser->AsyncReset(args[1].As<Object>());
671
6560
    parser->Init(type, max_http_header_size, lenient_flags);
672
673
6560
    if (connectionsList != nullptr) {
674
2467
      parser->connectionsList_ = connectionsList;
675
676
      // This protects from a DoS attack where an attacker establishes
677
      // the connection without sending any data on applications where
678
      // server.timeout is left to the default value of zero.
679
2467
      parser->last_message_start_ = uv_hrtime();
680
681
      // Important: Push into the lists AFTER setting the last_message_start_
682
      // otherwise std::set.erase will fail later.
683
2467
      parser->connectionsList_->Push(parser);
684
2467
      parser->connectionsList_->PushActive(parser);
685
    } else {
686
4093
      parser->connectionsList_ = nullptr;
687
    }
688
  }
689
690
  template <bool should_pause>
691
22
  static void Pause(const FunctionCallbackInfo<Value>& args) {
692
22
    Environment* env = Environment::GetCurrent(args);
693
    Parser* parser;
694
30
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
695
    // Should always be called from the same context.
696
22
    CHECK_EQ(env, parser->env());
697
698
22
    if (parser->execute_depth_) {
699
8
      parser->pending_pause_ = should_pause;
700
8
      return;
701
    }
702
703
    if (should_pause) {
704
8
      llhttp_pause(&parser->parser_);
705
    } else {
706
6
      llhttp_resume(&parser->parser_);
707
    }
708
  }
709
710
711
3460
  static void Consume(const FunctionCallbackInfo<Value>& args) {
712
    Parser* parser;
713
3460
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
714
3460
    CHECK(args[0]->IsObject());
715
6920
    StreamBase* stream = StreamBase::FromObject(args[0].As<Object>());
716
3460
    CHECK_NOT_NULL(stream);
717
3460
    stream->PushStreamListener(parser);
718
  }
719
720
721
3450
  static void Unconsume(const FunctionCallbackInfo<Value>& args) {
722
    Parser* parser;
723
3450
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
724
725
    // Already unconsumed
726
3450
    if (parser->stream_ == nullptr)
727
      return;
728
729
3450
    parser->stream_->RemoveStreamListener(parser);
730
  }
731
732
733
38
  static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) {
734
    Parser* parser;
735
38
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
736
737
38
    Local<Object> ret = Buffer::Copy(
738
        parser->env(),
739
        parser->current_buffer_data_,
740
76
        parser->current_buffer_len_).ToLocalChecked();
741
742
76
    args.GetReturnValue().Set(ret);
743
  }
744
745
  static void Duration(const FunctionCallbackInfo<Value>& args) {
746
    Parser* parser;
747
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
748
749
    if (parser->last_message_start_ == 0) {
750
      args.GetReturnValue().Set(0);
751
      return;
752
    }
753
754
    double duration = (uv_hrtime() - parser->last_message_start_) / 1e6;
755
    args.GetReturnValue().Set(duration);
756
  }
757
758
  static void HeadersCompleted(const FunctionCallbackInfo<Value>& args) {
759
    Parser* parser;
760
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
761
762
    args.GetReturnValue().Set(parser->headers_completed_);
763
  }
764
765
 protected:
766
  static const size_t kAllocBufferSize = 64 * 1024;
767
768
4515
  uv_buf_t OnStreamAlloc(size_t suggested_size) override {
769
    // For most types of streams, OnStreamRead will be immediately after
770
    // OnStreamAlloc, and will consume all data, so using a static buffer for
771
    // reading is more efficient. For other streams, just use Malloc() directly.
772
4515
    if (binding_data_->parser_buffer_in_use)
773
      return uv_buf_init(Malloc(suggested_size), suggested_size);
774
4515
    binding_data_->parser_buffer_in_use = true;
775
776
4515
    if (binding_data_->parser_buffer.empty())
777
355
      binding_data_->parser_buffer.resize(kAllocBufferSize);
778
779
4515
    return uv_buf_init(binding_data_->parser_buffer.data(), kAllocBufferSize);
780
  }
781
782
783
4555
  void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override {
784
4555
    HandleScope scope(env()->isolate());
785
    // Once we’re done here, either indicate that the HTTP parser buffer
786
    // is free for re-use, or free() the data if it didn’t come from there
787
    // in the first place.
788
4551
    auto on_scope_leave = OnScopeLeave([&]() {
789
4551
      if (buf.base == binding_data_->parser_buffer.data())
790
4513
        binding_data_->parser_buffer_in_use = false;
791
      else
792
38
        free(buf.base);
793
4555
    });
794
795
4555
    if (nread < 0) {
796
305
      PassReadErrorToPreviousListener(nread);
797
305
      return;
798
    }
799
800
    // Ignore, empty reads have special meaning in http parser
801
4250
    if (nread == 0)
802
      return;
803
804
4250
    current_buffer_.Clear();
805
4250
    Local<Value> ret = Execute(buf.base, nread);
806
807
    // Exception
808
4249
    if (ret.IsEmpty())
809
5
      return;
810
811
    Local<Value> cb =
812
12732
        object()->Get(env()->context(), kOnExecute).ToLocalChecked();
813
814
4244
    if (!cb->IsFunction())
815
1003
      return;
816
817
    // Hooks for GetCurrentBuffer
818
3241
    current_buffer_len_ = nread;
819
3241
    current_buffer_data_ = buf.base;
820
821
6482
    MakeCallback(cb.As<Function>(), 1, &ret);
822
823
3238
    current_buffer_len_ = 0;
824
3238
    current_buffer_data_ = nullptr;
825
  }
826
827
828
8687
  Local<Value> Execute(const char* data, size_t len) {
829
8687
    EscapableHandleScope scope(env()->isolate());
830
831
8687
    current_buffer_len_ = len;
832
8687
    current_buffer_data_ = data;
833
8687
    got_exception_ = false;
834
835
    llhttp_errno_t err;
836
837
    // Do not allow re-entering `http_parser_execute()`
838
8687
    CHECK_EQ(execute_depth_, 0);
839
840
8687
    execute_depth_++;
841
8687
    if (data == nullptr) {
842
887
      err = llhttp_finish(&parser_);
843
    } else {
844
7800
      err = llhttp_execute(&parser_, data, len);
845
7798
      Save();
846
    }
847
8685
    execute_depth_--;
848
849
    // Calculate bytes read and resume after Upgrade/CONNECT pause
850
8685
    size_t nread = len;
851
8685
    if (err != HPE_OK) {
852
436
      nread = llhttp_get_error_pos(&parser_) - data;
853
854
      // This isn't a real pause, just a way to stop parsing early.
855
436
      if (err == HPE_PAUSED_UPGRADE) {
856
100
        err = HPE_OK;
857
100
        llhttp_resume_after_upgrade(&parser_);
858
      }
859
    }
860
861
    // Apply pending pause
862
8685
    if (pending_pause_) {
863
      pending_pause_ = false;
864
      llhttp_pause(&parser_);
865
    }
866
867
    // Unassign the 'buffer_' variable
868
8685
    current_buffer_.Clear();
869
8685
    current_buffer_len_ = 0;
870
8685
    current_buffer_data_ = nullptr;
871
872
    // If there was an exception in one of the callbacks
873
8685
    if (got_exception_)
874
8
      return scope.Escape(Local<Value>());
875
876
8677
    Local<Integer> nread_obj = Integer::New(env()->isolate(), nread);
877
878
    // If there was a parse error in one of the callbacks
879
    // TODO(bnoordhuis) What if there is an error on EOF?
880

8677
    if (!parser_.upgrade && err != HPE_OK) {
881
228
      Local<Value> e = Exception::Error(env()->parse_error_string());
882
228
      Local<Object> obj = e->ToObject(env()->isolate()->GetCurrentContext())
883
228
        .ToLocalChecked();
884
228
      obj->Set(env()->context(),
885
               env()->bytes_parsed_string(),
886
456
               nread_obj).Check();
887
228
      const char* errno_reason = llhttp_get_error_reason(&parser_);
888
889
      Local<String> code;
890
      Local<String> reason;
891
228
      if (err == HPE_USER) {
892
19
        const char* colon = strchr(errno_reason, ':');
893
19
        CHECK_NOT_NULL(colon);
894
        code = OneByteString(env()->isolate(),
895
                             errno_reason,
896
19
                             static_cast<int>(colon - errno_reason));
897
19
        reason = OneByteString(env()->isolate(), colon + 1);
898
      } else {
899
209
        code = OneByteString(env()->isolate(), llhttp_errno_name(err));
900
209
        reason = OneByteString(env()->isolate(), errno_reason);
901
      }
902
903
684
      obj->Set(env()->context(), env()->code_string(), code).Check();
904
684
      obj->Set(env()->context(), env()->reason_string(), reason).Check();
905
228
      return scope.Escape(e);
906
    }
907
908
    // No return value is needed for `Finish()`
909
8449
    if (data == nullptr) {
910
854
      return scope.Escape(Local<Value>());
911
    }
912
7595
    return scope.Escape(nread_obj);
913
  }
914
915
17688
  Local<Array> CreateHeaders() {
916
    // There could be extra entries but the max size should be fixed
917
1149720
    Local<Value> headers_v[kMaxHeaderFieldsCount * 2];
918
919
36491
    for (size_t i = 0; i < num_values_; ++i) {
920
18803
      headers_v[i * 2] = fields_[i].ToString(env());
921
37606
      headers_v[i * 2 + 1] = values_[i].ToTrimmedString(env());
922
    }
923
924
17688
    return Array::New(env()->isolate(), headers_v, num_values_ * 2);
925
  }
926
927
928
  // spill headers and request path to JS land
929
67
  void Flush() {
930
67
    HandleScope scope(env()->isolate());
931
932
67
    Local<Object> obj = object();
933
134
    Local<Value> cb = obj->Get(env()->context(), kOnHeaders).ToLocalChecked();
934
935
67
    if (!cb->IsFunction())
936
      return;
937
938
    Local<Value> argv[2] = {
939
      CreateHeaders(),
940
      url_.ToString(env())
941
134
    };
942
943
    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
944
67
                                       arraysize(argv),
945
134
                                       argv);
946
947
67
    if (r.IsEmpty())
948
      got_exception_ = true;
949
950
67
    url_.Reset();
951
67
    have_flushed_ = true;
952
  }
953
954
955
6560
  void Init(llhttp_type_t type, uint64_t max_http_header_size,
956
            uint32_t lenient_flags) {
957
6560
    llhttp_init(&parser_, type, &settings);
958
959
6560
    if (lenient_flags & kLenientHeaders) {
960
5
      llhttp_set_lenient_headers(&parser_, 1);
961
    }
962
6560
    if (lenient_flags & kLenientChunkedLength) {
963
5
      llhttp_set_lenient_chunked_length(&parser_, 1);
964
    }
965
6560
    if (lenient_flags & kLenientKeepAlive) {
966
5
      llhttp_set_lenient_keep_alive(&parser_, 1);
967
    }
968
969
6560
    header_nread_ = 0;
970
6560
    url_.Reset();
971
6560
    status_message_.Reset();
972
6560
    num_fields_ = 0;
973
6560
    num_values_ = 0;
974
6560
    have_flushed_ = false;
975
6560
    got_exception_ = false;
976
6560
    headers_completed_ = false;
977
6560
    max_http_header_size_ = max_http_header_size;
978
6560
  }
979
980
981
55473
  int TrackHeader(size_t len) {
982
55473
    header_nread_ += len;
983
55473
    if (header_nread_ >= max_http_header_size_) {
984
17
      llhttp_set_error_reason(&parser_, "HPE_HEADER_OVERFLOW:Header overflow");
985
17
      return HPE_USER;
986
    }
987
55456
    return 0;
988
  }
989
990
991
141696
  int MaybePause() {
992
141696
    CHECK_NE(execute_depth_, 0);
993
994
141696
    if (!pending_pause_) {
995
141696
      return 0;
996
    }
997
998
    pending_pause_ = false;
999
    llhttp_set_error_reason(&parser_, "Paused in callback");
1000
    return HPE_PAUSED;
1001
  }
1002
1003
1004
  bool IsNotIndicativeOfMemoryLeakAtExit() const override {
1005
    // HTTP parsers are able to emit events without any GC root referring
1006
    // to them, because they receive events directly from the underlying
1007
    // libuv resource.
1008
    return true;
1009
  }
1010
1011
1012
  llhttp_t parser_;
1013
  StringPtr fields_[kMaxHeaderFieldsCount];  // header fields
1014
  StringPtr values_[kMaxHeaderFieldsCount];  // header values
1015
  StringPtr url_;
1016
  StringPtr status_message_;
1017
  size_t num_fields_;
1018
  size_t num_values_;
1019
  bool have_flushed_;
1020
  bool got_exception_;
1021
  Local<Object> current_buffer_;
1022
  size_t current_buffer_len_;
1023
  const char* current_buffer_data_;
1024
  unsigned int execute_depth_ = 0;
1025
  bool headers_completed_ = false;
1026
  bool pending_pause_ = false;
1027
  uint64_t header_nread_ = 0;
1028
  uint64_t max_http_header_size_;
1029
  uint64_t last_message_start_;
1030
  ConnectionsList* connectionsList_;
1031
1032
  BaseObjectPtr<BindingData> binding_data_;
1033
1034
  // These are helper functions for filling `http_parser_settings`, which turn
1035
  // a member function of Parser into a C-style HTTP parser callback.
1036
  template <typename Parser, Parser> struct Proxy;
1037
  template <typename Parser, typename ...Args, int (Parser::*Member)(Args...)>
1038
  struct Proxy<int (Parser::*)(Args...), Member> {
1039
283664
    static int Raw(llhttp_t* p, Args ... args) {
1040
283664
      Parser* parser = ContainerOf(&Parser::parser_, p);
1041
283664
      int rv = (parser->*Member)(std::forward<Args>(args)...);
1042
283660
      if (rv == 0) {
1043
283392
        rv = parser->MaybePause();
1044
      }
1045
283660
      return rv;
1046
    }
1047
  };
1048
1049
  typedef int (Parser::*Call)();
1050
  typedef int (Parser::*DataCall)(const char* at, size_t length);
1051
1052
  static const llhttp_settings_t settings;
1053
};
1054
1055
271203
bool ParserComparator::operator()(const Parser* lhs, const Parser* rhs) const {
1056

271203
  if (lhs->last_message_start_ == 0 && rhs->last_message_start_ == 0) {
1057
    // When both parsers are idle, guarantee strict order by
1058
    // comparing pointers as ints.
1059
55381
    return lhs < rhs;
1060
215822
  } else if (lhs->last_message_start_ == 0) {
1061
21552
    return true;
1062
194270
  } else if (rhs->last_message_start_ == 0) {
1063
7381
    return false;
1064
  }
1065
1066
186889
  return lhs->last_message_start_ < rhs->last_message_start_;
1067
}
1068
1069
561
void ConnectionsList::New(const FunctionCallbackInfo<Value>& args) {
1070
561
  Local<Context> context = args.GetIsolate()->GetCurrentContext();
1071
561
  Environment* env = Environment::GetCurrent(context);
1072
1073
561
  new ConnectionsList(env, args.This());
1074
561
}
1075
1076
4
void ConnectionsList::All(const FunctionCallbackInfo<Value>& args) {
1077
4
  Isolate* isolate = args.GetIsolate();
1078
4
  Local<Context> context = isolate->GetCurrentContext();
1079
1080
4
  Local<Array> all = Array::New(isolate);
1081
  ConnectionsList* list;
1082
1083
4
  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1084
1085
4
  uint32_t i = 0;
1086
10
  for (auto parser : list->all_connections_) {
1087
18
    if (all->Set(context, i++, parser->object()).IsNothing()) {
1088
      return;
1089
    }
1090
  }
1091
1092
8
  return args.GetReturnValue().Set(all);
1093
}
1094
1095
2
void ConnectionsList::Idle(const FunctionCallbackInfo<Value>& args) {
1096
2
  Isolate* isolate = args.GetIsolate();
1097
2
  Local<Context> context = isolate->GetCurrentContext();
1098
1099
2
  Local<Array> idle = Array::New(isolate);
1100
  ConnectionsList* list;
1101
1102
2
  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1103
1104
2
  uint32_t i = 0;
1105
6
  for (auto parser : list->all_connections_) {
1106
4
    if (parser->last_message_start_ == 0) {
1107
6
      if (idle->Set(context, i++, parser->object()).IsNothing()) {
1108
        return;
1109
      }
1110
    }
1111
  }
1112
1113
4
  return args.GetReturnValue().Set(idle);
1114
}
1115
1116
void ConnectionsList::Active(const FunctionCallbackInfo<Value>& args) {
1117
  Isolate* isolate = args.GetIsolate();
1118
  Local<Context> context = isolate->GetCurrentContext();
1119
1120
  Local<Array> active = Array::New(isolate);
1121
  ConnectionsList* list;
1122
1123
  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1124
1125
  uint32_t i = 0;
1126
  for (auto parser : list->active_connections_) {
1127
    if (active->Set(context, i++, parser->object()).IsNothing()) {
1128
      return;
1129
    }
1130
  }
1131
1132
  return args.GetReturnValue().Set(active);
1133
}
1134
1135
85
void ConnectionsList::Expired(const FunctionCallbackInfo<Value>& args) {
1136
85
  Isolate* isolate = args.GetIsolate();
1137
85
  Local<Context> context = isolate->GetCurrentContext();
1138
1139
85
  Local<Array> expired = Array::New(isolate);
1140
  ConnectionsList* list;
1141
1142
85
  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1143
85
  CHECK(args[0]->IsNumber());
1144
85
  CHECK(args[1]->IsNumber());
1145
  uint64_t headers_timeout =
1146
170
    static_cast<uint64_t>(args[0].As<Uint32>()->Value()) * 1000000;
1147
  uint64_t request_timeout =
1148
170
    static_cast<uint64_t>(args[1].As<Uint32>()->Value()) * 1000000;
1149
1150

85
  if (headers_timeout == 0 && request_timeout == 0) {
1151
    return args.GetReturnValue().Set(expired);
1152

85
  } else if (request_timeout > 0 && headers_timeout > request_timeout) {
1153
    std::swap(headers_timeout, request_timeout);
1154
  }
1155
1156
85
  const uint64_t now = uv_hrtime();
1157
85
  const uint64_t headers_deadline =
1158
85
    headers_timeout > 0 ? now - headers_timeout : 0;
1159
85
  const uint64_t request_deadline =
1160
85
    request_timeout > 0 ? now - request_timeout : 0;
1161
1162
85
  uint32_t i = 0;
1163
85
  auto iter = list->active_connections_.begin();
1164
85
  auto end = list->active_connections_.end();
1165
167
  while (iter != end) {
1166
82
    Parser* parser = *iter;
1167
82
    iter++;
1168
1169
    // Check for expiration.
1170
82
    if (
1171

82
      (!parser->headers_completed_ && headers_deadline > 0 &&
1172

82
        parser->last_message_start_ < headers_deadline) ||
1173
      (
1174
60
        request_deadline > 0 &&
1175
60
        parser->last_message_start_ < request_deadline)
1176
    ) {
1177
39
      if (expired->Set(context, i++, parser->object()).IsNothing()) {
1178
        return;
1179
      }
1180
1181
13
      list->active_connections_.erase(parser);
1182
    }
1183
  }
1184
1185
170
  return args.GetReturnValue().Set(expired);
1186
}
1187
1188
const llhttp_settings_t Parser::settings = {
1189
  Proxy<Call, &Parser::on_message_begin>::Raw,
1190
  Proxy<DataCall, &Parser::on_url>::Raw,
1191
  Proxy<DataCall, &Parser::on_status>::Raw,
1192
  Proxy<DataCall, &Parser::on_header_field>::Raw,
1193
  Proxy<DataCall, &Parser::on_header_value>::Raw,
1194
  Proxy<Call, &Parser::on_headers_complete>::Raw,
1195
  Proxy<DataCall, &Parser::on_body>::Raw,
1196
  Proxy<Call, &Parser::on_message_complete>::Raw,
1197
  Proxy<Call, &Parser::on_chunk_header>::Raw,
1198
  Proxy<Call, &Parser::on_chunk_complete>::Raw,
1199
1200
  // on_url_complete
1201
  nullptr,
1202
  // on_status_complete
1203
  nullptr,
1204
  // on_header_field_complete
1205
  nullptr,
1206
  // on_header_value_complete
1207
  nullptr,
1208
};
1209
1210
1211
1045
void InitializeHttpParser(Local<Object> target,
1212
                          Local<Value> unused,
1213
                          Local<Context> context,
1214
                          void* priv) {
1215
1045
  Environment* env = Environment::GetCurrent(context);
1216
  BindingData* const binding_data =
1217
1045
      env->AddBindingData<BindingData>(context, target);
1218
1045
  if (binding_data == nullptr) return;
1219
1220
1045
  Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
1221
2090
  t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount);
1222
1223
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
1224
         Integer::New(env->isolate(), HTTP_REQUEST));
1225
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
1226
         Integer::New(env->isolate(), HTTP_RESPONSE));
1227
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageBegin"),
1228
         Integer::NewFromUnsigned(env->isolate(), kOnMessageBegin));
1229
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
1230
         Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
1231
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
1232
         Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
1233
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
1234
         Integer::NewFromUnsigned(env->isolate(), kOnBody));
1235
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
1236
         Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
1237
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
1238
         Integer::NewFromUnsigned(env->isolate(), kOnExecute));
1239
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnTimeout"),
1240
         Integer::NewFromUnsigned(env->isolate(), kOnTimeout));
1241
1242
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientNone"),
1243
         Integer::NewFromUnsigned(env->isolate(), kLenientNone));
1244
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientHeaders"),
1245
         Integer::NewFromUnsigned(env->isolate(), kLenientHeaders));
1246
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientChunkedLength"),
1247
         Integer::NewFromUnsigned(env->isolate(), kLenientChunkedLength));
1248
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientKeepAlive"),
1249
         Integer::NewFromUnsigned(env->isolate(), kLenientKeepAlive));
1250
3135
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientAll"),
1251
         Integer::NewFromUnsigned(env->isolate(), kLenientAll));
1252
1253
1045
  Local<Array> methods = Array::New(env->isolate());
1254
#define V(num, name, string)                                                  \
1255
    methods->Set(env->context(),                                              \
1256
        num, FIXED_ONE_BYTE_STRING(env->isolate(), #string)).Check();
1257
72105
  HTTP_METHOD_MAP(V)
1258
#undef V
1259
1045
  target->Set(env->context(),
1260
              FIXED_ONE_BYTE_STRING(env->isolate(), "methods"),
1261
3135
              methods).Check();
1262
1263
1045
  t->Inherit(AsyncWrap::GetConstructorTemplate(env));
1264
1045
  env->SetProtoMethod(t, "close", Parser::Close);
1265
1045
  env->SetProtoMethod(t, "free", Parser::Free);
1266
1045
  env->SetProtoMethod(t, "execute", Parser::Execute);
1267
1045
  env->SetProtoMethod(t, "finish", Parser::Finish);
1268
1045
  env->SetProtoMethod(t, "initialize", Parser::Initialize);
1269
1045
  env->SetProtoMethod(t, "pause", Parser::Pause<true>);
1270
1045
  env->SetProtoMethod(t, "resume", Parser::Pause<false>);
1271
1045
  env->SetProtoMethod(t, "consume", Parser::Consume);
1272
1045
  env->SetProtoMethod(t, "unconsume", Parser::Unconsume);
1273
1045
  env->SetProtoMethod(t, "getCurrentBuffer", Parser::GetCurrentBuffer);
1274
1045
  env->SetProtoMethod(t, "duration", Parser::Duration);
1275
1045
  env->SetProtoMethod(t, "headersCompleted", Parser::HeadersCompleted);
1276
1277
1045
  env->SetConstructorFunction(target, "HTTPParser", t);
1278
1279
1045
  Local<FunctionTemplate> c = env->NewFunctionTemplate(ConnectionsList::New);
1280
1045
  c->InstanceTemplate()
1281
1045
    ->SetInternalFieldCount(ConnectionsList::kInternalFieldCount);
1282
1045
  env->SetProtoMethod(c, "all", ConnectionsList::All);
1283
1045
  env->SetProtoMethod(c, "idle", ConnectionsList::Idle);
1284
1045
  env->SetProtoMethod(c, "active", ConnectionsList::Active);
1285
1045
  env->SetProtoMethod(c, "expired", ConnectionsList::Expired);
1286
1045
  env->SetConstructorFunction(target, "ConnectionsList", c);
1287
}
1288
1289
}  // anonymous namespace
1290
}  // namespace node
1291
1292
5255
NODE_MODULE_CONTEXT_AWARE_INTERNAL(http_parser, node::InitializeHttpParser)