xref: /third_party/node/src/node_http_parser.cc (revision 1cb0ef41)
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
49namespace node {
50namespace {  // NOLINT(build/namespaces)
51
52using v8::Array;
53using v8::Boolean;
54using v8::Context;
55using v8::EscapableHandleScope;
56using v8::Exception;
57using v8::Function;
58using v8::FunctionCallbackInfo;
59using v8::FunctionTemplate;
60using v8::HandleScope;
61using v8::Int32;
62using v8::Integer;
63using v8::Isolate;
64using v8::Local;
65using v8::MaybeLocal;
66using v8::Number;
67using v8::Object;
68using v8::String;
69using v8::Uint32;
70using v8::Undefined;
71using v8::Value;
72
73const uint32_t kOnMessageBegin = 0;
74const uint32_t kOnHeaders = 1;
75const uint32_t kOnHeadersComplete = 2;
76const uint32_t kOnBody = 3;
77const uint32_t kOnMessageComplete = 4;
78const uint32_t kOnExecute = 5;
79const uint32_t kOnTimeout = 6;
80// Any more fields than this will be flushed into JS
81const size_t kMaxHeaderFieldsCount = 32;
82// Maximum size of chunk extensions
83const size_t kMaxChunkExtensionsSize = 16384;
84
85const uint32_t kLenientNone = 0;
86const uint32_t kLenientHeaders = 1 << 0;
87const uint32_t kLenientChunkedLength = 1 << 1;
88const uint32_t kLenientKeepAlive = 1 << 2;
89const uint32_t kLenientAll = kLenientHeaders | kLenientChunkedLength |
90  kLenientKeepAlive;
91
92inline bool IsOWS(char c) {
93  return c == ' ' || c == '\t';
94}
95
96class BindingData : public BaseObject {
97 public:
98  BindingData(Realm* realm, Local<Object> obj) : BaseObject(realm, obj) {}
99
100  SET_BINDING_ID(http_parser_binding_data)
101
102  std::vector<char> parser_buffer;
103  bool parser_buffer_in_use = false;
104
105  void MemoryInfo(MemoryTracker* tracker) const override {
106    tracker->TrackField("parser_buffer", parser_buffer);
107  }
108  SET_SELF_SIZE(BindingData)
109  SET_MEMORY_INFO_NAME(BindingData)
110};
111
112// helper class for the Parser
113struct StringPtr {
114  StringPtr() {
115    on_heap_ = false;
116    Reset();
117  }
118
119
120  ~StringPtr() {
121    Reset();
122  }
123
124
125  // If str_ does not point to a heap string yet, this function makes it do
126  // so. This is called at the end of each http_parser_execute() so as not
127  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
128  void Save() {
129    if (!on_heap_ && size_ > 0) {
130      char* s = new char[size_];
131      memcpy(s, str_, size_);
132      str_ = s;
133      on_heap_ = true;
134    }
135  }
136
137
138  void Reset() {
139    if (on_heap_) {
140      delete[] str_;
141      on_heap_ = false;
142    }
143
144    str_ = nullptr;
145    size_ = 0;
146  }
147
148
149  void Update(const char* str, size_t size) {
150    if (str_ == nullptr) {
151      str_ = str;
152    } else if (on_heap_ || str_ + size_ != str) {
153      // Non-consecutive input, make a copy on the heap.
154      // TODO(bnoordhuis) Use slab allocation, O(n) allocs is bad.
155      char* s = new char[size_ + size];
156      memcpy(s, str_, size_);
157      memcpy(s + size_, str, size);
158
159      if (on_heap_)
160        delete[] str_;
161      else
162        on_heap_ = true;
163
164      str_ = s;
165    }
166    size_ += size;
167  }
168
169
170  Local<String> ToString(Environment* env) const {
171    if (size_ != 0)
172      return OneByteString(env->isolate(), str_, size_);
173    else
174      return String::Empty(env->isolate());
175  }
176
177
178  // Strip trailing OWS (SPC or HTAB) from string.
179  Local<String> ToTrimmedString(Environment* env) {
180    while (size_ > 0 && IsOWS(str_[size_ - 1])) {
181      size_--;
182    }
183    return ToString(env);
184  }
185
186
187  const char* str_;
188  bool on_heap_;
189  size_t size_;
190};
191
192class Parser;
193
194struct ParserComparator {
195  bool operator()(const Parser* lhs, const Parser* rhs) const;
196};
197
198class ConnectionsList : public BaseObject {
199 public:
200    static void New(const FunctionCallbackInfo<Value>& args);
201
202    static void All(const FunctionCallbackInfo<Value>& args);
203
204    static void Idle(const FunctionCallbackInfo<Value>& args);
205
206    static void Active(const FunctionCallbackInfo<Value>& args);
207
208    static void Expired(const FunctionCallbackInfo<Value>& args);
209
210    void Push(Parser* parser) {
211      all_connections_.insert(parser);
212    }
213
214    void Pop(Parser* parser) {
215      all_connections_.erase(parser);
216    }
217
218    void PushActive(Parser* parser) {
219      active_connections_.insert(parser);
220    }
221
222    void PopActive(Parser* parser) {
223      active_connections_.erase(parser);
224    }
225
226    SET_NO_MEMORY_INFO()
227    SET_MEMORY_INFO_NAME(ConnectionsList)
228    SET_SELF_SIZE(ConnectionsList)
229
230 private:
231    ConnectionsList(Environment* env, Local<Object> object)
232      : BaseObject(env, object) {
233        MakeWeak();
234      }
235
236    std::set<Parser*, ParserComparator> all_connections_;
237    std::set<Parser*, ParserComparator> active_connections_;
238};
239
240class Parser : public AsyncWrap, public StreamListener {
241  friend class ConnectionsList;
242  friend struct ParserComparator;
243
244 public:
245  Parser(BindingData* binding_data, Local<Object> wrap)
246      : AsyncWrap(binding_data->env(), wrap),
247        current_buffer_len_(0),
248        current_buffer_data_(nullptr),
249        binding_data_(binding_data) {
250  }
251
252  SET_NO_MEMORY_INFO()
253  SET_MEMORY_INFO_NAME(Parser)
254  SET_SELF_SIZE(Parser)
255
256  int on_message_begin() {
257    // Important: Pop from the lists BEFORE resetting the last_message_start_
258    // otherwise std::set.erase will fail.
259    if (connectionsList_ != nullptr) {
260      connectionsList_->Pop(this);
261      connectionsList_->PopActive(this);
262    }
263
264    num_fields_ = num_values_ = 0;
265    headers_completed_ = false;
266    chunk_extensions_nread_ = 0;
267    last_message_start_ = uv_hrtime();
268    url_.Reset();
269    status_message_.Reset();
270
271    if (connectionsList_ != nullptr) {
272      connectionsList_->Push(this);
273      connectionsList_->PushActive(this);
274    }
275
276    Local<Value> cb = object()->Get(env()->context(), kOnMessageBegin)
277                              .ToLocalChecked();
278    if (cb->IsFunction()) {
279      InternalCallbackScope callback_scope(
280        this, InternalCallbackScope::kSkipTaskQueues);
281
282      MaybeLocal<Value> r = cb.As<Function>()->Call(
283        env()->context(), object(), 0, nullptr);
284
285      if (r.IsEmpty()) callback_scope.MarkAsFailed();
286    }
287
288    return 0;
289  }
290
291
292  int on_url(const char* at, size_t length) {
293    int rv = TrackHeader(length);
294    if (rv != 0) {
295      return rv;
296    }
297
298    url_.Update(at, length);
299    return 0;
300  }
301
302
303  int on_status(const char* at, size_t length) {
304    int rv = TrackHeader(length);
305    if (rv != 0) {
306      return rv;
307    }
308
309    status_message_.Update(at, length);
310    return 0;
311  }
312
313
314  int on_header_field(const char* at, size_t length) {
315    int rv = TrackHeader(length);
316    if (rv != 0) {
317      return rv;
318    }
319
320    if (num_fields_ == num_values_) {
321      // start of new field name
322      num_fields_++;
323      if (num_fields_ == kMaxHeaderFieldsCount) {
324        // ran out of space - flush to javascript land
325        Flush();
326        num_fields_ = 1;
327        num_values_ = 0;
328      }
329      fields_[num_fields_ - 1].Reset();
330    }
331
332    CHECK_LT(num_fields_, kMaxHeaderFieldsCount);
333    CHECK_EQ(num_fields_, num_values_ + 1);
334
335    fields_[num_fields_ - 1].Update(at, length);
336
337    return 0;
338  }
339
340
341  int on_header_value(const char* at, size_t length) {
342    int rv = TrackHeader(length);
343    if (rv != 0) {
344      return rv;
345    }
346
347    if (num_values_ != num_fields_) {
348      // start of new header value
349      num_values_++;
350      values_[num_values_ - 1].Reset();
351    }
352
353    CHECK_LT(num_values_, arraysize(values_));
354    CHECK_EQ(num_values_, num_fields_);
355
356    values_[num_values_ - 1].Update(at, length);
357
358    return 0;
359  }
360
361
362  int on_headers_complete() {
363    headers_completed_ = true;
364    header_nread_ = 0;
365
366    // Arguments for the on-headers-complete javascript callback. This
367    // list needs to be kept in sync with the actual argument list for
368    // `parserOnHeadersComplete` in lib/_http_common.js.
369    enum on_headers_complete_arg_index {
370      A_VERSION_MAJOR = 0,
371      A_VERSION_MINOR,
372      A_HEADERS,
373      A_METHOD,
374      A_URL,
375      A_STATUS_CODE,
376      A_STATUS_MESSAGE,
377      A_UPGRADE,
378      A_SHOULD_KEEP_ALIVE,
379      A_MAX
380    };
381
382    Local<Value> argv[A_MAX];
383    Local<Object> obj = object();
384    Local<Value> cb = obj->Get(env()->context(),
385                               kOnHeadersComplete).ToLocalChecked();
386
387    if (!cb->IsFunction())
388      return 0;
389
390    Local<Value> undefined = Undefined(env()->isolate());
391    for (size_t i = 0; i < arraysize(argv); i++)
392      argv[i] = undefined;
393
394    if (have_flushed_) {
395      // Slow case, flush remaining headers.
396      Flush();
397    } else {
398      // Fast case, pass headers and URL to JS land.
399      argv[A_HEADERS] = CreateHeaders();
400      if (parser_.type == HTTP_REQUEST)
401        argv[A_URL] = url_.ToString(env());
402    }
403
404    num_fields_ = 0;
405    num_values_ = 0;
406
407    // METHOD
408    if (parser_.type == HTTP_REQUEST) {
409      argv[A_METHOD] =
410          Uint32::NewFromUnsigned(env()->isolate(), parser_.method);
411    }
412
413    // STATUS
414    if (parser_.type == HTTP_RESPONSE) {
415      argv[A_STATUS_CODE] =
416          Integer::New(env()->isolate(), parser_.status_code);
417      argv[A_STATUS_MESSAGE] = status_message_.ToString(env());
418    }
419
420    // VERSION
421    argv[A_VERSION_MAJOR] = Integer::New(env()->isolate(), parser_.http_major);
422    argv[A_VERSION_MINOR] = Integer::New(env()->isolate(), parser_.http_minor);
423
424    bool should_keep_alive;
425    should_keep_alive = llhttp_should_keep_alive(&parser_);
426
427    argv[A_SHOULD_KEEP_ALIVE] =
428        Boolean::New(env()->isolate(), should_keep_alive);
429
430    argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade);
431
432    MaybeLocal<Value> head_response;
433    {
434      InternalCallbackScope callback_scope(
435          this, InternalCallbackScope::kSkipTaskQueues);
436      head_response = cb.As<Function>()->Call(
437          env()->context(), object(), arraysize(argv), argv);
438      if (head_response.IsEmpty()) callback_scope.MarkAsFailed();
439    }
440
441    int64_t val;
442
443    if (head_response.IsEmpty() || !head_response.ToLocalChecked()
444                                        ->IntegerValue(env()->context())
445                                        .To(&val)) {
446      got_exception_ = true;
447      return -1;
448    }
449
450    return static_cast<int>(val);
451  }
452
453
454  int on_body(const char* at, size_t length) {
455    if (length == 0)
456      return 0;
457
458    Environment* env = this->env();
459    HandleScope handle_scope(env->isolate());
460
461    Local<Value> cb = object()->Get(env->context(), kOnBody).ToLocalChecked();
462
463    if (!cb->IsFunction())
464      return 0;
465
466    Local<Value> buffer = Buffer::Copy(env, at, length).ToLocalChecked();
467
468    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(), 1, &buffer);
469
470    if (r.IsEmpty()) {
471      got_exception_ = true;
472      llhttp_set_error_reason(&parser_, "HPE_JS_EXCEPTION:JS Exception");
473      return HPE_USER;
474    }
475
476    return 0;
477  }
478
479
480  int on_message_complete() {
481    HandleScope scope(env()->isolate());
482
483    // Important: Pop from the lists BEFORE resetting the last_message_start_
484    // otherwise std::set.erase will fail.
485    if (connectionsList_ != nullptr) {
486      connectionsList_->Pop(this);
487      connectionsList_->PopActive(this);
488    }
489
490    last_message_start_ = 0;
491
492    if (connectionsList_ != nullptr) {
493      connectionsList_->Push(this);
494    }
495
496    if (num_fields_)
497      Flush();  // Flush trailing HTTP headers.
498
499    Local<Object> obj = object();
500    Local<Value> cb = obj->Get(env()->context(),
501                               kOnMessageComplete).ToLocalChecked();
502
503    if (!cb->IsFunction())
504      return 0;
505
506    MaybeLocal<Value> r;
507    {
508      InternalCallbackScope callback_scope(
509          this, InternalCallbackScope::kSkipTaskQueues);
510      r = cb.As<Function>()->Call(env()->context(), object(), 0, nullptr);
511      if (r.IsEmpty()) callback_scope.MarkAsFailed();
512    }
513
514    if (r.IsEmpty()) {
515      got_exception_ = true;
516      return -1;
517    }
518
519    return 0;
520  }
521
522  int on_chunk_extension(const char* at, size_t length) {
523    chunk_extensions_nread_ += length;
524
525    if (chunk_extensions_nread_ > kMaxChunkExtensionsSize) {
526      llhttp_set_error_reason(&parser_,
527        "HPE_CHUNK_EXTENSIONS_OVERFLOW:Chunk extensions overflow");
528      return HPE_USER;
529    }
530
531    return 0;
532  }
533
534  // Reset nread for the next chunk and also reset the extensions counter
535  int on_chunk_header() {
536    header_nread_ = 0;
537    chunk_extensions_nread_ = 0;
538    return 0;
539  }
540
541
542  // Reset nread for the next chunk
543  int on_chunk_complete() {
544    header_nread_ = 0;
545    return 0;
546  }
547
548  static void New(const FunctionCallbackInfo<Value>& args) {
549    BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
550    new Parser(binding_data, args.This());
551  }
552
553
554  static void Close(const FunctionCallbackInfo<Value>& args) {
555    Parser* parser;
556    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
557
558    delete parser;
559  }
560
561
562  static void Free(const FunctionCallbackInfo<Value>& args) {
563    Parser* parser;
564    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
565
566    // Since the Parser destructor isn't going to run the destroy() callbacks
567    // it needs to be triggered manually.
568    parser->EmitTraceEventDestroy();
569    parser->EmitDestroy();
570  }
571
572  static void Remove(const FunctionCallbackInfo<Value>& args) {
573    Parser* parser;
574    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
575
576    if (parser->connectionsList_ != nullptr) {
577      parser->connectionsList_->Pop(parser);
578      parser->connectionsList_->PopActive(parser);
579    }
580  }
581
582  void Save() {
583    url_.Save();
584    status_message_.Save();
585
586    for (size_t i = 0; i < num_fields_; i++) {
587      fields_[i].Save();
588    }
589
590    for (size_t i = 0; i < num_values_; i++) {
591      values_[i].Save();
592    }
593  }
594
595  // var bytesParsed = parser->execute(buffer);
596  static void Execute(const FunctionCallbackInfo<Value>& args) {
597    Parser* parser;
598    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
599
600    ArrayBufferViewContents<char> buffer(args[0]);
601
602    Local<Value> ret = parser->Execute(buffer.data(), buffer.length());
603
604    if (!ret.IsEmpty())
605      args.GetReturnValue().Set(ret);
606  }
607
608
609  static void Finish(const FunctionCallbackInfo<Value>& args) {
610    Parser* parser;
611    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
612
613    Local<Value> ret = parser->Execute(nullptr, 0);
614
615    if (!ret.IsEmpty())
616      args.GetReturnValue().Set(ret);
617  }
618
619
620  static void Initialize(const FunctionCallbackInfo<Value>& args) {
621    Environment* env = Environment::GetCurrent(args);
622
623    uint64_t max_http_header_size = 0;
624    uint32_t lenient_flags = kLenientNone;
625    ConnectionsList* connectionsList = nullptr;
626
627    CHECK(args[0]->IsInt32());
628    CHECK(args[1]->IsObject());
629
630    if (args.Length() > 2) {
631      CHECK(args[2]->IsNumber());
632      max_http_header_size =
633          static_cast<uint64_t>(args[2].As<Number>()->Value());
634    }
635    if (max_http_header_size == 0) {
636      max_http_header_size = env->options()->max_http_header_size;
637    }
638
639    if (args.Length() > 3) {
640      CHECK(args[3]->IsInt32());
641      lenient_flags = args[3].As<Int32>()->Value();
642    }
643
644    if (args.Length() > 4 && !args[4]->IsNullOrUndefined()) {
645      CHECK(args[4]->IsObject());
646      ASSIGN_OR_RETURN_UNWRAP(&connectionsList, args[4]);
647    }
648
649    llhttp_type_t type =
650        static_cast<llhttp_type_t>(args[0].As<Int32>()->Value());
651
652    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
653    Parser* parser;
654    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
655    // Should always be called from the same context.
656    CHECK_EQ(env, parser->env());
657
658    AsyncWrap::ProviderType provider =
659        (type == HTTP_REQUEST ?
660            AsyncWrap::PROVIDER_HTTPINCOMINGMESSAGE
661            : AsyncWrap::PROVIDER_HTTPCLIENTREQUEST);
662
663    parser->set_provider_type(provider);
664    parser->AsyncReset(args[1].As<Object>());
665    parser->Init(type, max_http_header_size, lenient_flags);
666
667    if (connectionsList != nullptr) {
668      parser->connectionsList_ = connectionsList;
669
670      // This protects from a DoS attack where an attacker establishes
671      // the connection without sending any data on applications where
672      // server.timeout is left to the default value of zero.
673      parser->last_message_start_ = uv_hrtime();
674
675      // Important: Push into the lists AFTER setting the last_message_start_
676      // otherwise std::set.erase will fail later.
677      parser->connectionsList_->Push(parser);
678      parser->connectionsList_->PushActive(parser);
679    } else {
680      parser->connectionsList_ = nullptr;
681    }
682  }
683
684  template <bool should_pause>
685  static void Pause(const FunctionCallbackInfo<Value>& args) {
686    Environment* env = Environment::GetCurrent(args);
687    Parser* parser;
688    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
689    // Should always be called from the same context.
690    CHECK_EQ(env, parser->env());
691
692    if constexpr (should_pause) {
693      llhttp_pause(&parser->parser_);
694    } else {
695      llhttp_resume(&parser->parser_);
696    }
697  }
698
699
700  static void Consume(const FunctionCallbackInfo<Value>& args) {
701    Parser* parser;
702    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
703    CHECK(args[0]->IsObject());
704    StreamBase* stream = StreamBase::FromObject(args[0].As<Object>());
705    CHECK_NOT_NULL(stream);
706    stream->PushStreamListener(parser);
707  }
708
709
710  static void Unconsume(const FunctionCallbackInfo<Value>& args) {
711    Parser* parser;
712    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
713
714    // Already unconsumed
715    if (parser->stream_ == nullptr)
716      return;
717
718    parser->stream_->RemoveStreamListener(parser);
719  }
720
721
722  static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) {
723    Parser* parser;
724    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
725
726    Local<Object> ret = Buffer::Copy(
727        parser->env(),
728        parser->current_buffer_data_,
729        parser->current_buffer_len_).ToLocalChecked();
730
731    args.GetReturnValue().Set(ret);
732  }
733
734  static void Duration(const FunctionCallbackInfo<Value>& args) {
735    Parser* parser;
736    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
737
738    if (parser->last_message_start_ == 0) {
739      args.GetReturnValue().Set(0);
740      return;
741    }
742
743    double duration = (uv_hrtime() - parser->last_message_start_) / 1e6;
744    args.GetReturnValue().Set(duration);
745  }
746
747  static void HeadersCompleted(const FunctionCallbackInfo<Value>& args) {
748    Parser* parser;
749    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
750
751    args.GetReturnValue().Set(parser->headers_completed_);
752  }
753
754 protected:
755  static const size_t kAllocBufferSize = 64 * 1024;
756
757  uv_buf_t OnStreamAlloc(size_t suggested_size) override {
758    // For most types of streams, OnStreamRead will be immediately after
759    // OnStreamAlloc, and will consume all data, so using a static buffer for
760    // reading is more efficient. For other streams, just use Malloc() directly.
761    if (binding_data_->parser_buffer_in_use)
762      return uv_buf_init(Malloc(suggested_size), suggested_size);
763    binding_data_->parser_buffer_in_use = true;
764
765    if (binding_data_->parser_buffer.empty())
766      binding_data_->parser_buffer.resize(kAllocBufferSize);
767
768    return uv_buf_init(binding_data_->parser_buffer.data(), kAllocBufferSize);
769  }
770
771
772  void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override {
773    HandleScope scope(env()->isolate());
774    // Once we’re done here, either indicate that the HTTP parser buffer
775    // is free for re-use, or free() the data if it didn’t come from there
776    // in the first place.
777    auto on_scope_leave = OnScopeLeave([&]() {
778      if (buf.base == binding_data_->parser_buffer.data())
779        binding_data_->parser_buffer_in_use = false;
780      else
781        free(buf.base);
782    });
783
784    if (nread < 0) {
785      PassReadErrorToPreviousListener(nread);
786      return;
787    }
788
789    // Ignore, empty reads have special meaning in http parser
790    if (nread == 0)
791      return;
792
793    Local<Value> ret = Execute(buf.base, nread);
794
795    // Exception
796    if (ret.IsEmpty())
797      return;
798
799    Local<Value> cb =
800        object()->Get(env()->context(), kOnExecute).ToLocalChecked();
801
802    if (!cb->IsFunction())
803      return;
804
805    // Hooks for GetCurrentBuffer
806    current_buffer_len_ = nread;
807    current_buffer_data_ = buf.base;
808
809    MakeCallback(cb.As<Function>(), 1, &ret);
810
811    current_buffer_len_ = 0;
812    current_buffer_data_ = nullptr;
813  }
814
815
816  Local<Value> Execute(const char* data, size_t len) {
817    EscapableHandleScope scope(env()->isolate());
818
819    current_buffer_len_ = len;
820    current_buffer_data_ = data;
821    got_exception_ = false;
822
823    llhttp_errno_t err;
824
825    if (data == nullptr) {
826      err = llhttp_finish(&parser_);
827    } else {
828      err = llhttp_execute(&parser_, data, len);
829      Save();
830    }
831
832    // Calculate bytes read and resume after Upgrade/CONNECT pause
833    size_t nread = len;
834    if (err != HPE_OK) {
835      nread = llhttp_get_error_pos(&parser_) - data;
836
837      // This isn't a real pause, just a way to stop parsing early.
838      if (err == HPE_PAUSED_UPGRADE) {
839        err = HPE_OK;
840        llhttp_resume_after_upgrade(&parser_);
841      }
842    }
843
844    // Apply pending pause
845    if (pending_pause_) {
846      pending_pause_ = false;
847      llhttp_pause(&parser_);
848    }
849
850    current_buffer_len_ = 0;
851    current_buffer_data_ = nullptr;
852
853    // If there was an exception in one of the callbacks
854    if (got_exception_)
855      return scope.Escape(Local<Value>());
856
857    Local<Integer> nread_obj = Integer::New(env()->isolate(), nread);
858
859    // If there was a parse error in one of the callbacks
860    // TODO(bnoordhuis) What if there is an error on EOF?
861    if (!parser_.upgrade && err != HPE_OK) {
862      Local<Value> e = Exception::Error(env()->parse_error_string());
863      Local<Object> obj = e->ToObject(env()->isolate()->GetCurrentContext())
864        .ToLocalChecked();
865      obj->Set(env()->context(),
866               env()->bytes_parsed_string(),
867               nread_obj).Check();
868      const char* errno_reason = llhttp_get_error_reason(&parser_);
869
870      Local<String> code;
871      Local<String> reason;
872      if (err == HPE_USER) {
873        const char* colon = strchr(errno_reason, ':');
874        CHECK_NOT_NULL(colon);
875        code = OneByteString(env()->isolate(),
876                             errno_reason,
877                             static_cast<int>(colon - errno_reason));
878        reason = OneByteString(env()->isolate(), colon + 1);
879      } else {
880        code = OneByteString(env()->isolate(), llhttp_errno_name(err));
881        reason = OneByteString(env()->isolate(), errno_reason);
882      }
883
884      obj->Set(env()->context(), env()->code_string(), code).Check();
885      obj->Set(env()->context(), env()->reason_string(), reason).Check();
886      return scope.Escape(e);
887    }
888
889    // No return value is needed for `Finish()`
890    if (data == nullptr) {
891      return scope.Escape(Local<Value>());
892    }
893    return scope.Escape(nread_obj);
894  }
895
896  Local<Array> CreateHeaders() {
897    // There could be extra entries but the max size should be fixed
898    Local<Value> headers_v[kMaxHeaderFieldsCount * 2];
899
900    for (size_t i = 0; i < num_values_; ++i) {
901      headers_v[i * 2] = fields_[i].ToString(env());
902      headers_v[i * 2 + 1] = values_[i].ToTrimmedString(env());
903    }
904
905    return Array::New(env()->isolate(), headers_v, num_values_ * 2);
906  }
907
908
909  // spill headers and request path to JS land
910  void Flush() {
911    HandleScope scope(env()->isolate());
912
913    Local<Object> obj = object();
914    Local<Value> cb = obj->Get(env()->context(), kOnHeaders).ToLocalChecked();
915
916    if (!cb->IsFunction())
917      return;
918
919    Local<Value> argv[2] = {
920      CreateHeaders(),
921      url_.ToString(env())
922    };
923
924    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
925                                       arraysize(argv),
926                                       argv);
927
928    if (r.IsEmpty())
929      got_exception_ = true;
930
931    url_.Reset();
932    have_flushed_ = true;
933  }
934
935
936  void Init(llhttp_type_t type, uint64_t max_http_header_size,
937            uint32_t lenient_flags) {
938    llhttp_init(&parser_, type, &settings);
939
940    if (lenient_flags & kLenientHeaders) {
941      llhttp_set_lenient_headers(&parser_, 1);
942    }
943    if (lenient_flags & kLenientChunkedLength) {
944      llhttp_set_lenient_chunked_length(&parser_, 1);
945    }
946    if (lenient_flags & kLenientKeepAlive) {
947      llhttp_set_lenient_keep_alive(&parser_, 1);
948    }
949
950    header_nread_ = 0;
951    url_.Reset();
952    status_message_.Reset();
953    num_fields_ = 0;
954    num_values_ = 0;
955    have_flushed_ = false;
956    got_exception_ = false;
957    headers_completed_ = false;
958    max_http_header_size_ = max_http_header_size;
959  }
960
961
962  int TrackHeader(size_t len) {
963    header_nread_ += len;
964    if (header_nread_ >= max_http_header_size_) {
965      llhttp_set_error_reason(&parser_, "HPE_HEADER_OVERFLOW:Header overflow");
966      return HPE_USER;
967    }
968    return 0;
969  }
970
971
972  int MaybePause() {
973    if (!pending_pause_) {
974      return 0;
975    }
976
977    pending_pause_ = false;
978    llhttp_set_error_reason(&parser_, "Paused in callback");
979    return HPE_PAUSED;
980  }
981
982
983  bool IsNotIndicativeOfMemoryLeakAtExit() const override {
984    // HTTP parsers are able to emit events without any GC root referring
985    // to them, because they receive events directly from the underlying
986    // libuv resource.
987    return true;
988  }
989
990
991  llhttp_t parser_;
992  StringPtr fields_[kMaxHeaderFieldsCount];  // header fields
993  StringPtr values_[kMaxHeaderFieldsCount];  // header values
994  StringPtr url_;
995  StringPtr status_message_;
996  size_t num_fields_;
997  size_t num_values_;
998  bool have_flushed_;
999  bool got_exception_;
1000  size_t current_buffer_len_;
1001  const char* current_buffer_data_;
1002  bool headers_completed_ = false;
1003  bool pending_pause_ = false;
1004  uint64_t header_nread_ = 0;
1005  uint64_t chunk_extensions_nread_ = 0;
1006  uint64_t max_http_header_size_;
1007  uint64_t last_message_start_;
1008  ConnectionsList* connectionsList_;
1009
1010  BaseObjectPtr<BindingData> binding_data_;
1011
1012  // These are helper functions for filling `http_parser_settings`, which turn
1013  // a member function of Parser into a C-style HTTP parser callback.
1014  template <typename Parser, Parser> struct Proxy;
1015  template <typename Parser, typename ...Args, int (Parser::*Member)(Args...)>
1016  struct Proxy<int (Parser::*)(Args...), Member> {
1017    static int Raw(llhttp_t* p, Args ... args) {
1018      Parser* parser = ContainerOf(&Parser::parser_, p);
1019      int rv = (parser->*Member)(std::forward<Args>(args)...);
1020      if (rv == 0) {
1021        rv = parser->MaybePause();
1022      }
1023      return rv;
1024    }
1025  };
1026
1027  typedef int (Parser::*Call)();
1028  typedef int (Parser::*DataCall)(const char* at, size_t length);
1029
1030  static const llhttp_settings_t settings;
1031};
1032
1033bool ParserComparator::operator()(const Parser* lhs, const Parser* rhs) const {
1034  if (lhs->last_message_start_ == 0 && rhs->last_message_start_ == 0) {
1035    // When both parsers are idle, guarantee strict order by
1036    // comparing pointers as ints.
1037    return lhs < rhs;
1038  } else if (lhs->last_message_start_ == 0) {
1039    return true;
1040  } else if (rhs->last_message_start_ == 0) {
1041    return false;
1042  }
1043
1044  return lhs->last_message_start_ < rhs->last_message_start_;
1045}
1046
1047void ConnectionsList::New(const FunctionCallbackInfo<Value>& args) {
1048  Local<Context> context = args.GetIsolate()->GetCurrentContext();
1049  Environment* env = Environment::GetCurrent(context);
1050
1051  new ConnectionsList(env, args.This());
1052}
1053
1054void ConnectionsList::All(const FunctionCallbackInfo<Value>& args) {
1055  Isolate* isolate = args.GetIsolate();
1056
1057  ConnectionsList* list;
1058
1059  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1060
1061  std::vector<Local<Value>> result;
1062  result.reserve(list->all_connections_.size());
1063  for (auto parser : list->all_connections_) {
1064    result.emplace_back(parser->object());
1065  }
1066
1067  return args.GetReturnValue().Set(
1068      Array::New(isolate, result.data(), result.size()));
1069}
1070
1071void ConnectionsList::Idle(const FunctionCallbackInfo<Value>& args) {
1072  Isolate* isolate = args.GetIsolate();
1073
1074  ConnectionsList* list;
1075
1076  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1077
1078  std::vector<Local<Value>> result;
1079  result.reserve(list->all_connections_.size());
1080  for (auto parser : list->all_connections_) {
1081    if (parser->last_message_start_ == 0) {
1082      result.emplace_back(parser->object());
1083    }
1084  }
1085
1086  return args.GetReturnValue().Set(
1087      Array::New(isolate, result.data(), result.size()));
1088}
1089
1090void ConnectionsList::Active(const FunctionCallbackInfo<Value>& args) {
1091  Isolate* isolate = args.GetIsolate();
1092
1093  ConnectionsList* list;
1094
1095  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1096
1097  std::vector<Local<Value>> result;
1098  result.reserve(list->active_connections_.size());
1099  for (auto parser : list->active_connections_) {
1100    result.emplace_back(parser->object());
1101  }
1102
1103  return args.GetReturnValue().Set(
1104      Array::New(isolate, result.data(), result.size()));
1105}
1106
1107void ConnectionsList::Expired(const FunctionCallbackInfo<Value>& args) {
1108  Isolate* isolate = args.GetIsolate();
1109
1110  ConnectionsList* list;
1111
1112  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
1113  CHECK(args[0]->IsNumber());
1114  CHECK(args[1]->IsNumber());
1115  uint64_t headers_timeout =
1116    static_cast<uint64_t>(args[0].As<Uint32>()->Value()) * 1000000;
1117  uint64_t request_timeout =
1118    static_cast<uint64_t>(args[1].As<Uint32>()->Value()) * 1000000;
1119
1120  if (headers_timeout == 0 && request_timeout == 0) {
1121    return args.GetReturnValue().Set(Array::New(isolate, 0));
1122  } else if (request_timeout > 0 && headers_timeout > request_timeout) {
1123    std::swap(headers_timeout, request_timeout);
1124  }
1125
1126  // On IoT or embedded devices the uv_hrtime() may return the timestamp
1127  // that is smaller than configured timeout for headers or request
1128  // to prevent subtracting two unsigned integers
1129  // that can yield incorrect results we should check
1130  // if the 'now' is bigger than the timeout for headers or request
1131  const uint64_t now = uv_hrtime();
1132  const uint64_t headers_deadline =
1133      (headers_timeout > 0 && now > headers_timeout) ? now - headers_timeout
1134                                                     : 0;
1135  const uint64_t request_deadline =
1136      (request_timeout > 0 && now > request_timeout) ? now - request_timeout
1137                                                     : 0;
1138
1139  if (headers_deadline == 0 && request_deadline == 0) {
1140    return args.GetReturnValue().Set(Array::New(isolate, 0));
1141  }
1142
1143  auto iter = list->active_connections_.begin();
1144  auto end = list->active_connections_.end();
1145
1146  std::vector<Local<Value>> result;
1147  result.reserve(list->active_connections_.size());
1148  while (iter != end) {
1149    Parser* parser = *iter;
1150    iter++;
1151
1152    // Check for expiration.
1153    if (
1154      (!parser->headers_completed_ && headers_deadline > 0 &&
1155        parser->last_message_start_ < headers_deadline) ||
1156      (
1157        request_deadline > 0 &&
1158        parser->last_message_start_ < request_deadline)
1159    ) {
1160      result.emplace_back(parser->object());
1161
1162      list->active_connections_.erase(parser);
1163    }
1164  }
1165
1166  return args.GetReturnValue().Set(
1167      Array::New(isolate, result.data(), result.size()));
1168}
1169
1170const llhttp_settings_t Parser::settings = {
1171  Proxy<Call, &Parser::on_message_begin>::Raw,
1172  Proxy<DataCall, &Parser::on_url>::Raw,
1173  Proxy<DataCall, &Parser::on_status>::Raw,
1174  Proxy<DataCall, &Parser::on_header_field>::Raw,
1175  Proxy<DataCall, &Parser::on_header_value>::Raw,
1176  Proxy<Call, &Parser::on_headers_complete>::Raw,
1177  Proxy<DataCall, &Parser::on_chunk_extension>::Raw,
1178  Proxy<DataCall, &Parser::on_body>::Raw,
1179  Proxy<Call, &Parser::on_message_complete>::Raw,
1180  Proxy<Call, &Parser::on_chunk_header>::Raw,
1181  Proxy<Call, &Parser::on_chunk_complete>::Raw,
1182
1183  // on_url_complete
1184  nullptr,
1185  // on_status_complete
1186  nullptr,
1187  // on_header_field_complete
1188  nullptr,
1189  // on_header_value_complete
1190  nullptr,
1191};
1192
1193
1194void InitializeHttpParser(Local<Object> target,
1195                          Local<Value> unused,
1196                          Local<Context> context,
1197                          void* priv) {
1198  Realm* realm = Realm::GetCurrent(context);
1199  Environment* env = realm->env();
1200  Isolate* isolate = env->isolate();
1201  BindingData* const binding_data =
1202      realm->AddBindingData<BindingData>(context, target);
1203  if (binding_data == nullptr) return;
1204
1205  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, Parser::New);
1206  t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount);
1207
1208  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
1209         Integer::New(env->isolate(), HTTP_REQUEST));
1210  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
1211         Integer::New(env->isolate(), HTTP_RESPONSE));
1212  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageBegin"),
1213         Integer::NewFromUnsigned(env->isolate(), kOnMessageBegin));
1214  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
1215         Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
1216  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
1217         Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
1218  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
1219         Integer::NewFromUnsigned(env->isolate(), kOnBody));
1220  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
1221         Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
1222  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
1223         Integer::NewFromUnsigned(env->isolate(), kOnExecute));
1224  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnTimeout"),
1225         Integer::NewFromUnsigned(env->isolate(), kOnTimeout));
1226
1227  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientNone"),
1228         Integer::NewFromUnsigned(env->isolate(), kLenientNone));
1229  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientHeaders"),
1230         Integer::NewFromUnsigned(env->isolate(), kLenientHeaders));
1231  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientChunkedLength"),
1232         Integer::NewFromUnsigned(env->isolate(), kLenientChunkedLength));
1233  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientKeepAlive"),
1234         Integer::NewFromUnsigned(env->isolate(), kLenientKeepAlive));
1235  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientAll"),
1236         Integer::NewFromUnsigned(env->isolate(), kLenientAll));
1237
1238  Local<Array> methods = Array::New(env->isolate());
1239#define V(num, name, string)                                                  \
1240    methods->Set(env->context(),                                              \
1241        num, FIXED_ONE_BYTE_STRING(env->isolate(), #string)).Check();
1242  HTTP_METHOD_MAP(V)
1243#undef V
1244  target->Set(env->context(),
1245              FIXED_ONE_BYTE_STRING(env->isolate(), "methods"),
1246              methods).Check();
1247
1248  t->Inherit(AsyncWrap::GetConstructorTemplate(env));
1249  SetProtoMethod(isolate, t, "close", Parser::Close);
1250  SetProtoMethod(isolate, t, "free", Parser::Free);
1251  SetProtoMethod(isolate, t, "remove", Parser::Remove);
1252  SetProtoMethod(isolate, t, "execute", Parser::Execute);
1253  SetProtoMethod(isolate, t, "finish", Parser::Finish);
1254  SetProtoMethod(isolate, t, "initialize", Parser::Initialize);
1255  SetProtoMethod(isolate, t, "pause", Parser::Pause<true>);
1256  SetProtoMethod(isolate, t, "resume", Parser::Pause<false>);
1257  SetProtoMethod(isolate, t, "consume", Parser::Consume);
1258  SetProtoMethod(isolate, t, "unconsume", Parser::Unconsume);
1259  SetProtoMethod(isolate, t, "getCurrentBuffer", Parser::GetCurrentBuffer);
1260  SetProtoMethod(isolate, t, "duration", Parser::Duration);
1261  SetProtoMethod(isolate, t, "headersCompleted", Parser::HeadersCompleted);
1262
1263  SetConstructorFunction(context, target, "HTTPParser", t);
1264
1265  Local<FunctionTemplate> c =
1266      NewFunctionTemplate(isolate, ConnectionsList::New);
1267  c->InstanceTemplate()
1268    ->SetInternalFieldCount(ConnectionsList::kInternalFieldCount);
1269  SetProtoMethod(isolate, c, "all", ConnectionsList::All);
1270  SetProtoMethod(isolate, c, "idle", ConnectionsList::Idle);
1271  SetProtoMethod(isolate, c, "active", ConnectionsList::Active);
1272  SetProtoMethod(isolate, c, "expired", ConnectionsList::Expired);
1273  SetConstructorFunction(context, target, "ConnectionsList", c);
1274}
1275
1276}  // anonymous namespace
1277}  // namespace node
1278
1279NODE_BINDING_CONTEXT_AWARE_INTERNAL(http_parser, node::InitializeHttpParser)
1280