GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_http_parser_impl.h Lines: 394 421 93.6 %
Date: 2019-02-13 22:28:58 Branches: 184 255 72.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
// This file is included from 2 files, node_http_parser_traditional.cc
23
// and node_http_parser_llhttp.cc.
24
25
#ifndef SRC_NODE_HTTP_PARSER_IMPL_H_
26
#define SRC_NODE_HTTP_PARSER_IMPL_H_
27
28
#include "node.h"
29
#include "node_buffer.h"
30
#include "util.h"
31
32
#include "async_wrap-inl.h"
33
#include "env-inl.h"
34
#include "stream_base-inl.h"
35
#include "util-inl.h"
36
#include "v8.h"
37
38
#include <stdlib.h>  // free()
39
#include <string.h>  // strdup(), strchr()
40
41
#include "http_parser_adaptor.h"
42
43
// This is a binding to http_parser (https://github.com/nodejs/http-parser)
44
// The goal is to decouple sockets from parsing for more javascript-level
45
// agility. A Buffer is read from a socket and passed to parser.execute().
46
// The parser then issues callbacks with slices of the data
47
//     parser.onMessageBegin
48
//     parser.onPath
49
//     parser.onBody
50
//     ...
51
// No copying is performed when slicing the buffer, only small reference
52
// allocations.
53
54
55
namespace node {
56
namespace {  // NOLINT(build/namespaces)
57
58
using v8::Array;
59
using v8::Boolean;
60
using v8::Context;
61
using v8::EscapableHandleScope;
62
using v8::Exception;
63
using v8::Function;
64
using v8::FunctionCallbackInfo;
65
using v8::FunctionTemplate;
66
using v8::HandleScope;
67
using v8::Int32;
68
using v8::Integer;
69
using v8::Local;
70
using v8::MaybeLocal;
71
using v8::Object;
72
using v8::String;
73
using v8::Uint32;
74
using v8::Undefined;
75
using v8::Value;
76
77
const uint32_t kOnHeaders = 0;
78
const uint32_t kOnHeadersComplete = 1;
79
const uint32_t kOnBody = 2;
80
const uint32_t kOnMessageComplete = 3;
81
const uint32_t kOnExecute = 4;
82
// Any more fields than this will be flushed into JS
83
const size_t kMaxHeaderFieldsCount = 32;
84
85
// helper class for the Parser
86
struct StringPtr {
87
188628
  StringPtr() {
88
188628
    on_heap_ = false;
89
188628
    Reset();
90
188628
  }
91
92
93
186186
  ~StringPtr() {
94
186186
    Reset();
95
186186
  }
96
97
98
  // If str_ does not point to a heap string yet, this function makes it do
99
  // so. This is called at the end of each http_parser_execute() so as not
100
  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
101
161364
  void Save() {
102

161364
    if (!on_heap_ && size_ > 0) {
103
74358
      char* s = new char[size_];
104
74358
      memcpy(s, str_, size_);
105
74358
      str_ = s;
106
74358
      on_heap_ = true;
107
    }
108
161364
  }
109
110
111
880328
  void Reset() {
112
880328
    if (on_heap_) {
113
74319
      delete[] str_;
114
74319
      on_heap_ = false;
115
    }
116
117
880328
    str_ = nullptr;
118
880328
    size_ = 0;
119
880328
  }
120
121
122
348439
  void Update(const char* str, size_t size) {
123
348439
    if (str_ == nullptr) {
124
348334
      str_ = str;
125

105
    } else if (on_heap_ || str_ + size_ != str) {
126
      // Non-consecutive input, make a copy on the heap.
127
      // TODO(bnoordhuis) Use slab allocation, O(n) allocs is bad.
128
105
      char* s = new char[size_ + size];
129
105
      memcpy(s, str_, size_);
130
105
      memcpy(s + size_, str, size);
131
132
105
      if (on_heap_)
133
104
        delete[] str_;
134
      else
135
1
        on_heap_ = true;
136
137
105
      str_ = s;
138
    }
139
348439
    size_ += size;
140
348439
  }
141
142
143
348286
  Local<String> ToString(Environment* env) const {
144
348286
    if (str_)
145
348223
      return OneByteString(env->isolate(), str_, size_);
146
    else
147
126
      return String::Empty(env->isolate());
148
  }
149
150
151
  const char* str_;
152
  bool on_heap_;
153
  size_t size_;
154
};
155
156
157


5642
class Parser : public AsyncWrap, public StreamListener {
158
 public:
159
2858
  Parser(Environment* env, Local<Object> wrap, parser_type_t type)
160
      : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTPPARSER),
161
        current_buffer_len_(0),
162

5716
        current_buffer_data_(nullptr) {
163
2858
    Init(type);
164
2858
  }
165
166
167
  void MemoryInfo(MemoryTracker* tracker) const override {
168
    tracker->TrackField("current_buffer", current_buffer_);
169
  }
170
171
  SET_MEMORY_INFO_NAME(Parser)
172
  SET_SELF_SIZE(Parser)
173
174
85403
  int on_message_begin() {
175
85403
    num_fields_ = num_values_ = 0;
176
85403
    url_.Reset();
177
85403
    status_message_.Reset();
178
85403
    return 0;
179
  }
180
181
182
72680
  int on_url(const char* at, size_t length) {
183
72680
    int rv = TrackHeader(length);
184
72680
    if (rv != 0) {
185
      return rv;
186
    }
187
188
72680
    url_.Update(at, length);
189
72680
    return 0;
190
  }
191
192
193
12715
  int on_status(const char* at, size_t length) {
194
12715
    int rv = TrackHeader(length);
195
12715
    if (rv != 0) {
196
      return rv;
197
    }
198
199
12715
    status_message_.Update(at, length);
200
12715
    return 0;
201
  }
202
203
204
131510
  int on_header_field(const char* at, size_t length) {
205
131510
    int rv = TrackHeader(length);
206
131510
    if (rv != 0) {
207
      return rv;
208
    }
209
210
131510
    if (num_fields_ == num_values_) {
211
      // start of new field name
212
131481
      num_fields_++;
213
131481
      if (num_fields_ == kMaxHeaderFieldsCount) {
214
        // ran out of space - flush to javascript land
215
47
        Flush();
216
47
        num_fields_ = 1;
217
47
        num_values_ = 0;
218
      }
219
131481
      fields_[num_fields_ - 1].Reset();
220
    }
221
222
131510
    CHECK_LT(num_fields_, kMaxHeaderFieldsCount);
223
131510
    CHECK_EQ(num_fields_, num_values_ + 1);
224
225
131510
    fields_[num_fields_ - 1].Update(at, length);
226
227
131510
    return 0;
228
  }
229
230
231
131542
  int on_header_value(const char* at, size_t length) {
232
131542
    int rv = TrackHeader(length);
233
131542
    if (rv != 0) {
234
8
      return rv;
235
    }
236
237
131534
    if (num_values_ != num_fields_) {
238
      // start of new header value
239
131466
      num_values_++;
240
131466
      values_[num_values_ - 1].Reset();
241
    }
242
243
131534
    CHECK_LT(num_values_, arraysize(values_));
244
131534
    CHECK_EQ(num_values_, num_fields_);
245
246
131534
    values_[num_values_ - 1].Update(at, length);
247
248
131534
    return 0;
249
  }
250
251
252
85369
  int on_headers_complete() {
253
#ifdef NODE_EXPERIMENTAL_HTTP
254
85367
    header_nread_ = 0;
255
#endif  /* NODE_EXPERIMENTAL_HTTP */
256
257
    // Arguments for the on-headers-complete javascript callback. This
258
    // list needs to be kept in sync with the actual argument list for
259
    // `parserOnHeadersComplete` in lib/_http_common.js.
260
    enum on_headers_complete_arg_index {
261
      A_VERSION_MAJOR = 0,
262
      A_VERSION_MINOR,
263
      A_HEADERS,
264
      A_METHOD,
265
      A_URL,
266
      A_STATUS_CODE,
267
      A_STATUS_MESSAGE,
268
      A_UPGRADE,
269
      A_SHOULD_KEEP_ALIVE,
270
      A_MAX
271
    };
272
273
853690
    Local<Value> argv[A_MAX];
274
85369
    Local<Object> obj = object();
275
    Local<Value> cb = obj->Get(env()->context(),
276
256107
                               kOnHeadersComplete).ToLocalChecked();
277
278
85369
    if (!cb->IsFunction())
279
      return 0;
280
281
85369
    Local<Value> undefined = Undefined(env()->isolate());
282
853690
    for (size_t i = 0; i < arraysize(argv); i++)
283
768321
      argv[i] = undefined;
284
285
85369
    if (have_flushed_) {
286
      // Slow case, flush remaining headers.
287
16
      Flush();
288
    } else {
289
      // Fast case, pass headers and URL to JS land.
290
170706
      argv[A_HEADERS] = CreateHeaders();
291
85353
      if (parser_.type == HTTP_REQUEST)
292
145298
        argv[A_URL] = url_.ToString(env());
293
    }
294
295
85369
    num_fields_ = 0;
296
85369
    num_values_ = 0;
297
298
    // METHOD
299
85369
    if (parser_.type == HTTP_REQUEST) {
300
      argv[A_METHOD] =
301
145314
          Uint32::NewFromUnsigned(env()->isolate(), parser_.method);
302
    }
303
304
    // STATUS
305
85369
    if (parser_.type == HTTP_RESPONSE) {
306
      argv[A_STATUS_CODE] =
307
25424
          Integer::New(env()->isolate(), parser_.status_code);
308
25424
      argv[A_STATUS_MESSAGE] = status_message_.ToString(env());
309
    }
310
311
    // VERSION
312
170738
    argv[A_VERSION_MAJOR] = Integer::New(env()->isolate(), parser_.http_major);
313
170738
    argv[A_VERSION_MINOR] = Integer::New(env()->isolate(), parser_.http_minor);
314
315
    bool should_keep_alive;
316
#ifdef NODE_EXPERIMENTAL_HTTP
317
85367
    should_keep_alive = llhttp_should_keep_alive(&parser_);
318
#else  /* !NODE_EXPERIMENTAL_HTTP */
319
2
    should_keep_alive = http_should_keep_alive(&parser_);
320
#endif  /* NODE_EXPERIMENTAL_HTTP */
321
322
    argv[A_SHOULD_KEEP_ALIVE] =
323
170738
        Boolean::New(env()->isolate(), should_keep_alive);
324
325
170738
    argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade);
326
327
85369
    Environment::AsyncCallbackScope callback_scope(env());
328
329
    MaybeLocal<Value> head_response =
330
170738
        MakeCallback(cb.As<Function>(), arraysize(argv), argv);
331
332
    int64_t val;
333
334

426828
    if (head_response.IsEmpty() || !head_response.ToLocalChecked()
335
426807
                                        ->IntegerValue(env()->context())
336
341447
                                        .To(&val)) {
337
7
      got_exception_ = true;
338
7
      return -1;
339
    }
340
341
85360
    return val;
342
  }
343
344
345
21962
  int on_body(const char* at, size_t length) {
346
21962
    EscapableHandleScope scope(env()->isolate());
347
348
21962
    Local<Object> obj = object();
349
65886
    Local<Value> cb = obj->Get(env()->context(), kOnBody).ToLocalChecked();
350
351
21962
    if (!cb->IsFunction())
352
      return 0;
353
354
    // We came from consumed stream
355
43924
    if (current_buffer_.IsEmpty()) {
356
      // Make sure Buffer will be in parent HandleScope
357
      current_buffer_ = scope.Escape(Buffer::Copy(
358
          env()->isolate(),
359
          current_buffer_data_,
360
5494
          current_buffer_len_).ToLocalChecked());
361
    }
362
363
    Local<Value> argv[3] = {
364
      current_buffer_,
365
21962
      Integer::NewFromUnsigned(env()->isolate(), at - current_buffer_data_),
366
      Integer::NewFromUnsigned(env()->isolate(), length)
367
109810
    };
368
369
    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
370
21962
                                       arraysize(argv),
371
43924
                                       argv);
372
373
21962
    if (r.IsEmpty()) {
374
      got_exception_ = true;
375
#ifdef NODE_EXPERIMENTAL_HTTP
376
      llhttp_set_error_reason(&parser_, "HPE_JS_EXCEPTION:JS Exception");
377
#endif  /* NODE_EXPERIMENTAL_HTTP */
378
      return HPE_USER;
379
    }
380
381
21962
    return 0;
382
  }
