GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/node_http_parser.cc Lines: 332 341 97.4 %
Date: 2016-07-26 Branches: 153 228 67.1 %

Line Exec Source
1
#include "node.h"
2
#include "node_buffer.h"
3
#include "node_http_parser.h"
4
5
#include "async-wrap.h"
6
#include "async-wrap-inl.h"
7
#include "env.h"
8
#include "env-inl.h"
9
#include "stream_base.h"
10
#include "stream_base-inl.h"
11
#include "util.h"
12
#include "util-inl.h"
13
#include "v8.h"
14
15
#include <stdlib.h>  // free()
16
#include <string.h>  // strdup()
17
18
// This is a binding to http_parser (https://github.com/joyent/http-parser)
19
// The goal is to decouple sockets from parsing for more javascript-level
20
// agility. A Buffer is read from a socket and passed to parser.execute().
21
// The parser then issues callbacks with slices of the data
22
//     parser.onMessageBegin
23
//     parser.onPath
24
//     parser.onBody
25
//     ...
26
// No copying is performed when slicing the buffer, only small reference
27
// allocations.
28
29
30
namespace node {
31
32
using v8::Array;
33
using v8::Boolean;
34
using v8::Context;
35
using v8::EscapableHandleScope;
36
using v8::Exception;
37
using v8::Function;
38
using v8::FunctionCallbackInfo;
39
using v8::FunctionTemplate;
40
using v8::HandleScope;
41
using v8::Integer;
42
using v8::Local;
43
using v8::Object;
44
using v8::String;
45
using v8::Uint32;
46
using v8::Undefined;
47
using v8::Value;
48
49
const uint32_t kOnHeaders = 0;
50
const uint32_t kOnHeadersComplete = 1;
51
const uint32_t kOnBody = 2;
52
const uint32_t kOnMessageComplete = 3;
53
const uint32_t kOnExecute = 4;
54
55
56
#define HTTP_CB(name)                                                         \
57
  static int name(http_parser* p_) {                                          \
58
    Parser* self = ContainerOf(&Parser::parser_, p_);                         \
59
    return self->name##_();                                                   \
60
  }                                                                           \
61
  int name##_()
62
63
64
#define HTTP_DATA_CB(name)                                                    \
65
  static int name(http_parser* p_, const char* at, size_t length) {           \
66
    Parser* self = ContainerOf(&Parser::parser_, p_);                         \
67
    return self->name##_(at, length);                                         \
68
  }                                                                           \
69
  int name##_(const char* at, size_t length)
70
71
72
// helper class for the Parser
73
struct StringPtr {
74
  StringPtr() {
75
120450
    on_heap_ = false;
76
120450
    Reset();
77
  }
78
79
80
66
  ~StringPtr() {
81
66
    Reset();
82
  }
83
84
85
  // If str_ does not point to a heap string yet, this function makes it do
86
  // so. This is called at the end of each http_parser_execute() so as not
87
  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
88
9483
  void Save() {
89
9483
    if (!on_heap_ && size_ > 0) {
90
3548
      char* s = new char[size_];
91
7096
      memcpy(s, str_, size_);
92
3548
      str_ = s;
93
3548
      on_heap_ = true;
94
    }
95
9483
  }
96
97
98
  void Reset() {
99
82223
    if (on_heap_) {
100
1622
      delete[] str_;
101
1622
      on_heap_ = false;
102
    }
103
104
202673
    str_ = nullptr;
105
202673
    size_ = 0;
106
  }
107
108
109
57277
  void Update(const char* str, size_t size) {
110
57277
    if (str_ == nullptr) {
111
57220
      str_ = str;
112
57
    } else if (on_heap_ || str_ + size_ != str) {
113
      // Non-consecutive input, make a copy on the heap.
114
      // TODO(bnoordhuis) Use slab allocation, O(n) allocs is bad.
115
57
      char* s = new char[size_ + size];
116
114
      memcpy(s, str_, size_);
117
114
      memcpy(s + size_, str, size);
118
119
57
      if (on_heap_)
120
56
        delete[] str_;
121
      else
122
1
        on_heap_ = true;
123
124
57
      str_ = s;
125
    }
126
57277
    size_ += size;
127
57277
  }
128
129
130
  Local<String> ToString(Environment* env) const {
131
57601
    if (str_)
132
57194
      return OneByteString(env->isolate(), str_, size_);
133
    else
134
407
      return String::Empty(env->isolate());
135
  }
136
137
138
  const char* str_;
139
  bool on_heap_;
140
  size_t size_;
141
};
142
143
144
class Parser : public AsyncWrap {
145
 public:
146
1825
  Parser(Environment* env, Local<Object> wrap, enum http_parser_type type)
147
      : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTPPARSER),
148
        current_buffer_len_(0),
149
127750
        current_buffer_data_(nullptr) {
150
3650
    Wrap(object(), this);
151
1825
    Init(type);
152
1825
  }
153
154
155
7
  ~Parser() override {
156
2
    ClearWrap(object());
157
2
    persistent().Reset();
158
2
  }
159
160
161
  size_t self_size() const override {
162
    return sizeof(*this);
163
  }
164
165
166
43932
  HTTP_CB(on_message_begin) {
167
14644
    num_fields_ = num_values_ = 0;
168
29288
    url_.Reset();
169
29288
    status_message_.Reset();
170
14644
    return 0;
171
  }
172
173
174
39399
  HTTP_DATA_CB(on_url) {
175
13133
    url_.Update(at, length);
176
    return 0;
177
  }
178
179
180
4539
  HTTP_DATA_CB(on_status) {
181
1513
    status_message_.Update(at, length);
182
    return 0;
183
  }
184
185
186
63960
  HTTP_DATA_CB(on_header_field) {
187
21320
    if (num_fields_ == num_values_) {
188
      // start of new field name
189
21291
      num_fields_++;
190
21291
      if (num_fields_ == arraysize(fields_)) {
191
        // ran out of space - flush to javascript land
192
395
        Flush();
193
395
        num_fields_ = 1;
194
395
        num_values_ = 0;
195
      }
196
21291
      fields_[num_fields_ - 1].Reset();
197
    }
198
199
21320
    CHECK_LT(num_fields_, arraysize(fields_));
200
21320
    CHECK_EQ(num_fields_, num_values_ + 1);
201
202
21320
    fields_[num_fields_ - 1].Update(at, length);
203
204
21320
    return 0;
205
  }
206
207
208
63933
  HTTP_DATA_CB(on_header_value) {
209
21311
    if (num_values_ != num_fields_) {
210
      // start of new header value
211
21291
      num_values_++;
212
21291
      values_[num_values_ - 1].Reset();
213
    }
214
215
21311
    CHECK_LT(num_values_, arraysize(values_));
216
21311
    CHECK_EQ(num_values_, num_fields_);
217
218
21311
    values_[num_values_ - 1].Update(at, length);
219
220
21311
    return 0;
221
  }
222
223
224
43905
  HTTP_CB(on_headers_complete) {
225
    // Arguments for the on-headers-complete javascript callback. This
226
    // list needs to be kept in sync with the actual argument list for
227
    // `parserOnHeadersComplete` in lib/_http_common.js.
228
    enum on_headers_complete_arg_index {
229
      A_VERSION_MAJOR = 0,
230
      A_VERSION_MINOR,
231
      A_HEADERS,
232
      A_METHOD,
233
      A_URL,
234
      A_STATUS_CODE,
235
      A_STATUS_MESSAGE,
236
      A_UPGRADE,
237
      A_SHOULD_KEEP_ALIVE,
238
      A_MAX
239
    };
240
241
278065
    Local<Value> argv[A_MAX];
242
29270
    Local<Object> obj = object();
243
14635
    Local<Value> cb = obj->Get(kOnHeadersComplete);
244
245
14635
    if (!cb->IsFunction())
246
      return 0;
247
248
43905
    Local<Value> undefined = Undefined(env()->isolate());
249
146350
    for (size_t i = 0; i < arraysize(argv); i++)
250
131715
      argv[i] = undefined;
251
252
14635
    if (have_flushed_) {
253
      // Slow case, flush remaining headers.
254
10
      Flush();
255
    } else {
256
      // Fast case, pass headers and URL to JS land.
257
29250
      argv[A_HEADERS] = CreateHeaders();
258
14625
      if (parser_.type == HTTP_REQUEST)
259
39348
        argv[A_URL] = url_.ToString(env());
260
    }
261
262
14635
    num_fields_ = 0;
263
14635
    num_values_ = 0;
264
265
    // METHOD
266
14635
    if (parser_.type == HTTP_REQUEST) {
267
      argv[A_METHOD] =
268
26242
          Uint32::NewFromUnsigned(env()->isolate(), parser_.method);
269
    }
270
271
    // STATUS
272
14635
    if (parser_.type == HTTP_RESPONSE) {
273
      argv[A_STATUS_CODE] =
274
3028
          Integer::New(env()->isolate(), parser_.status_code);
275
4542
      argv[A_STATUS_MESSAGE] = status_message_.ToString(env());
276
    }
277
278
    // VERSION
279
29270
    argv[A_VERSION_MAJOR] = Integer::New(env()->isolate(), parser_.http_major);
280
29270
    argv[A_VERSION_MINOR] = Integer::New(env()->isolate(), parser_.http_minor);
281
282
    argv[A_SHOULD_KEEP_ALIVE] =
283
43905
        Boolean::New(env()->isolate(), http_should_keep_alive(&parser_));
284
285
43905
    argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade);
286
287
29270
    Environment::AsyncCallbackScope callback_scope(env());
288
289
    Local<Value> head_response =
290
29270
        MakeCallback(cb.As<Function>(), arraysize(argv), argv);
291
292
14632
    if (head_response.IsEmpty()) {
293
7
      got_exception_ = true;
294
7
      return -1;
295
    }
296
297
14625
    return head_response->IntegerValue();
298
  }