383
384
385
84168
  int on_message_complete() {
386
84168
    HandleScope scope(env()->isolate());
387
388
84168
    if (num_fields_)
389
4
      Flush();  // Flush trailing HTTP headers.
390
391
84168
    Local<Object> obj = object();
392
    Local<Value> cb = obj->Get(env()->context(),
393
252504
                               kOnMessageComplete).ToLocalChecked();
394
395
84168
    if (!cb->IsFunction())
396
2
      return 0;
397
398
168332
    Environment::AsyncCallbackScope callback_scope(env());
399
400
84166
    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(), 0, nullptr);
401
402
84166
    if (r.IsEmpty()) {
403
      got_exception_ = true;
404
      return -1;
405
    }
406
407
168334
    return 0;
408
  }
409
410
#ifdef NODE_EXPERIMENTAL_HTTP
411
  // Reset nread for the next chunk
412
27431
  int on_chunk_header() {
413
27431
    header_nread_ = 0;
414
27431
    return 0;
415
  }
416
417
418
  // Reset nread for the next chunk
419
27276
  int on_chunk_complete() {
420
27276
    header_nread_ = 0;
421
27276
    return 0;
422
  }
423
#endif  /* NODE_EXPERIMENTAL_HTTP */
424
425
426
2858
  static void New(const FunctionCallbackInfo<Value>& args) {
427
2858
    Environment* env = Environment::GetCurrent(args);
428
5716
    CHECK(args[0]->IsInt32());
429
    parser_type_t type =
430
8574
        static_cast<parser_type_t>(args[0].As<Int32>()->Value());
431

2858
    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
432
2858
    new Parser(env, args.This(), type);
433
2858
  }
434
435
436
3
  static void Close(const FunctionCallbackInfo<Value>& args) {
437
    Parser* parser;
438
6
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
439
440
3
    delete parser;
441
  }
442
443
444
32954
  static void Free(const FunctionCallbackInfo<Value>& args) {
445
32954
    Environment* env = Environment::GetCurrent(args);
446
    Parser* parser;
447
65908
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
448
449
    // Since the Parser destructor isn't going to run the destroy() callbacks
450
    // it needs to be triggered manually.
451
32954
    parser->EmitTraceEventDestroy();
452
32954
    parser->EmitDestroy(env, parser->get_async_id());
453
  }
454
455
456
80405
  void Save() {
457
80405
    url_.Save();
458
80405
    status_message_.Save();
459
460
80707
    for (size_t i = 0; i < num_fields_; i++) {
461
302
      fields_[i].Save();
462
    }
463
464
80657
    for (size_t i = 0; i < num_values_; i++) {
465
252
      values_[i].Save();
466
    }
467
80405
  }
468
469
470
  // var bytesParsed = parser->execute(buffer);
471
15582
  static void Execute(const FunctionCallbackInfo<Value>& args) {
472
    Parser* parser;
473
31163
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
474
31164
    CHECK(parser->current_buffer_.IsEmpty());
475
15582
    CHECK_EQ(parser->current_buffer_len_, 0);
476
15582
    CHECK_NULL(parser->current_buffer_data_);
477
15582
    CHECK_EQ(Buffer::HasInstance(args[0]), true);
478
479
31164
    Local<Object> buffer_obj = args[0].As<Object>();
480
15582
    char* buffer_data = Buffer::Data(buffer_obj);
481
15582
    size_t buffer_len = Buffer::Length(buffer_obj);
482
483
    // This is a hack to get the current_buffer to the callbacks with the least
484
    // amount of overhead. Nothing else will run while http_parser_execute()
485
    // runs, therefore this pointer can be set and used for the execution.
486
15582
    parser->current_buffer_ = buffer_obj;
487
488
15582
    Local<Value> ret = parser->Execute(buffer_data, buffer_len);
489
490
15581
    if (!ret.IsEmpty())
491
31158
      args.GetReturnValue().Set(ret);
492
  }