299
300
301
15996
  HTTP_DATA_CB(on_body) {
302
10664
    EscapableHandleScope scope(env()->isolate());
303
304
10664
    Local<Object> obj = object();
305
5332
    Local<Value> cb = obj->Get(kOnBody);
306
307
5332
    if (!cb->IsFunction())
308
      return 0;
309
310
    // We came from consumed stream
311
10664
    if (current_buffer_.IsEmpty()) {
312
      // Make sure Buffer will be in parent HandleScope
313
474
      current_buffer_ = scope.Escape(Buffer::Copy(
314
          env()->isolate(),
315
474
          current_buffer_data_,
316
1896
          current_buffer_len_).ToLocalChecked());
317
    }
318
319
    Local<Value> argv[3] = {
320
      current_buffer_,
321
5332
      Integer::NewFromUnsigned(env()->isolate(), at - current_buffer_data_),
322
      Integer::NewFromUnsigned(env()->isolate(), length)
323
26660
    };
324
325
10664
    Local<Value> r = MakeCallback(cb.As<Function>(), arraysize(argv), argv);
326
327
5332
    if (r.IsEmpty()) {
328
      got_exception_ = true;
329
      return -1;
330
    }
331
332
    return 0;
333
  }
334
335
336
40350
  HTTP_CB(on_message_complete) {
337
26900
    HandleScope scope(env()->isolate());
338
339
13450
    if (num_fields_)
340
4
      Flush();  // Flush trailing HTTP headers.
341
342
26900
    Local<Object> obj = object();
343
13450
    Local<Value> cb = obj->Get(kOnMessageComplete);
344
345
13450
    if (!cb->IsFunction())
346
      return 0;
347
348
26900
    Environment::AsyncCallbackScope callback_scope(env());
349
350
13450
    Local<Value> r = MakeCallback(cb.As<Function>(), 0, nullptr);
351
352
13450
    if (r.IsEmpty()) {
353
      got_exception_ = true;
354
      return -1;
355
    }
356
357
    return 0;
358
  }
359
360
361
1825
  static void New(const FunctionCallbackInfo<Value>& args) {
362
1825
    Environment* env = Environment::GetCurrent(args);
363
    http_parser_type type =
364
1825
        static_cast<http_parser_type>(args[0]->Int32Value());
365
1825
    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
366
1825
    new Parser(env, args.This(), type);
367
1825
  }
368
369
370
1
  static void Close(const FunctionCallbackInfo<Value>& args) {
371
    Parser* parser;
372
1
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
373
374
1
    if (--parser->refcount_ == 0)
375
      delete parser;
376
  }
377
378
379
4652
  void Save() {
380
4652
    url_.Save();
381
4652
    status_message_.Save();
382
383
4758
    for (size_t i = 0; i < num_fields_; i++) {
384
106
      fields_[i].Save();
385
    }
386
387
4798
    for (size_t i = 0; i < num_values_; i++) {
388
73
      values_[i].Save();
389
    }
390
4652
  }
391
392
393
  // var bytesParsed = parser->execute(buffer);
394
1496
  static void Execute(const FunctionCallbackInfo<Value>& args) {
395
    Parser* parser;
396
1496
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
397
2992
    CHECK(parser->current_buffer_.IsEmpty());
398
1496
    CHECK_EQ(parser->current_buffer_len_, 0);
399
1496
    CHECK_EQ(parser->current_buffer_data_, nullptr);
400
1496
    CHECK_EQ(Buffer::HasInstance(args[0]), true);
401
402
2992
    Local<Object> buffer_obj = args[0].As<Object>();
403
1496
    char* buffer_data = Buffer::Data(buffer_obj);
404
1496
    size_t buffer_len = Buffer::Length(buffer_obj);
405
406
    // This is a hack to get the current_buffer to the callbacks with the least
407
    // amount of overhead. Nothing else will run while http_parser_execute()
408
    // runs, therefore this pointer can be set and used for the execution.
409
1496
    parser->current_buffer_ = buffer_obj;
410
411
1496
    Local<Value> ret = parser->Execute(buffer_data, buffer_len);
412
413
1494
    if (!ret.IsEmpty())
414
1492
      args.GetReturnValue().Set(ret);
415
  }