493
494
495
853
  static void Finish(const FunctionCallbackInfo<Value>& args) {
496
    Parser* parser;
497
1706
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
498
499
1706
    CHECK(parser->current_buffer_.IsEmpty());
500
853
    Local<Value> ret = parser->Execute(nullptr, 0);
501
502
853
    if (!ret.IsEmpty())
503
58
      args.GetReturnValue().Set(ret);
504
  }
505
506
507
32989
  static void Reinitialize(const FunctionCallbackInfo<Value>& args) {
508
32989
    Environment* env = Environment::GetCurrent(args);
509
510
65978
    CHECK(args[0]->IsInt32());
511
65978
    CHECK(args[1]->IsBoolean());
512
65978
    bool isReused = args[1]->IsTrue();
513
    parser_type_t type =
514
98967
        static_cast<parser_type_t>(args[0].As<Int32>()->Value());
515
516

32989
    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
517
    Parser* parser;
518
65978
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
519
    // Should always be called from the same context.
520
32989
    CHECK_EQ(env, parser->env());
521
    // This parser has either just been created or it is being reused.
522
    // We must only call AsyncReset for the latter case, because AsyncReset has
523
    // already been called via the constructor for the former case.
524
32989
    if (isReused) {
525
30296
      parser->AsyncReset();
526
    }
527
32989
    parser->Init(type);
528
  }
529
530
531
  template <bool should_pause>