416
417
418
206
  static void Finish(const FunctionCallbackInfo<Value>& args) {
419
206
    Environment* env = Environment::GetCurrent(args);
420
421
    Parser* parser;
422
206
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
423
424
412
    CHECK(parser->current_buffer_.IsEmpty());
425
206
    parser->got_exception_ = false;
426
427
206
    int rv = http_parser_execute(&(parser->parser_), &settings, nullptr, 0);
428
429
206
    if (parser->got_exception_)
430
      return;
431
432
206
    if (rv != 0) {
433
12
      enum http_errno err = HTTP_PARSER_ERRNO(&parser->parser_);
434
435
12
      Local<Value> e = Exception::Error(env->parse_error_string());
436
24
      Local<Object> obj = e->ToObject(env->isolate());
437
48
      obj->Set(env->bytes_parsed_string(), Integer::New(env->isolate(), 0));
438
60
      obj->Set(env->code_string(),
439
12
               OneByteString(env->isolate(), http_errno_name(err)));
440
441
24
      args.GetReturnValue().Set(e);
442
    }
443
  }
444
445
446
3114
  static void Reinitialize(const FunctionCallbackInfo<Value>& args) {
447
3114
    Environment* env = Environment::GetCurrent(args);
448
449
    http_parser_type type =
450
3114
        static_cast<http_parser_type>(args[0]->Int32Value());
451
452
3114
    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
453
    Parser* parser;
454
3114
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
455
    // Should always be called from the same context.
456
3114
    CHECK_EQ(env, parser->env());
457
3114
    parser->Init(type);
458
  }
459
460
461
  template <bool should_pause>
462
10
  static void Pause(const FunctionCallbackInfo<Value>& args) {
463
10
    Environment* env = Environment::GetCurrent(args);
464
    Parser* parser;
465
10
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
466
    // Should always be called from the same context.
467
10
    CHECK_EQ(env, parser->env());
468
10
    http_parser_pause(&parser->parser_, should_pause);
469
  }
470
471
472
2533
  static void Consume(const FunctionCallbackInfo<Value>& args) {
473
    Parser* parser;
474
2533
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
475
5066
    Local<External> stream_obj = args[0].As<External>();
476
2533
    StreamBase* stream = static_cast<StreamBase*>(stream_obj->Value());
477
2533
    CHECK_NE(stream, nullptr);
478
479
2533
    stream->Consume();
480
481
2533
    parser->prev_alloc_cb_ = stream->alloc_cb();
482
2533
    parser->prev_read_cb_ = stream->read_cb();
483
484
2533
    stream->set_alloc_cb({ OnAllocImpl, parser });
485
2533
    stream->set_read_cb({ OnReadImpl, parser });
486
  }
487
488
489
2523
  static void Unconsume(const FunctionCallbackInfo<Value>& args) {
490
    Parser* parser;
491
2523
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
492
493
    // Already unconsumed
494
2523
    if (parser->prev_alloc_cb_.is_empty())
495
      return;
496
497
    // Restore stream's callbacks
498
6060
    if (args.Length() == 1 && args[0]->IsExternal()) {
499
2028
      Local<External> stream_obj = args[0].As<External>();
500
1014
      StreamBase* stream = static_cast<StreamBase*>(stream_obj->Value());
501
1014
      CHECK_NE(stream, nullptr);
502
503
1014
      stream->set_alloc_cb(parser->prev_alloc_cb_);
504
1014
      stream->set_read_cb(parser->prev_read_cb_);
505
    }
506
507
5046
    parser->prev_alloc_cb_.clear();
508
5046
    parser->prev_read_cb_.clear();
509
  }
510
511
512
11
  static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) {
513
    Parser* parser;
514
11
    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
515
516
22
    Local<Object> ret = Buffer::Copy(
517
        parser->env(),
518
11
        parser->current_buffer_data_,
519
33
        parser->current_buffer_len_).ToLocalChecked();
520
521
11
    args.GetReturnValue().Set(ret);
522
  }
523
524
 protected:
525
  class ScopedRetainParser {
526
   public:
527
3159
    explicit ScopedRetainParser(Parser* p) : p_(p) {
528
3159
      CHECK_GT(p_->refcount_, 0);
529
3159
      p_->refcount_++;
530
    }
531
532
2151
    ~ScopedRetainParser() {
533
3157
      if (0 == --p_->refcount_)
534
1
        delete p_;
535
    }
536
537
   private:
538
    Parser* const p_;
539
  };
540
541
  static const size_t kAllocBufferSize = 64 * 1024;
542
543
3250
  static void OnAllocImpl(size_t suggested_size, uv_buf_t* buf, void* ctx) {
544
3250
    Parser* parser = static_cast<Parser*>(ctx);
545
3250
    Environment* env = parser->env();
546
547
3250
    if (env->http_parser_buffer() == nullptr)
548
182
      env->set_http_parser_buffer(new char[kAllocBufferSize]);
549
550
3250
    buf->base = env->http_parser_buffer();
551
3250
    buf->len = kAllocBufferSize;
552
3250
  }