532
11
  static void Pause(const FunctionCallbackInfo<Value>& args) {
533
11
    Environment* env = Environment::GetCurrent(args);
534
    Parser* parser;
535

15
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
536
    // Should always be called from the same context.
537

11
    CHECK_EQ(env, parser->env());
538
539
#ifdef NODE_EXPERIMENTAL_HTTP
540

11
    if (parser->execute_depth_) {
541
4
      parser->pending_pause_ = should_pause;
542
4
      return;
543
    }
544
545
    if (should_pause) {
546
4
      llhttp_pause(&parser->parser_);
547
    } else {
548
3
      llhttp_resume(&parser->parser_);
549
    }
550
#else  /* !NODE_EXPERIMENTAL_HTTP */
551
    http_parser_pause(&parser->parser_, should_pause);
552
#endif  /* NODE_EXPERIMENTAL_HTTP */
553
  }
554
555
556
20692
  static void Consume(const FunctionCallbackInfo<Value>& args) {
557
    Parser* parser;
558
41384
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
559
41384
    CHECK(args[0]->IsExternal());
560
41384
    Local<External> stream_obj = args[0].As<External>();
561
20692
    StreamBase* stream = static_cast<StreamBase*>(stream_obj->Value());
562
20692
    CHECK_NOT_NULL(stream);
563
20692
    stream->PushStreamListener(parser);
564
  }
565
566
567
20676
  static void Unconsume(const FunctionCallbackInfo<Value>& args) {
568
    Parser* parser;
569
20676
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
570
571
    // Already unconsumed
572
20676
    if (parser->stream_ == nullptr)
573
      return;
574
575
20676
    parser->stream_->RemoveStreamListener(parser);
576
  }
577
578
579
31
  static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) {
580
    Parser* parser;
581
62
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
582
583
    Local<Object> ret = Buffer::Copy(
584
        parser->env(),
585
        parser->current_buffer_data_,
586
62
        parser->current_buffer_len_).ToLocalChecked();
587
588
62
    args.GetReturnValue().Set(ret);
589
  }
590
591
 protected:
592
  static const size_t kAllocBufferSize = 64 * 1024;
593
594
65008
  uv_buf_t OnStreamAlloc(size_t suggested_size) override {
595
    // For most types of streams, OnStreamRead will be immediately after
596
    // OnStreamAlloc, and will consume all data, so using a static buffer for
597
    // reading is more efficient. For other streams, just use the default
598
    // allocator, which uses Malloc().
599
65008
    if (env()->http_parser_buffer_in_use())
600
      return StreamListener::OnStreamAlloc(suggested_size);
601
65008
    env()->set_http_parser_buffer_in_use(true);
602
603
65008
    if (env()->http_parser_buffer() == nullptr)
604
283
      env()->set_http_parser_buffer(new char[kAllocBufferSize]);
605
606
65008
    return uv_buf_init(env()->http_parser_buffer(), kAllocBufferSize);
607
  }
608
609
610
65031
  void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override {
611
65031
    HandleScope scope(env()->isolate());
612
    // Once we’re done here, either indicate that the HTTP parser buffer
613
    // is free for re-use, or free() the data if it didn’t come from there
614
    // in the first place.
615
65027
    OnScopeLeave on_scope_leave([&]() {
616
65027
      if (buf.base == env()->http_parser_buffer())
617
65005
        env()->set_http_parser_buffer_in_use(false);
618
      else
619
22
        free(buf.base);
620
193872
    });
621
622
65031
    if (nread < 0) {
623
206
      PassReadErrorToPreviousListener(nread);
624
206
      return;
625
    }
626
627
    // Ignore, empty reads have special meaning in http parser
628
64825
    if (nread == 0)
629
      return;
630
631
64825
    current_buffer_.Clear();
632
64825
    Local<Value> ret = Execute(buf.base, nread);
633
634
    // Exception
635
64824
    if (ret.IsEmpty())
636
5
      return;
637
638
    Local<Value> cb =
639
194457
        object()->Get(env()->context(), kOnExecute).ToLocalChecked();
640
641
64819
    if (!cb->IsFunction())
642
1002
      return;
643
644
    // Hooks for GetCurrentBuffer
645
63817
    current_buffer_len_ = nread;
646
63817
    current_buffer_data_ = buf.base;
647
648
63817
    MakeCallback(cb.As<Function>(), 1, &ret);
649
650
63814
    current_buffer_len_ = 0;
651
127628
    current_buffer_data_ = nullptr;
652
  }