553
554
555
3257
  static void OnReadImpl(ssize_t nread,
556
                         const uv_buf_t* buf,
557
                         uv_handle_type pending,
558
                         void* ctx) {
559
3257
    Parser* parser = static_cast<Parser*>(ctx);
560
5408
    HandleScope scope(parser->env()->isolate());
561
562
3257
    if (nread < 0) {
563
      uv_buf_t tmp_buf;
564
98
      tmp_buf.base = nullptr;
565
98
      tmp_buf.len = 0;
566
98
      parser->prev_read_cb_.fn(nread,
567
                               &tmp_buf,
568
                               pending,
569
98
                               parser->prev_read_cb_.ctx);
570
      return;
571
    }
572
573
    // Ignore, empty reads have special meaning in http parser
574
3159
    if (nread == 0)
575
      return;
576
577
5310
    ScopedRetainParser retain(parser);
578
579
6318
    parser->current_buffer_.Clear();
580
3159
    Local<Value> ret = parser->Execute(buf->base, nread);
581
582
    // Exception
583
3158
    if (ret.IsEmpty())
584
      return;
585
586
6306
    Local<Object> obj = parser->object();
587
3153
    Local<Value> cb = obj->Get(kOnExecute);
588
589
3153
    if (!cb->IsFunction())
590
      return;
591
592
    // Hooks for GetCurrentBuffer
593
2152
    parser->current_buffer_len_ = nread;
594
2152
    parser->current_buffer_data_ = buf->base;
595
596
2152
    parser->MakeCallback(cb.As<Function>(), 1, &ret);
597
598
2151
    parser->current_buffer_len_ = 0;
599
2151
    parser->current_buffer_data_ = nullptr;
600
  }
601
602
603
4655
  Local<Value> Execute(char* data, size_t len) {
604
9307
    EscapableHandleScope scope(env()->isolate());
605
606
4655
    current_buffer_len_ = len;
607
4655
    current_buffer_data_ = data;
608
4655
    got_exception_ = false;
609
610
    size_t nparsed =
611
4655
      http_parser_execute(&parser_, &settings, data, len);
612
613
4652
    Save();
614
615
    // Unassign the 'buffer_' variable
616
9304
    current_buffer_.Clear();
617
4652
    current_buffer_len_ = 0;
618
4652
    current_buffer_data_ = nullptr;
619
620
    // If there was an exception in one of the callbacks
621
4652
    if (got_exception_)
622
14
      return scope.Escape(Local<Value>());
623
624
4645
    Local<Integer> nparsed_obj = Integer::New(env()->isolate(), nparsed);
625
    // If there was a parse error in one of the callbacks
626
    // TODO(bnoordhuis) What if there is an error on EOF?
627
4645
    if (!parser_.upgrade && nparsed != len) {
628
161
      enum http_errno err = HTTP_PARSER_ERRNO(&parser_);
629
630
322
      Local<Value> e = Exception::Error(env()->parse_error_string());
631
322
      Local<Object> obj = e->ToObject(env()->isolate());
632
483
      obj->Set(env()->bytes_parsed_string(), nparsed_obj);
633
805
      obj->Set(env()->code_string(),
634
161
               OneByteString(env()->isolate(), http_errno_name(err)));
635
636
161
      return scope.Escape(e);
637
    }
638
8968
    return scope.Escape(nparsed_obj);
639
  }
640
641
15034
  Local<Array> CreateHeaders() {
642
15034
    Local<Array> headers = Array::New(env()->isolate());
643
30068
    Local<Function> fn = env()->push_values_to_array_function();
644
496122
    Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX * 2];
645
    size_t i = 0;
646
647
    do {
648
16237
      size_t j = 0;
649
58799
      while (i < num_values_ && j < arraysize(argv) / 2) {
650
63843
        argv[j * 2] = fields_[i].ToString(env());
651
63843
        argv[j * 2 + 1] = values_[i].ToString(env());
652
21281
        i++;
653
21281
        j++;
654
      }
655
16237
      if (j > 0) {
656
20680
        fn->Call(env()->context(), headers, j * 2, argv).ToLocalChecked();
657
      }
658
16237
    } while (i < num_values_);
659
660
15034
    return headers;
661
  }
662
663
664
  // spill headers and request path to JS land
665
409
  void Flush() {
666
818
    HandleScope scope(env()->isolate());
667
668
818
    Local<Object> obj = object();
669
409
    Local<Value> cb = obj->Get(kOnHeaders);
670
671
409
    if (!cb->IsFunction())
672
      return;
673
674
    Local<Value> argv[2] = {
675
      CreateHeaders(),
676
      url_.ToString(env())
677
1636
    };
678
679
818
    Local<Value> r = MakeCallback(cb.As<Function>(), arraysize(argv), argv);
680
681
409
    if (r.IsEmpty())
682
      got_exception_ = true;
683
684
818
    url_.Reset();
685
409
    have_flushed_ = true;
686
  }