653
654
655
81260
  Local<Value> Execute(char* data, size_t len) {
656
81260
    EscapableHandleScope scope(env()->isolate());
657
658
81260
    current_buffer_len_ = len;
659
81260
    current_buffer_data_ = data;
660
81260
    got_exception_ = false;
661
662
    parser_errno_t err;
663
664
#ifdef NODE_EXPERIMENTAL_HTTP
665
    // Do not allow re-entering `http_parser_execute()`
666
81250
    CHECK_EQ(execute_depth_, 0);
667
668
81250
    execute_depth_++;
669
81250
    if (data == nullptr) {
670
850
      err = llhttp_finish(&parser_);
671
    } else {
672
80400
      err = llhttp_execute(&parser_, data, len);
673
80398
      Save();
674
    }
675
81248
    execute_depth_--;
676
677
    // Calculate bytes read and resume after Upgrade/CONNECT pause
678
81248
    size_t nread = len;
679
81248
    if (err != HPE_OK) {
680
307
      nread = llhttp_get_error_pos(&parser_) - data;
681
682
      // This isn't a real pause, just a way to stop parsing early.
683
307
      if (err == HPE_PAUSED_UPGRADE) {
684
49
        err = HPE_OK;
685
49
        llhttp_resume_after_upgrade(&parser_);
686
      }
687
    }
688
689
    // Apply pending pause
690
81248
    if (pending_pause_) {
691
      pending_pause_ = false;
692
      llhttp_pause(&parser_);
693
    }
694
#else  /* !NODE_EXPERIMENTAL_HTTP */
695
10
    size_t nread = http_parser_execute(&parser_, &settings, data, len);
696
10
    err = HTTP_PARSER_ERRNO(&parser_);
697
698
    // Finish()
699
10
    if (data == nullptr) {
700
      // `http_parser_execute()` returns either `0` or `1` when `len` is 0
701
      // (part of the finishing sequence).
702
3
      CHECK_EQ(len, 0);
703
3
      switch (nread) {
704
        case 0:
705
3
          err = HPE_OK;
706
3
          break;
707
        case 1:
708
          nread = 0;
709
          break;
710
        default:
711
          UNREACHABLE();
712
      }
713
714
    // Regular Execute()
715
    } else {
716
7
      Save();
717
    }
718
#endif  /* NODE_EXPERIMENTAL_HTTP */
719
720
    // Unassign the 'buffer_' variable
721
81258
    current_buffer_.Clear();
722
81258
    current_buffer_len_ = 0;
723
81258
    current_buffer_data_ = nullptr;
724
725
    // If there was an exception in one of the callbacks
726
81258
    if (got_exception_)
727
7
      return scope.Escape(Local<Value>());
728
729
81251
    Local<Integer> nread_obj = Integer::New(env()->isolate(), nread);
730
731
    // If there was a parse error in one of the callbacks
732
    // TODO(bnoordhuis) What if there is an error on EOF?
733

81251
    if (!parser_.upgrade && err != HPE_OK) {
734
207
      Local<Value> e = Exception::Error(env()->parse_error_string());
735
414
      Local<Object> obj = e->ToObject(env()->isolate()->GetCurrentContext())
736
414
        .ToLocalChecked();
737
      obj->Set(env()->context(),
738
               env()->bytes_parsed_string(),
739
828
               nread_obj).FromJust();
740
#ifdef NODE_EXPERIMENTAL_HTTP
741
202
      const char* errno_reason = llhttp_get_error_reason(&parser_);
742
743
      Local<String> code;
744
      Local<String> reason;
745
202
      if (err == HPE_USER) {
746
8
        const char* colon = strchr(errno_reason, ':');
747
8
        CHECK_NOT_NULL(colon);
748
        code = OneByteString(env()->isolate(), errno_reason,
749
8
                             colon - errno_reason);
750
8
        reason = OneByteString(env()->isolate(), colon + 1);
751
      } else {
752
194
        code = OneByteString(env()->isolate(), llhttp_errno_name(err));
753
194
        reason = OneByteString(env()->isolate(), errno_reason);
754
      }
755
756
808
      obj->Set(env()->context(), env()->code_string(), code).FromJust();
757
808
      obj->Set(env()->context(), env()->reason_string(), reason).FromJust();
758
#else  /* !NODE_EXPERIMENTAL_HTTP */
759
      obj->Set(env()->context(),
760
               env()->code_string(),
761
               OneByteString(env()->isolate(),
762
25
                             http_errno_name(err))).FromJust();
763
#endif  /* NODE_EXPERIMENTAL_HTTP */
764
      return scope.Escape(e);
765
    }
766
767
    // No return value is needed for `Finish()`
768
81044
    if (data == nullptr) {
769
824
      return scope.Escape(Local<Value>());
770
    }
771
80220
    return scope.Escape(nread_obj);
772
  }
773
774
85420
  Local<Array> CreateHeaders() {
775
    // There could be extra entries but the max size should be fixed
776
5552300
    Local<Value> headers_v[kMaxHeaderFieldsCount * 2];
777
778
216849
    for (size_t i = 0; i < num_values_; ++i) {
779
262858
      headers_v[i * 2] = fields_[i].ToString(env());
780
262858
      headers_v[i * 2 + 1] = values_[i].ToString(env());
781
    }
782
783
85420
    return Array::New(env()->isolate(), headers_v, num_values_ * 2);
784
  }
785
786
787
  // spill headers and request path to JS land
788
67
  void Flush() {
789
67
    HandleScope scope(env()->isolate());
790
791
67
    Local<Object> obj = object();
792
201
    Local<Value> cb = obj->Get(env()->context(), kOnHeaders).ToLocalChecked();
793
794
67
    if (!cb->IsFunction())
795
67
      return;
796
797
    Local<Value> argv[2] = {
798
      CreateHeaders(),
799
      url_.ToString(env())
800
201
    };
801
802
    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
803
67
                                       arraysize(argv),
804
134
                                       argv);
805
806
67
    if (r.IsEmpty())
807
      got_exception_ = true;
808
809
67
    url_.Reset();
810
67
    have_flushed_ = true;
811
  }
812
813
814
35847
  void Init(parser_type_t type) {
815
#ifdef NODE_EXPERIMENTAL_HTTP
816
35837
    llhttp_init(&parser_, type, &settings);
817
35837
    header_nread_ = 0;
818
#else  /* !NODE_EXPERIMENTAL_HTTP */
819
10
    http_parser_init(&parser_, type);
820
#endif  /* NODE_EXPERIMENTAL_HTTP */
821
35847
    url_.Reset();
822
35847
    status_message_.Reset();
823
35847
    num_fields_ = 0;
824
35847
    num_values_ = 0;
825
35847
    have_flushed_ = false;
826
35847
    got_exception_ = false;
827
35847
  }
828
829
830
348447
  int TrackHeader(size_t len) {
831
#ifdef NODE_EXPERIMENTAL_HTTP
832
348407
    header_nread_ += len;
833
348407
    if (header_nread_ >= per_process::cli_options->max_http_header_size) {
834
8
      llhttp_set_error_reason(&parser_, "HPE_HEADER_OVERFLOW:Header overflow");
835
8
      return HPE_USER;
836
    }
837
#endif  /* NODE_EXPERIMENTAL_HTTP */
838
348439
    return 0;
839
  }
840
841
842
679983
  int MaybePause() {
843
#ifdef NODE_EXPERIMENTAL_HTTP
844
679932
    CHECK_NE(execute_depth_, 0);
845
846
679932
    if (!pending_pause_) {
847
679932
      return 0;
848
    }
849
850
    pending_pause_ = false;
851
    llhttp_set_error_reason(&parser_, "Paused in callback");
852
    return HPE_PAUSED;
853
#else  /* !NODE_EXPERIMENTAL_HTTP */
854
51
    return 0;
855
#endif  /* NODE_EXPERIMENTAL_HTTP */
856
  }
857
858
  parser_t parser_;
859
  StringPtr fields_[kMaxHeaderFieldsCount];  // header fields
860
  StringPtr values_[kMaxHeaderFieldsCount];  // header values
861
  StringPtr url_;
862
  StringPtr status_message_;
863
  size_t num_fields_;
864
  size_t num_values_;
865
  bool have_flushed_;
866
  bool got_exception_;
867
  Local<Object> current_buffer_;
868
  size_t current_buffer_len_;
869
  char* current_buffer_data_;
870
#ifdef NODE_EXPERIMENTAL_HTTP
871
  unsigned int execute_depth_ = 0;
872
  bool pending_pause_ = false;
873
  uint64_t header_nread_ = 0;
874
#endif  /* NODE_EXPERIMENTAL_HTTP */
875
876
  // These are helper functions for filling `http_parser_settings`, which turn
877
  // a member function of Parser into a C-style HTTP parser callback.
878
  template <typename Parser, Parser> struct Proxy;
879
  template <typename Parser, typename ...Args, int (Parser::*Member)(Args...)>
880
  struct Proxy<int (Parser::*)(Args...), Member> {
881
680056
    static int Raw(parser_t* p, Args ... args) {
882
680056
      Parser* parser = ContainerOf(&Parser::parser_, p);
883
680056
      int rv = (parser->*Member)(std::forward<Args>(args)...);
884





680054
      if (rv == 0) {
885
679983
        rv = parser->MaybePause();
886
      }
887
680054
      return rv;
888
    }
889
  };