687
688
689
4939
  void Init(enum http_parser_type type) {
690
4939
    http_parser_init(&parser_, type);
691
9878
    url_.Reset();
692
9878
    status_message_.Reset();
693
4939
    num_fields_ = 0;
694
4939
    num_values_ = 0;
695
4939
    have_flushed_ = false;
696
4939
    got_exception_ = false;
697
4939
  }
698
699
700
  http_parser parser_;
701
  StringPtr fields_[32];  // header fields
702
  StringPtr values_[32];  // header values
703
  StringPtr url_;
704
  StringPtr status_message_;
705
  size_t num_fields_;
706
  size_t num_values_;
707
  bool have_flushed_;
708
  bool got_exception_;
709
  Local<Object> current_buffer_;
710
  size_t current_buffer_len_;
711
  char* current_buffer_data_;
712
  StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_;
713
  StreamResource::Callback<StreamResource::ReadCb> prev_read_cb_;
714
  int refcount_ = 1;
715
  static const struct http_parser_settings settings;
716
717
  friend class ScopedRetainParser;
718
};
719
720
721
const struct http_parser_settings Parser::settings = {
722
  Parser::on_message_begin,
723
  Parser::on_url,
724
  Parser::on_status,
725
  Parser::on_header_field,
726
  Parser::on_header_value,
727
  Parser::on_headers_complete,
728
  Parser::on_body,
729
  Parser::on_message_complete,
730
  nullptr,  // on_chunk_header
731
  nullptr   // on_chunk_complete
732
};
733
734
735
247
void InitHttpParser(Local<Object> target,
736
                    Local<Value> unused,
737
                    Local<Context> context,
738
                    void* priv) {
739
247
  Environment* env = Environment::GetCurrent(context);
740
494
  Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
741
494
  t->InstanceTemplate()->SetInternalFieldCount(1);
742
247
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"));
743
744
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
745
247
         Integer::New(env->isolate(), HTTP_REQUEST));
746
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
747
247
         Integer::New(env->isolate(), HTTP_RESPONSE));
748
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
749
247
         Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
750
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
751
247
         Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
752
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
753
247
         Integer::NewFromUnsigned(env->isolate(), kOnBody));
754
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
755
247
         Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
756
988
  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
757
247
         Integer::NewFromUnsigned(env->isolate(), kOnExecute));
758
759
247
  Local<Array> methods = Array::New(env->isolate());
760
#define V(num, name, string)                                                  \
761
    methods->Set(num, FIXED_ONE_BYTE_STRING(env->isolate(), #string));
762
8398
  HTTP_METHOD_MAP(V)
763
#undef V
764
494
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "methods"), methods);
765
766
247
  env->SetProtoMethod(t, "close", Parser::Close);
767
247
  env->SetProtoMethod(t, "execute", Parser::Execute);
768
247
  env->SetProtoMethod(t, "finish", Parser::Finish);
769
247
  env->SetProtoMethod(t, "reinitialize", Parser::Reinitialize);
770
247
  env->SetProtoMethod(t, "pause", Parser::Pause<true>);
771
247
  env->SetProtoMethod(t, "resume", Parser::Pause<false>);
772
247
  env->SetProtoMethod(t, "consume", Parser::Consume);
773
247
  env->SetProtoMethod(t, "unconsume", Parser::Unconsume);
774
247
  env->SetProtoMethod(t, "getCurrentBuffer", Parser::GetCurrentBuffer);
775
776
988
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"),
777
247
              t->GetFunction());
778
247
}
779
780
}  // namespace node
781
782
1566
NODE_MODULE_CONTEXT_AWARE_BUILTIN(http_parser, node::InitHttpParser)