890
891
  typedef int (Parser::*Call)();
892
  typedef int (Parser::*DataCall)(const char* at, size_t length);
893
894
  static const parser_settings_t settings;
895
};
896
897
const parser_settings_t Parser::settings = {
898
  Proxy<Call, &Parser::on_message_begin>::Raw,
899
  Proxy<DataCall, &Parser::on_url>::Raw,
900
  Proxy<DataCall, &Parser::on_status>::Raw,
901
  Proxy<DataCall, &Parser::on_header_field>::Raw,
902
  Proxy<DataCall, &Parser::on_header_value>::Raw,
903
  Proxy<Call, &Parser::on_headers_complete>::Raw,
904
  Proxy<DataCall, &Parser::on_body>::Raw,
905
  Proxy<Call, &Parser::on_message_complete>::Raw,
906
#ifdef NODE_EXPERIMENTAL_HTTP
907
  Proxy<Call, &Parser::on_chunk_header>::Raw,
908
  Proxy<Call, &Parser::on_chunk_complete>::Raw,
909
#else  /* !NODE_EXPERIMENTAL_HTTP */
910
  nullptr,
911
  nullptr,
912
#endif  /* NODE_EXPERIMENTAL_HTTP */
913
};
914
915
916
#ifndef NODE_EXPERIMENTAL_HTTP
917
4
void InitMaxHttpHeaderSizeOnce() {
918
  const uint32_t max_http_header_size =
919
4
      per_process::cli_options->max_http_header_size;
920
4
  http_parser_set_max_header_size(max_http_header_size);
921
4
}
922
#endif  /* NODE_EXPERIMENTAL_HTTP */
923
924
925
662
void InitializeHttpParser(Local<Object> target,
926
                          Local<Value> unused,
927
                          Local<Context> context,
928
                          void* priv) {
929
662
  Environment* env = Environment::GetCurrent(context);
930
662
  Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
931
1324
  t->InstanceTemplate()->SetInternalFieldCount(1);
932
1324
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"));
933
934
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
935
1986
         Integer::New(env->isolate(), HTTP_REQUEST));
936
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
937
1986
         Integer::New(env->isolate(), HTTP_RESPONSE));
938
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
939
1986
         Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
940
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
941
1986
         Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
942
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
943
1986
         Integer::NewFromUnsigned(env->isolate(), kOnBody));
944
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
945
1986
         Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
946
662
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
947
1986
         Integer::NewFromUnsigned(env->isolate(), kOnExecute));
948
949
662
  Local<Array> methods = Array::New(env->isolate());
950
#define V(num, name, string)                                                  \
951
    methods->Set(env->context(),                                              \
952
        num, FIXED_ONE_BYTE_STRING(env->isolate(), #string)).FromJust();
953
68186
  HTTP_METHOD_MAP(V)
954
#undef V
955
  target->Set(env->context(),
956
              FIXED_ONE_BYTE_STRING(env->isolate(), "methods"),
957
2648
              methods).FromJust();
958
959
1324
  t->Inherit(AsyncWrap::GetConstructorTemplate(env));
960
662
  env->SetProtoMethod(t, "close", Parser::Close);
961
662
  env->SetProtoMethod(t, "free", Parser::Free);
962
662
  env->SetProtoMethod(t, "execute", Parser::Execute);
963
662
  env->SetProtoMethod(t, "finish", Parser::Finish);
964
662
  env->SetProtoMethod(t, "reinitialize", Parser::Reinitialize);
965
662
  env->SetProtoMethod(t, "pause", Parser::Pause<true>);
966
662
  env->SetProtoMethod(t, "resume", Parser::Pause<false>);
967
662
  env->SetProtoMethod(t, "consume", Parser::Consume);
968
662
  env->SetProtoMethod(t, "unconsume", Parser::Unconsume);
969
662
  env->SetProtoMethod(t, "getCurrentBuffer", Parser::GetCurrentBuffer);
970
971
  target->Set(env->context(),
972
              FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"),
973
3972
              t->GetFunction(env->context()).ToLocalChecked()).FromJust();
974
975
#ifndef NODE_EXPERIMENTAL_HTTP
976
  static uv_once_t init_once = UV_ONCE_INIT;
977
4
  uv_once(&init_once, InitMaxHttpHeaderSizeOnce);
978
#endif  /* NODE_EXPERIMENTAL_HTTP */
979
662
}
980
981
}  // anonymous namespace
982
}  // namespace node
983
984
#endif  // SRC_NODE_HTTP_PARSER_IMPL_H_