11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "node.h"
231cb0ef41Sopenharmony_ci#include "node_buffer.h"
241cb0ef41Sopenharmony_ci#include "util.h"
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci#include "async_wrap-inl.h"
271cb0ef41Sopenharmony_ci#include "env-inl.h"
281cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h"
291cb0ef41Sopenharmony_ci#include "stream_base-inl.h"
301cb0ef41Sopenharmony_ci#include "v8.h"
311cb0ef41Sopenharmony_ci#include "llhttp.h"
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci#include <cstdlib>  // free()
341cb0ef41Sopenharmony_ci#include <cstring>  // strdup(), strchr()
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci// This is a binding to llhttp (https://github.com/nodejs/llhttp)
381cb0ef41Sopenharmony_ci// The goal is to decouple sockets from parsing for more javascript-level
391cb0ef41Sopenharmony_ci// agility. A Buffer is read from a socket and passed to parser.execute().
401cb0ef41Sopenharmony_ci// The parser then issues callbacks with slices of the data
411cb0ef41Sopenharmony_ci//     parser.onMessageBegin
421cb0ef41Sopenharmony_ci//     parser.onPath
431cb0ef41Sopenharmony_ci//     parser.onBody
441cb0ef41Sopenharmony_ci//     ...
451cb0ef41Sopenharmony_ci// No copying is performed when slicing the buffer, only small reference
461cb0ef41Sopenharmony_ci// allocations.
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_cinamespace node {
501cb0ef41Sopenharmony_cinamespace {  // NOLINT(build/namespaces)
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciusing v8::Array;
531cb0ef41Sopenharmony_ciusing v8::Boolean;
541cb0ef41Sopenharmony_ciusing v8::Context;
551cb0ef41Sopenharmony_ciusing v8::EscapableHandleScope;
561cb0ef41Sopenharmony_ciusing v8::Exception;
571cb0ef41Sopenharmony_ciusing v8::Function;
581cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
591cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
601cb0ef41Sopenharmony_ciusing v8::HandleScope;
611cb0ef41Sopenharmony_ciusing v8::Int32;
621cb0ef41Sopenharmony_ciusing v8::Integer;
631cb0ef41Sopenharmony_ciusing v8::Isolate;
641cb0ef41Sopenharmony_ciusing v8::Local;
651cb0ef41Sopenharmony_ciusing v8::MaybeLocal;
661cb0ef41Sopenharmony_ciusing v8::Number;
671cb0ef41Sopenharmony_ciusing v8::Object;
681cb0ef41Sopenharmony_ciusing v8::String;
691cb0ef41Sopenharmony_ciusing v8::Uint32;
701cb0ef41Sopenharmony_ciusing v8::Undefined;
711cb0ef41Sopenharmony_ciusing v8::Value;
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ciconst uint32_t kOnMessageBegin = 0;
741cb0ef41Sopenharmony_ciconst uint32_t kOnHeaders = 1;
751cb0ef41Sopenharmony_ciconst uint32_t kOnHeadersComplete = 2;
761cb0ef41Sopenharmony_ciconst uint32_t kOnBody = 3;
771cb0ef41Sopenharmony_ciconst uint32_t kOnMessageComplete = 4;
781cb0ef41Sopenharmony_ciconst uint32_t kOnExecute = 5;
791cb0ef41Sopenharmony_ciconst uint32_t kOnTimeout = 6;
801cb0ef41Sopenharmony_ci// Any more fields than this will be flushed into JS
811cb0ef41Sopenharmony_ciconst size_t kMaxHeaderFieldsCount = 32;
821cb0ef41Sopenharmony_ci// Maximum size of chunk extensions
831cb0ef41Sopenharmony_ciconst size_t kMaxChunkExtensionsSize = 16384;
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ciconst uint32_t kLenientNone = 0;
861cb0ef41Sopenharmony_ciconst uint32_t kLenientHeaders = 1 << 0;
871cb0ef41Sopenharmony_ciconst uint32_t kLenientChunkedLength = 1 << 1;
881cb0ef41Sopenharmony_ciconst uint32_t kLenientKeepAlive = 1 << 2;
891cb0ef41Sopenharmony_ciconst uint32_t kLenientAll = kLenientHeaders | kLenientChunkedLength |
901cb0ef41Sopenharmony_ci  kLenientKeepAlive;
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciinline bool IsOWS(char c) {
931cb0ef41Sopenharmony_ci  return c == ' ' || c == '\t';
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ciclass BindingData : public BaseObject {
971cb0ef41Sopenharmony_ci public:
981cb0ef41Sopenharmony_ci  BindingData(Realm* realm, Local<Object> obj) : BaseObject(realm, obj) {}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  SET_BINDING_ID(http_parser_binding_data)
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  std::vector<char> parser_buffer;
1031cb0ef41Sopenharmony_ci  bool parser_buffer_in_use = false;
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  void MemoryInfo(MemoryTracker* tracker) const override {
1061cb0ef41Sopenharmony_ci    tracker->TrackField("parser_buffer", parser_buffer);
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci  SET_SELF_SIZE(BindingData)
1091cb0ef41Sopenharmony_ci  SET_MEMORY_INFO_NAME(BindingData)
1101cb0ef41Sopenharmony_ci};
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci// helper class for the Parser
1131cb0ef41Sopenharmony_cistruct StringPtr {
1141cb0ef41Sopenharmony_ci  StringPtr() {
1151cb0ef41Sopenharmony_ci    on_heap_ = false;
1161cb0ef41Sopenharmony_ci    Reset();
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  ~StringPtr() {
1211cb0ef41Sopenharmony_ci    Reset();
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  // If str_ does not point to a heap string yet, this function makes it do
1261cb0ef41Sopenharmony_ci  // so. This is called at the end of each http_parser_execute() so as not
1271cb0ef41Sopenharmony_ci  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
1281cb0ef41Sopenharmony_ci  void Save() {
1291cb0ef41Sopenharmony_ci    if (!on_heap_ && size_ > 0) {
1301cb0ef41Sopenharmony_ci      char* s = new char[size_];
1311cb0ef41Sopenharmony_ci      memcpy(s, str_, size_);
1321cb0ef41Sopenharmony_ci      str_ = s;
1331cb0ef41Sopenharmony_ci      on_heap_ = true;
1341cb0ef41Sopenharmony_ci    }
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  void Reset() {
1391cb0ef41Sopenharmony_ci    if (on_heap_) {
1401cb0ef41Sopenharmony_ci      delete[] str_;
1411cb0ef41Sopenharmony_ci      on_heap_ = false;
1421cb0ef41Sopenharmony_ci    }
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci    str_ = nullptr;
1451cb0ef41Sopenharmony_ci    size_ = 0;
1461cb0ef41Sopenharmony_ci  }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  void Update(const char* str, size_t size) {
1501cb0ef41Sopenharmony_ci    if (str_ == nullptr) {
1511cb0ef41Sopenharmony_ci      str_ = str;
1521cb0ef41Sopenharmony_ci    } else if (on_heap_ || str_ + size_ != str) {
1531cb0ef41Sopenharmony_ci      // Non-consecutive input, make a copy on the heap.
1541cb0ef41Sopenharmony_ci      // TODO(bnoordhuis) Use slab allocation, O(n) allocs is bad.
1551cb0ef41Sopenharmony_ci      char* s = new char[size_ + size];
1561cb0ef41Sopenharmony_ci      memcpy(s, str_, size_);
1571cb0ef41Sopenharmony_ci      memcpy(s + size_, str, size);
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci      if (on_heap_)
1601cb0ef41Sopenharmony_ci        delete[] str_;
1611cb0ef41Sopenharmony_ci      else
1621cb0ef41Sopenharmony_ci        on_heap_ = true;
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci      str_ = s;
1651cb0ef41Sopenharmony_ci    }
1661cb0ef41Sopenharmony_ci    size_ += size;
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  Local<String> ToString(Environment* env) const {
1711cb0ef41Sopenharmony_ci    if (size_ != 0)
1721cb0ef41Sopenharmony_ci      return OneByteString(env->isolate(), str_, size_);
1731cb0ef41Sopenharmony_ci    else
1741cb0ef41Sopenharmony_ci      return String::Empty(env->isolate());
1751cb0ef41Sopenharmony_ci  }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  // Strip trailing OWS (SPC or HTAB) from string.
1791cb0ef41Sopenharmony_ci  Local<String> ToTrimmedString(Environment* env) {
1801cb0ef41Sopenharmony_ci    while (size_ > 0 && IsOWS(str_[size_ - 1])) {
1811cb0ef41Sopenharmony_ci      size_--;
1821cb0ef41Sopenharmony_ci    }
1831cb0ef41Sopenharmony_ci    return ToString(env);
1841cb0ef41Sopenharmony_ci  }
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  const char* str_;
1881cb0ef41Sopenharmony_ci  bool on_heap_;
1891cb0ef41Sopenharmony_ci  size_t size_;
1901cb0ef41Sopenharmony_ci};
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ciclass Parser;
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_cistruct ParserComparator {
1951cb0ef41Sopenharmony_ci  bool operator()(const Parser* lhs, const Parser* rhs) const;
1961cb0ef41Sopenharmony_ci};
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ciclass ConnectionsList : public BaseObject {
1991cb0ef41Sopenharmony_ci public:
2001cb0ef41Sopenharmony_ci    static void New(const FunctionCallbackInfo<Value>& args);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci    static void All(const FunctionCallbackInfo<Value>& args);
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci    static void Idle(const FunctionCallbackInfo<Value>& args);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci    static void Active(const FunctionCallbackInfo<Value>& args);
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci    static void Expired(const FunctionCallbackInfo<Value>& args);
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci    void Push(Parser* parser) {
2111cb0ef41Sopenharmony_ci      all_connections_.insert(parser);
2121cb0ef41Sopenharmony_ci    }
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci    void Pop(Parser* parser) {
2151cb0ef41Sopenharmony_ci      all_connections_.erase(parser);
2161cb0ef41Sopenharmony_ci    }
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci    void PushActive(Parser* parser) {
2191cb0ef41Sopenharmony_ci      active_connections_.insert(parser);
2201cb0ef41Sopenharmony_ci    }
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci    void PopActive(Parser* parser) {
2231cb0ef41Sopenharmony_ci      active_connections_.erase(parser);
2241cb0ef41Sopenharmony_ci    }
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci    SET_NO_MEMORY_INFO()
2271cb0ef41Sopenharmony_ci    SET_MEMORY_INFO_NAME(ConnectionsList)
2281cb0ef41Sopenharmony_ci    SET_SELF_SIZE(ConnectionsList)
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci private:
2311cb0ef41Sopenharmony_ci    ConnectionsList(Environment* env, Local<Object> object)
2321cb0ef41Sopenharmony_ci      : BaseObject(env, object) {
2331cb0ef41Sopenharmony_ci        MakeWeak();
2341cb0ef41Sopenharmony_ci      }
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci    std::set<Parser*, ParserComparator> all_connections_;
2371cb0ef41Sopenharmony_ci    std::set<Parser*, ParserComparator> active_connections_;
2381cb0ef41Sopenharmony_ci};
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ciclass Parser : public AsyncWrap, public StreamListener {
2411cb0ef41Sopenharmony_ci  friend class ConnectionsList;
2421cb0ef41Sopenharmony_ci  friend struct ParserComparator;
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci public:
2451cb0ef41Sopenharmony_ci  Parser(BindingData* binding_data, Local<Object> wrap)
2461cb0ef41Sopenharmony_ci      : AsyncWrap(binding_data->env(), wrap),
2471cb0ef41Sopenharmony_ci        current_buffer_len_(0),
2481cb0ef41Sopenharmony_ci        current_buffer_data_(nullptr),
2491cb0ef41Sopenharmony_ci        binding_data_(binding_data) {
2501cb0ef41Sopenharmony_ci  }
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci  SET_NO_MEMORY_INFO()
2531cb0ef41Sopenharmony_ci  SET_MEMORY_INFO_NAME(Parser)
2541cb0ef41Sopenharmony_ci  SET_SELF_SIZE(Parser)
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  int on_message_begin() {
2571cb0ef41Sopenharmony_ci    // Important: Pop from the lists BEFORE resetting the last_message_start_
2581cb0ef41Sopenharmony_ci    // otherwise std::set.erase will fail.
2591cb0ef41Sopenharmony_ci    if (connectionsList_ != nullptr) {
2601cb0ef41Sopenharmony_ci      connectionsList_->Pop(this);
2611cb0ef41Sopenharmony_ci      connectionsList_->PopActive(this);
2621cb0ef41Sopenharmony_ci    }
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci    num_fields_ = num_values_ = 0;
2651cb0ef41Sopenharmony_ci    headers_completed_ = false;
2661cb0ef41Sopenharmony_ci    chunk_extensions_nread_ = 0;
2671cb0ef41Sopenharmony_ci    last_message_start_ = uv_hrtime();
2681cb0ef41Sopenharmony_ci    url_.Reset();
2691cb0ef41Sopenharmony_ci    status_message_.Reset();
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci    if (connectionsList_ != nullptr) {
2721cb0ef41Sopenharmony_ci      connectionsList_->Push(this);
2731cb0ef41Sopenharmony_ci      connectionsList_->PushActive(this);
2741cb0ef41Sopenharmony_ci    }
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci    Local<Value> cb = object()->Get(env()->context(), kOnMessageBegin)
2771cb0ef41Sopenharmony_ci                              .ToLocalChecked();
2781cb0ef41Sopenharmony_ci    if (cb->IsFunction()) {
2791cb0ef41Sopenharmony_ci      InternalCallbackScope callback_scope(
2801cb0ef41Sopenharmony_ci        this, InternalCallbackScope::kSkipTaskQueues);
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci      MaybeLocal<Value> r = cb.As<Function>()->Call(
2831cb0ef41Sopenharmony_ci        env()->context(), object(), 0, nullptr);
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci      if (r.IsEmpty()) callback_scope.MarkAsFailed();
2861cb0ef41Sopenharmony_ci    }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci    return 0;
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  int on_url(const char* at, size_t length) {
2931cb0ef41Sopenharmony_ci    int rv = TrackHeader(length);
2941cb0ef41Sopenharmony_ci    if (rv != 0) {
2951cb0ef41Sopenharmony_ci      return rv;
2961cb0ef41Sopenharmony_ci    }
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci    url_.Update(at, length);
2991cb0ef41Sopenharmony_ci    return 0;
3001cb0ef41Sopenharmony_ci  }
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  int on_status(const char* at, size_t length) {
3041cb0ef41Sopenharmony_ci    int rv = TrackHeader(length);
3051cb0ef41Sopenharmony_ci    if (rv != 0) {
3061cb0ef41Sopenharmony_ci      return rv;
3071cb0ef41Sopenharmony_ci    }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci    status_message_.Update(at, length);
3101cb0ef41Sopenharmony_ci    return 0;
3111cb0ef41Sopenharmony_ci  }
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci  int on_header_field(const char* at, size_t length) {
3151cb0ef41Sopenharmony_ci    int rv = TrackHeader(length);
3161cb0ef41Sopenharmony_ci    if (rv != 0) {
3171cb0ef41Sopenharmony_ci      return rv;
3181cb0ef41Sopenharmony_ci    }
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci    if (num_fields_ == num_values_) {
3211cb0ef41Sopenharmony_ci      // start of new field name
3221cb0ef41Sopenharmony_ci      num_fields_++;
3231cb0ef41Sopenharmony_ci      if (num_fields_ == kMaxHeaderFieldsCount) {
3241cb0ef41Sopenharmony_ci        // ran out of space - flush to javascript land
3251cb0ef41Sopenharmony_ci        Flush();
3261cb0ef41Sopenharmony_ci        num_fields_ = 1;
3271cb0ef41Sopenharmony_ci        num_values_ = 0;
3281cb0ef41Sopenharmony_ci      }
3291cb0ef41Sopenharmony_ci      fields_[num_fields_ - 1].Reset();
3301cb0ef41Sopenharmony_ci    }
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci    CHECK_LT(num_fields_, kMaxHeaderFieldsCount);
3331cb0ef41Sopenharmony_ci    CHECK_EQ(num_fields_, num_values_ + 1);
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci    fields_[num_fields_ - 1].Update(at, length);
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci    return 0;
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  int on_header_value(const char* at, size_t length) {
3421cb0ef41Sopenharmony_ci    int rv = TrackHeader(length);
3431cb0ef41Sopenharmony_ci    if (rv != 0) {
3441cb0ef41Sopenharmony_ci      return rv;
3451cb0ef41Sopenharmony_ci    }
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci    if (num_values_ != num_fields_) {
3481cb0ef41Sopenharmony_ci      // start of new header value
3491cb0ef41Sopenharmony_ci      num_values_++;
3501cb0ef41Sopenharmony_ci      values_[num_values_ - 1].Reset();
3511cb0ef41Sopenharmony_ci    }
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci    CHECK_LT(num_values_, arraysize(values_));
3541cb0ef41Sopenharmony_ci    CHECK_EQ(num_values_, num_fields_);
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci    values_[num_values_ - 1].Update(at, length);
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci    return 0;
3591cb0ef41Sopenharmony_ci  }
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  int on_headers_complete() {
3631cb0ef41Sopenharmony_ci    headers_completed_ = true;
3641cb0ef41Sopenharmony_ci    header_nread_ = 0;
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci    // Arguments for the on-headers-complete javascript callback. This
3671cb0ef41Sopenharmony_ci    // list needs to be kept in sync with the actual argument list for
3681cb0ef41Sopenharmony_ci    // `parserOnHeadersComplete` in lib/_http_common.js.
3691cb0ef41Sopenharmony_ci    enum on_headers_complete_arg_index {
3701cb0ef41Sopenharmony_ci      A_VERSION_MAJOR = 0,
3711cb0ef41Sopenharmony_ci      A_VERSION_MINOR,
3721cb0ef41Sopenharmony_ci      A_HEADERS,
3731cb0ef41Sopenharmony_ci      A_METHOD,
3741cb0ef41Sopenharmony_ci      A_URL,
3751cb0ef41Sopenharmony_ci      A_STATUS_CODE,
3761cb0ef41Sopenharmony_ci      A_STATUS_MESSAGE,
3771cb0ef41Sopenharmony_ci      A_UPGRADE,
3781cb0ef41Sopenharmony_ci      A_SHOULD_KEEP_ALIVE,
3791cb0ef41Sopenharmony_ci      A_MAX
3801cb0ef41Sopenharmony_ci    };
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci    Local<Value> argv[A_MAX];
3831cb0ef41Sopenharmony_ci    Local<Object> obj = object();
3841cb0ef41Sopenharmony_ci    Local<Value> cb = obj->Get(env()->context(),
3851cb0ef41Sopenharmony_ci                               kOnHeadersComplete).ToLocalChecked();
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci    if (!cb->IsFunction())
3881cb0ef41Sopenharmony_ci      return 0;
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci    Local<Value> undefined = Undefined(env()->isolate());
3911cb0ef41Sopenharmony_ci    for (size_t i = 0; i < arraysize(argv); i++)
3921cb0ef41Sopenharmony_ci      argv[i] = undefined;
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci    if (have_flushed_) {
3951cb0ef41Sopenharmony_ci      // Slow case, flush remaining headers.
3961cb0ef41Sopenharmony_ci      Flush();
3971cb0ef41Sopenharmony_ci    } else {
3981cb0ef41Sopenharmony_ci      // Fast case, pass headers and URL to JS land.
3991cb0ef41Sopenharmony_ci      argv[A_HEADERS] = CreateHeaders();
4001cb0ef41Sopenharmony_ci      if (parser_.type == HTTP_REQUEST)
4011cb0ef41Sopenharmony_ci        argv[A_URL] = url_.ToString(env());
4021cb0ef41Sopenharmony_ci    }
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci    num_fields_ = 0;
4051cb0ef41Sopenharmony_ci    num_values_ = 0;
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci    // METHOD
4081cb0ef41Sopenharmony_ci    if (parser_.type == HTTP_REQUEST) {
4091cb0ef41Sopenharmony_ci      argv[A_METHOD] =
4101cb0ef41Sopenharmony_ci          Uint32::NewFromUnsigned(env()->isolate(), parser_.method);
4111cb0ef41Sopenharmony_ci    }
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci    // STATUS
4141cb0ef41Sopenharmony_ci    if (parser_.type == HTTP_RESPONSE) {
4151cb0ef41Sopenharmony_ci      argv[A_STATUS_CODE] =
4161cb0ef41Sopenharmony_ci          Integer::New(env()->isolate(), parser_.status_code);
4171cb0ef41Sopenharmony_ci      argv[A_STATUS_MESSAGE] = status_message_.ToString(env());
4181cb0ef41Sopenharmony_ci    }
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci    // VERSION
4211cb0ef41Sopenharmony_ci    argv[A_VERSION_MAJOR] = Integer::New(env()->isolate(), parser_.http_major);
4221cb0ef41Sopenharmony_ci    argv[A_VERSION_MINOR] = Integer::New(env()->isolate(), parser_.http_minor);
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci    bool should_keep_alive;
4251cb0ef41Sopenharmony_ci    should_keep_alive = llhttp_should_keep_alive(&parser_);
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci    argv[A_SHOULD_KEEP_ALIVE] =
4281cb0ef41Sopenharmony_ci        Boolean::New(env()->isolate(), should_keep_alive);
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci    argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade);
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci    MaybeLocal<Value> head_response;
4331cb0ef41Sopenharmony_ci    {
4341cb0ef41Sopenharmony_ci      InternalCallbackScope callback_scope(
4351cb0ef41Sopenharmony_ci          this, InternalCallbackScope::kSkipTaskQueues);
4361cb0ef41Sopenharmony_ci      head_response = cb.As<Function>()->Call(
4371cb0ef41Sopenharmony_ci          env()->context(), object(), arraysize(argv), argv);
4381cb0ef41Sopenharmony_ci      if (head_response.IsEmpty()) callback_scope.MarkAsFailed();
4391cb0ef41Sopenharmony_ci    }
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci    int64_t val;
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci    if (head_response.IsEmpty() || !head_response.ToLocalChecked()
4441cb0ef41Sopenharmony_ci                                        ->IntegerValue(env()->context())
4451cb0ef41Sopenharmony_ci                                        .To(&val)) {
4461cb0ef41Sopenharmony_ci      got_exception_ = true;
4471cb0ef41Sopenharmony_ci      return -1;
4481cb0ef41Sopenharmony_ci    }
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ci    return static_cast<int>(val);
4511cb0ef41Sopenharmony_ci  }
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci  int on_body(const char* at, size_t length) {
4551cb0ef41Sopenharmony_ci    if (length == 0)
4561cb0ef41Sopenharmony_ci      return 0;
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci    Environment* env = this->env();
4591cb0ef41Sopenharmony_ci    HandleScope handle_scope(env->isolate());
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci    Local<Value> cb = object()->Get(env->context(), kOnBody).ToLocalChecked();
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci    if (!cb->IsFunction())
4641cb0ef41Sopenharmony_ci      return 0;
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci    Local<Value> buffer = Buffer::Copy(env, at, length).ToLocalChecked();
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(), 1, &buffer);
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci    if (r.IsEmpty()) {
4711cb0ef41Sopenharmony_ci      got_exception_ = true;
4721cb0ef41Sopenharmony_ci      llhttp_set_error_reason(&parser_, "HPE_JS_EXCEPTION:JS Exception");
4731cb0ef41Sopenharmony_ci      return HPE_USER;
4741cb0ef41Sopenharmony_ci    }
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci    return 0;
4771cb0ef41Sopenharmony_ci  }
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci  int on_message_complete() {
4811cb0ef41Sopenharmony_ci    HandleScope scope(env()->isolate());
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci    // Important: Pop from the lists BEFORE resetting the last_message_start_
4841cb0ef41Sopenharmony_ci    // otherwise std::set.erase will fail.
4851cb0ef41Sopenharmony_ci    if (connectionsList_ != nullptr) {
4861cb0ef41Sopenharmony_ci      connectionsList_->Pop(this);
4871cb0ef41Sopenharmony_ci      connectionsList_->PopActive(this);
4881cb0ef41Sopenharmony_ci    }
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci    last_message_start_ = 0;
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci    if (connectionsList_ != nullptr) {
4931cb0ef41Sopenharmony_ci      connectionsList_->Push(this);
4941cb0ef41Sopenharmony_ci    }
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci    if (num_fields_)
4971cb0ef41Sopenharmony_ci      Flush();  // Flush trailing HTTP headers.
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci    Local<Object> obj = object();
5001cb0ef41Sopenharmony_ci    Local<Value> cb = obj->Get(env()->context(),
5011cb0ef41Sopenharmony_ci                               kOnMessageComplete).ToLocalChecked();
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci    if (!cb->IsFunction())
5041cb0ef41Sopenharmony_ci      return 0;
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci    MaybeLocal<Value> r;
5071cb0ef41Sopenharmony_ci    {
5081cb0ef41Sopenharmony_ci      InternalCallbackScope callback_scope(
5091cb0ef41Sopenharmony_ci          this, InternalCallbackScope::kSkipTaskQueues);
5101cb0ef41Sopenharmony_ci      r = cb.As<Function>()->Call(env()->context(), object(), 0, nullptr);
5111cb0ef41Sopenharmony_ci      if (r.IsEmpty()) callback_scope.MarkAsFailed();
5121cb0ef41Sopenharmony_ci    }
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci    if (r.IsEmpty()) {
5151cb0ef41Sopenharmony_ci      got_exception_ = true;
5161cb0ef41Sopenharmony_ci      return -1;
5171cb0ef41Sopenharmony_ci    }
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ci    return 0;
5201cb0ef41Sopenharmony_ci  }
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ci  int on_chunk_extension(const char* at, size_t length) {
5231cb0ef41Sopenharmony_ci    chunk_extensions_nread_ += length;
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci    if (chunk_extensions_nread_ > kMaxChunkExtensionsSize) {
5261cb0ef41Sopenharmony_ci      llhttp_set_error_reason(&parser_,
5271cb0ef41Sopenharmony_ci        "HPE_CHUNK_EXTENSIONS_OVERFLOW:Chunk extensions overflow");
5281cb0ef41Sopenharmony_ci      return HPE_USER;
5291cb0ef41Sopenharmony_ci    }
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci    return 0;
5321cb0ef41Sopenharmony_ci  }
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci  // Reset nread for the next chunk and also reset the extensions counter
5351cb0ef41Sopenharmony_ci  int on_chunk_header() {
5361cb0ef41Sopenharmony_ci    header_nread_ = 0;
5371cb0ef41Sopenharmony_ci    chunk_extensions_nread_ = 0;
5381cb0ef41Sopenharmony_ci    return 0;
5391cb0ef41Sopenharmony_ci  }
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  // Reset nread for the next chunk
5431cb0ef41Sopenharmony_ci  int on_chunk_complete() {
5441cb0ef41Sopenharmony_ci    header_nread_ = 0;
5451cb0ef41Sopenharmony_ci    return 0;
5461cb0ef41Sopenharmony_ci  }
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci  static void New(const FunctionCallbackInfo<Value>& args) {
5491cb0ef41Sopenharmony_ci    BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
5501cb0ef41Sopenharmony_ci    new Parser(binding_data, args.This());
5511cb0ef41Sopenharmony_ci  }
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  static void Close(const FunctionCallbackInfo<Value>& args) {
5551cb0ef41Sopenharmony_ci    Parser* parser;
5561cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
5571cb0ef41Sopenharmony_ci
5581cb0ef41Sopenharmony_ci    delete parser;
5591cb0ef41Sopenharmony_ci  }
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ci  static void Free(const FunctionCallbackInfo<Value>& args) {
5631cb0ef41Sopenharmony_ci    Parser* parser;
5641cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci    // Since the Parser destructor isn't going to run the destroy() callbacks
5671cb0ef41Sopenharmony_ci    // it needs to be triggered manually.
5681cb0ef41Sopenharmony_ci    parser->EmitTraceEventDestroy();
5691cb0ef41Sopenharmony_ci    parser->EmitDestroy();
5701cb0ef41Sopenharmony_ci  }
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  static void Remove(const FunctionCallbackInfo<Value>& args) {
5731cb0ef41Sopenharmony_ci    Parser* parser;
5741cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ci    if (parser->connectionsList_ != nullptr) {
5771cb0ef41Sopenharmony_ci      parser->connectionsList_->Pop(parser);
5781cb0ef41Sopenharmony_ci      parser->connectionsList_->PopActive(parser);
5791cb0ef41Sopenharmony_ci    }
5801cb0ef41Sopenharmony_ci  }
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  void Save() {
5831cb0ef41Sopenharmony_ci    url_.Save();
5841cb0ef41Sopenharmony_ci    status_message_.Save();
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_ci    for (size_t i = 0; i < num_fields_; i++) {
5871cb0ef41Sopenharmony_ci      fields_[i].Save();
5881cb0ef41Sopenharmony_ci    }
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci    for (size_t i = 0; i < num_values_; i++) {
5911cb0ef41Sopenharmony_ci      values_[i].Save();
5921cb0ef41Sopenharmony_ci    }
5931cb0ef41Sopenharmony_ci  }
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci  // var bytesParsed = parser->execute(buffer);
5961cb0ef41Sopenharmony_ci  static void Execute(const FunctionCallbackInfo<Value>& args) {
5971cb0ef41Sopenharmony_ci    Parser* parser;
5981cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci    ArrayBufferViewContents<char> buffer(args[0]);
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ci    Local<Value> ret = parser->Execute(buffer.data(), buffer.length());
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci    if (!ret.IsEmpty())
6051cb0ef41Sopenharmony_ci      args.GetReturnValue().Set(ret);
6061cb0ef41Sopenharmony_ci  }
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci  static void Finish(const FunctionCallbackInfo<Value>& args) {
6101cb0ef41Sopenharmony_ci    Parser* parser;
6111cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci    Local<Value> ret = parser->Execute(nullptr, 0);
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci    if (!ret.IsEmpty())
6161cb0ef41Sopenharmony_ci      args.GetReturnValue().Set(ret);
6171cb0ef41Sopenharmony_ci  }
6181cb0ef41Sopenharmony_ci
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci  static void Initialize(const FunctionCallbackInfo<Value>& args) {
6211cb0ef41Sopenharmony_ci    Environment* env = Environment::GetCurrent(args);
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci    uint64_t max_http_header_size = 0;
6241cb0ef41Sopenharmony_ci    uint32_t lenient_flags = kLenientNone;
6251cb0ef41Sopenharmony_ci    ConnectionsList* connectionsList = nullptr;
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci    CHECK(args[0]->IsInt32());
6281cb0ef41Sopenharmony_ci    CHECK(args[1]->IsObject());
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci    if (args.Length() > 2) {
6311cb0ef41Sopenharmony_ci      CHECK(args[2]->IsNumber());
6321cb0ef41Sopenharmony_ci      max_http_header_size =
6331cb0ef41Sopenharmony_ci          static_cast<uint64_t>(args[2].As<Number>()->Value());
6341cb0ef41Sopenharmony_ci    }
6351cb0ef41Sopenharmony_ci    if (max_http_header_size == 0) {
6361cb0ef41Sopenharmony_ci      max_http_header_size = env->options()->max_http_header_size;
6371cb0ef41Sopenharmony_ci    }
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci    if (args.Length() > 3) {
6401cb0ef41Sopenharmony_ci      CHECK(args[3]->IsInt32());
6411cb0ef41Sopenharmony_ci      lenient_flags = args[3].As<Int32>()->Value();
6421cb0ef41Sopenharmony_ci    }
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci    if (args.Length() > 4 && !args[4]->IsNullOrUndefined()) {
6451cb0ef41Sopenharmony_ci      CHECK(args[4]->IsObject());
6461cb0ef41Sopenharmony_ci      ASSIGN_OR_RETURN_UNWRAP(&connectionsList, args[4]);
6471cb0ef41Sopenharmony_ci    }
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci    llhttp_type_t type =
6501cb0ef41Sopenharmony_ci        static_cast<llhttp_type_t>(args[0].As<Int32>()->Value());
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci    CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
6531cb0ef41Sopenharmony_ci    Parser* parser;
6541cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
6551cb0ef41Sopenharmony_ci    // Should always be called from the same context.
6561cb0ef41Sopenharmony_ci    CHECK_EQ(env, parser->env());
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci    AsyncWrap::ProviderType provider =
6591cb0ef41Sopenharmony_ci        (type == HTTP_REQUEST ?
6601cb0ef41Sopenharmony_ci            AsyncWrap::PROVIDER_HTTPINCOMINGMESSAGE
6611cb0ef41Sopenharmony_ci            : AsyncWrap::PROVIDER_HTTPCLIENTREQUEST);
6621cb0ef41Sopenharmony_ci
6631cb0ef41Sopenharmony_ci    parser->set_provider_type(provider);
6641cb0ef41Sopenharmony_ci    parser->AsyncReset(args[1].As<Object>());
6651cb0ef41Sopenharmony_ci    parser->Init(type, max_http_header_size, lenient_flags);
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci    if (connectionsList != nullptr) {
6681cb0ef41Sopenharmony_ci      parser->connectionsList_ = connectionsList;
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci      // This protects from a DoS attack where an attacker establishes
6711cb0ef41Sopenharmony_ci      // the connection without sending any data on applications where
6721cb0ef41Sopenharmony_ci      // server.timeout is left to the default value of zero.
6731cb0ef41Sopenharmony_ci      parser->last_message_start_ = uv_hrtime();
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci      // Important: Push into the lists AFTER setting the last_message_start_
6761cb0ef41Sopenharmony_ci      // otherwise std::set.erase will fail later.
6771cb0ef41Sopenharmony_ci      parser->connectionsList_->Push(parser);
6781cb0ef41Sopenharmony_ci      parser->connectionsList_->PushActive(parser);
6791cb0ef41Sopenharmony_ci    } else {
6801cb0ef41Sopenharmony_ci      parser->connectionsList_ = nullptr;
6811cb0ef41Sopenharmony_ci    }
6821cb0ef41Sopenharmony_ci  }
6831cb0ef41Sopenharmony_ci
6841cb0ef41Sopenharmony_ci  template <bool should_pause>
6851cb0ef41Sopenharmony_ci  static void Pause(const FunctionCallbackInfo<Value>& args) {
6861cb0ef41Sopenharmony_ci    Environment* env = Environment::GetCurrent(args);
6871cb0ef41Sopenharmony_ci    Parser* parser;
6881cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
6891cb0ef41Sopenharmony_ci    // Should always be called from the same context.
6901cb0ef41Sopenharmony_ci    CHECK_EQ(env, parser->env());
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci    if constexpr (should_pause) {
6931cb0ef41Sopenharmony_ci      llhttp_pause(&parser->parser_);
6941cb0ef41Sopenharmony_ci    } else {
6951cb0ef41Sopenharmony_ci      llhttp_resume(&parser->parser_);
6961cb0ef41Sopenharmony_ci    }
6971cb0ef41Sopenharmony_ci  }
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci  static void Consume(const FunctionCallbackInfo<Value>& args) {
7011cb0ef41Sopenharmony_ci    Parser* parser;
7021cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
7031cb0ef41Sopenharmony_ci    CHECK(args[0]->IsObject());
7041cb0ef41Sopenharmony_ci    StreamBase* stream = StreamBase::FromObject(args[0].As<Object>());
7051cb0ef41Sopenharmony_ci    CHECK_NOT_NULL(stream);
7061cb0ef41Sopenharmony_ci    stream->PushStreamListener(parser);
7071cb0ef41Sopenharmony_ci  }
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci
7101cb0ef41Sopenharmony_ci  static void Unconsume(const FunctionCallbackInfo<Value>& args) {
7111cb0ef41Sopenharmony_ci    Parser* parser;
7121cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_ci    // Already unconsumed
7151cb0ef41Sopenharmony_ci    if (parser->stream_ == nullptr)
7161cb0ef41Sopenharmony_ci      return;
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci    parser->stream_->RemoveStreamListener(parser);
7191cb0ef41Sopenharmony_ci  }
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci
7221cb0ef41Sopenharmony_ci  static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) {
7231cb0ef41Sopenharmony_ci    Parser* parser;
7241cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_ci    Local<Object> ret = Buffer::Copy(
7271cb0ef41Sopenharmony_ci        parser->env(),
7281cb0ef41Sopenharmony_ci        parser->current_buffer_data_,
7291cb0ef41Sopenharmony_ci        parser->current_buffer_len_).ToLocalChecked();
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(ret);
7321cb0ef41Sopenharmony_ci  }
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci  static void Duration(const FunctionCallbackInfo<Value>& args) {
7351cb0ef41Sopenharmony_ci    Parser* parser;
7361cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci    if (parser->last_message_start_ == 0) {
7391cb0ef41Sopenharmony_ci      args.GetReturnValue().Set(0);
7401cb0ef41Sopenharmony_ci      return;
7411cb0ef41Sopenharmony_ci    }
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ci    double duration = (uv_hrtime() - parser->last_message_start_) / 1e6;
7441cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(duration);
7451cb0ef41Sopenharmony_ci  }
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci  static void HeadersCompleted(const FunctionCallbackInfo<Value>& args) {
7481cb0ef41Sopenharmony_ci    Parser* parser;
7491cb0ef41Sopenharmony_ci    ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(parser->headers_completed_);
7521cb0ef41Sopenharmony_ci  }
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci protected:
7551cb0ef41Sopenharmony_ci  static const size_t kAllocBufferSize = 64 * 1024;
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_ci  uv_buf_t OnStreamAlloc(size_t suggested_size) override {
7581cb0ef41Sopenharmony_ci    // For most types of streams, OnStreamRead will be immediately after
7591cb0ef41Sopenharmony_ci    // OnStreamAlloc, and will consume all data, so using a static buffer for
7601cb0ef41Sopenharmony_ci    // reading is more efficient. For other streams, just use Malloc() directly.
7611cb0ef41Sopenharmony_ci    if (binding_data_->parser_buffer_in_use)
7621cb0ef41Sopenharmony_ci      return uv_buf_init(Malloc(suggested_size), suggested_size);
7631cb0ef41Sopenharmony_ci    binding_data_->parser_buffer_in_use = true;
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci    if (binding_data_->parser_buffer.empty())
7661cb0ef41Sopenharmony_ci      binding_data_->parser_buffer.resize(kAllocBufferSize);
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ci    return uv_buf_init(binding_data_->parser_buffer.data(), kAllocBufferSize);
7691cb0ef41Sopenharmony_ci  }
7701cb0ef41Sopenharmony_ci
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci  void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override {
7731cb0ef41Sopenharmony_ci    HandleScope scope(env()->isolate());
7741cb0ef41Sopenharmony_ci    // Once we’re done here, either indicate that the HTTP parser buffer
7751cb0ef41Sopenharmony_ci    // is free for re-use, or free() the data if it didn’t come from there
7761cb0ef41Sopenharmony_ci    // in the first place.
7771cb0ef41Sopenharmony_ci    auto on_scope_leave = OnScopeLeave([&]() {
7781cb0ef41Sopenharmony_ci      if (buf.base == binding_data_->parser_buffer.data())
7791cb0ef41Sopenharmony_ci        binding_data_->parser_buffer_in_use = false;
7801cb0ef41Sopenharmony_ci      else
7811cb0ef41Sopenharmony_ci        free(buf.base);
7821cb0ef41Sopenharmony_ci    });
7831cb0ef41Sopenharmony_ci
7841cb0ef41Sopenharmony_ci    if (nread < 0) {
7851cb0ef41Sopenharmony_ci      PassReadErrorToPreviousListener(nread);
7861cb0ef41Sopenharmony_ci      return;
7871cb0ef41Sopenharmony_ci    }
7881cb0ef41Sopenharmony_ci
7891cb0ef41Sopenharmony_ci    // Ignore, empty reads have special meaning in http parser
7901cb0ef41Sopenharmony_ci    if (nread == 0)
7911cb0ef41Sopenharmony_ci      return;
7921cb0ef41Sopenharmony_ci
7931cb0ef41Sopenharmony_ci    Local<Value> ret = Execute(buf.base, nread);
7941cb0ef41Sopenharmony_ci
7951cb0ef41Sopenharmony_ci    // Exception
7961cb0ef41Sopenharmony_ci    if (ret.IsEmpty())
7971cb0ef41Sopenharmony_ci      return;
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_ci    Local<Value> cb =
8001cb0ef41Sopenharmony_ci        object()->Get(env()->context(), kOnExecute).ToLocalChecked();
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_ci    if (!cb->IsFunction())
8031cb0ef41Sopenharmony_ci      return;
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci    // Hooks for GetCurrentBuffer
8061cb0ef41Sopenharmony_ci    current_buffer_len_ = nread;
8071cb0ef41Sopenharmony_ci    current_buffer_data_ = buf.base;
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_ci    MakeCallback(cb.As<Function>(), 1, &ret);
8101cb0ef41Sopenharmony_ci
8111cb0ef41Sopenharmony_ci    current_buffer_len_ = 0;
8121cb0ef41Sopenharmony_ci    current_buffer_data_ = nullptr;
8131cb0ef41Sopenharmony_ci  }
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_ci
8161cb0ef41Sopenharmony_ci  Local<Value> Execute(const char* data, size_t len) {
8171cb0ef41Sopenharmony_ci    EscapableHandleScope scope(env()->isolate());
8181cb0ef41Sopenharmony_ci
8191cb0ef41Sopenharmony_ci    current_buffer_len_ = len;
8201cb0ef41Sopenharmony_ci    current_buffer_data_ = data;
8211cb0ef41Sopenharmony_ci    got_exception_ = false;
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci    llhttp_errno_t err;
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_ci    if (data == nullptr) {
8261cb0ef41Sopenharmony_ci      err = llhttp_finish(&parser_);
8271cb0ef41Sopenharmony_ci    } else {
8281cb0ef41Sopenharmony_ci      err = llhttp_execute(&parser_, data, len);
8291cb0ef41Sopenharmony_ci      Save();
8301cb0ef41Sopenharmony_ci    }
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci    // Calculate bytes read and resume after Upgrade/CONNECT pause
8331cb0ef41Sopenharmony_ci    size_t nread = len;
8341cb0ef41Sopenharmony_ci    if (err != HPE_OK) {
8351cb0ef41Sopenharmony_ci      nread = llhttp_get_error_pos(&parser_) - data;
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_ci      // This isn't a real pause, just a way to stop parsing early.
8381cb0ef41Sopenharmony_ci      if (err == HPE_PAUSED_UPGRADE) {
8391cb0ef41Sopenharmony_ci        err = HPE_OK;
8401cb0ef41Sopenharmony_ci        llhttp_resume_after_upgrade(&parser_);
8411cb0ef41Sopenharmony_ci      }
8421cb0ef41Sopenharmony_ci    }
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ci    // Apply pending pause
8451cb0ef41Sopenharmony_ci    if (pending_pause_) {
8461cb0ef41Sopenharmony_ci      pending_pause_ = false;
8471cb0ef41Sopenharmony_ci      llhttp_pause(&parser_);
8481cb0ef41Sopenharmony_ci    }
8491cb0ef41Sopenharmony_ci
8501cb0ef41Sopenharmony_ci    current_buffer_len_ = 0;
8511cb0ef41Sopenharmony_ci    current_buffer_data_ = nullptr;
8521cb0ef41Sopenharmony_ci
8531cb0ef41Sopenharmony_ci    // If there was an exception in one of the callbacks
8541cb0ef41Sopenharmony_ci    if (got_exception_)
8551cb0ef41Sopenharmony_ci      return scope.Escape(Local<Value>());
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_ci    Local<Integer> nread_obj = Integer::New(env()->isolate(), nread);
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci    // If there was a parse error in one of the callbacks
8601cb0ef41Sopenharmony_ci    // TODO(bnoordhuis) What if there is an error on EOF?
8611cb0ef41Sopenharmony_ci    if (!parser_.upgrade && err != HPE_OK) {
8621cb0ef41Sopenharmony_ci      Local<Value> e = Exception::Error(env()->parse_error_string());
8631cb0ef41Sopenharmony_ci      Local<Object> obj = e->ToObject(env()->isolate()->GetCurrentContext())
8641cb0ef41Sopenharmony_ci        .ToLocalChecked();
8651cb0ef41Sopenharmony_ci      obj->Set(env()->context(),
8661cb0ef41Sopenharmony_ci               env()->bytes_parsed_string(),
8671cb0ef41Sopenharmony_ci               nread_obj).Check();
8681cb0ef41Sopenharmony_ci      const char* errno_reason = llhttp_get_error_reason(&parser_);
8691cb0ef41Sopenharmony_ci
8701cb0ef41Sopenharmony_ci      Local<String> code;
8711cb0ef41Sopenharmony_ci      Local<String> reason;
8721cb0ef41Sopenharmony_ci      if (err == HPE_USER) {
8731cb0ef41Sopenharmony_ci        const char* colon = strchr(errno_reason, ':');
8741cb0ef41Sopenharmony_ci        CHECK_NOT_NULL(colon);
8751cb0ef41Sopenharmony_ci        code = OneByteString(env()->isolate(),
8761cb0ef41Sopenharmony_ci                             errno_reason,
8771cb0ef41Sopenharmony_ci                             static_cast<int>(colon - errno_reason));
8781cb0ef41Sopenharmony_ci        reason = OneByteString(env()->isolate(), colon + 1);
8791cb0ef41Sopenharmony_ci      } else {
8801cb0ef41Sopenharmony_ci        code = OneByteString(env()->isolate(), llhttp_errno_name(err));
8811cb0ef41Sopenharmony_ci        reason = OneByteString(env()->isolate(), errno_reason);
8821cb0ef41Sopenharmony_ci      }
8831cb0ef41Sopenharmony_ci
8841cb0ef41Sopenharmony_ci      obj->Set(env()->context(), env()->code_string(), code).Check();
8851cb0ef41Sopenharmony_ci      obj->Set(env()->context(), env()->reason_string(), reason).Check();
8861cb0ef41Sopenharmony_ci      return scope.Escape(e);
8871cb0ef41Sopenharmony_ci    }
8881cb0ef41Sopenharmony_ci
8891cb0ef41Sopenharmony_ci    // No return value is needed for `Finish()`
8901cb0ef41Sopenharmony_ci    if (data == nullptr) {
8911cb0ef41Sopenharmony_ci      return scope.Escape(Local<Value>());
8921cb0ef41Sopenharmony_ci    }
8931cb0ef41Sopenharmony_ci    return scope.Escape(nread_obj);
8941cb0ef41Sopenharmony_ci  }
8951cb0ef41Sopenharmony_ci
8961cb0ef41Sopenharmony_ci  Local<Array> CreateHeaders() {
8971cb0ef41Sopenharmony_ci    // There could be extra entries but the max size should be fixed
8981cb0ef41Sopenharmony_ci    Local<Value> headers_v[kMaxHeaderFieldsCount * 2];
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_ci    for (size_t i = 0; i < num_values_; ++i) {
9011cb0ef41Sopenharmony_ci      headers_v[i * 2] = fields_[i].ToString(env());
9021cb0ef41Sopenharmony_ci      headers_v[i * 2 + 1] = values_[i].ToTrimmedString(env());
9031cb0ef41Sopenharmony_ci    }
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci    return Array::New(env()->isolate(), headers_v, num_values_ * 2);
9061cb0ef41Sopenharmony_ci  }
9071cb0ef41Sopenharmony_ci
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ci  // spill headers and request path to JS land
9101cb0ef41Sopenharmony_ci  void Flush() {
9111cb0ef41Sopenharmony_ci    HandleScope scope(env()->isolate());
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_ci    Local<Object> obj = object();
9141cb0ef41Sopenharmony_ci    Local<Value> cb = obj->Get(env()->context(), kOnHeaders).ToLocalChecked();
9151cb0ef41Sopenharmony_ci
9161cb0ef41Sopenharmony_ci    if (!cb->IsFunction())
9171cb0ef41Sopenharmony_ci      return;
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci    Local<Value> argv[2] = {
9201cb0ef41Sopenharmony_ci      CreateHeaders(),
9211cb0ef41Sopenharmony_ci      url_.ToString(env())
9221cb0ef41Sopenharmony_ci    };
9231cb0ef41Sopenharmony_ci
9241cb0ef41Sopenharmony_ci    MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
9251cb0ef41Sopenharmony_ci                                       arraysize(argv),
9261cb0ef41Sopenharmony_ci                                       argv);
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_ci    if (r.IsEmpty())
9291cb0ef41Sopenharmony_ci      got_exception_ = true;
9301cb0ef41Sopenharmony_ci
9311cb0ef41Sopenharmony_ci    url_.Reset();
9321cb0ef41Sopenharmony_ci    have_flushed_ = true;
9331cb0ef41Sopenharmony_ci  }
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_ci
9361cb0ef41Sopenharmony_ci  void Init(llhttp_type_t type, uint64_t max_http_header_size,
9371cb0ef41Sopenharmony_ci            uint32_t lenient_flags) {
9381cb0ef41Sopenharmony_ci    llhttp_init(&parser_, type, &settings);
9391cb0ef41Sopenharmony_ci
9401cb0ef41Sopenharmony_ci    if (lenient_flags & kLenientHeaders) {
9411cb0ef41Sopenharmony_ci      llhttp_set_lenient_headers(&parser_, 1);
9421cb0ef41Sopenharmony_ci    }
9431cb0ef41Sopenharmony_ci    if (lenient_flags & kLenientChunkedLength) {
9441cb0ef41Sopenharmony_ci      llhttp_set_lenient_chunked_length(&parser_, 1);
9451cb0ef41Sopenharmony_ci    }
9461cb0ef41Sopenharmony_ci    if (lenient_flags & kLenientKeepAlive) {
9471cb0ef41Sopenharmony_ci      llhttp_set_lenient_keep_alive(&parser_, 1);
9481cb0ef41Sopenharmony_ci    }
9491cb0ef41Sopenharmony_ci
9501cb0ef41Sopenharmony_ci    header_nread_ = 0;
9511cb0ef41Sopenharmony_ci    url_.Reset();
9521cb0ef41Sopenharmony_ci    status_message_.Reset();
9531cb0ef41Sopenharmony_ci    num_fields_ = 0;
9541cb0ef41Sopenharmony_ci    num_values_ = 0;
9551cb0ef41Sopenharmony_ci    have_flushed_ = false;
9561cb0ef41Sopenharmony_ci    got_exception_ = false;
9571cb0ef41Sopenharmony_ci    headers_completed_ = false;
9581cb0ef41Sopenharmony_ci    max_http_header_size_ = max_http_header_size;
9591cb0ef41Sopenharmony_ci  }
9601cb0ef41Sopenharmony_ci
9611cb0ef41Sopenharmony_ci
9621cb0ef41Sopenharmony_ci  int TrackHeader(size_t len) {
9631cb0ef41Sopenharmony_ci    header_nread_ += len;
9641cb0ef41Sopenharmony_ci    if (header_nread_ >= max_http_header_size_) {
9651cb0ef41Sopenharmony_ci      llhttp_set_error_reason(&parser_, "HPE_HEADER_OVERFLOW:Header overflow");
9661cb0ef41Sopenharmony_ci      return HPE_USER;
9671cb0ef41Sopenharmony_ci    }
9681cb0ef41Sopenharmony_ci    return 0;
9691cb0ef41Sopenharmony_ci  }
9701cb0ef41Sopenharmony_ci
9711cb0ef41Sopenharmony_ci
9721cb0ef41Sopenharmony_ci  int MaybePause() {
9731cb0ef41Sopenharmony_ci    if (!pending_pause_) {
9741cb0ef41Sopenharmony_ci      return 0;
9751cb0ef41Sopenharmony_ci    }
9761cb0ef41Sopenharmony_ci
9771cb0ef41Sopenharmony_ci    pending_pause_ = false;
9781cb0ef41Sopenharmony_ci    llhttp_set_error_reason(&parser_, "Paused in callback");
9791cb0ef41Sopenharmony_ci    return HPE_PAUSED;
9801cb0ef41Sopenharmony_ci  }
9811cb0ef41Sopenharmony_ci
9821cb0ef41Sopenharmony_ci
9831cb0ef41Sopenharmony_ci  bool IsNotIndicativeOfMemoryLeakAtExit() const override {
9841cb0ef41Sopenharmony_ci    // HTTP parsers are able to emit events without any GC root referring
9851cb0ef41Sopenharmony_ci    // to them, because they receive events directly from the underlying
9861cb0ef41Sopenharmony_ci    // libuv resource.
9871cb0ef41Sopenharmony_ci    return true;
9881cb0ef41Sopenharmony_ci  }
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_ci
9911cb0ef41Sopenharmony_ci  llhttp_t parser_;
9921cb0ef41Sopenharmony_ci  StringPtr fields_[kMaxHeaderFieldsCount];  // header fields
9931cb0ef41Sopenharmony_ci  StringPtr values_[kMaxHeaderFieldsCount];  // header values
9941cb0ef41Sopenharmony_ci  StringPtr url_;
9951cb0ef41Sopenharmony_ci  StringPtr status_message_;
9961cb0ef41Sopenharmony_ci  size_t num_fields_;
9971cb0ef41Sopenharmony_ci  size_t num_values_;
9981cb0ef41Sopenharmony_ci  bool have_flushed_;
9991cb0ef41Sopenharmony_ci  bool got_exception_;
10001cb0ef41Sopenharmony_ci  size_t current_buffer_len_;
10011cb0ef41Sopenharmony_ci  const char* current_buffer_data_;
10021cb0ef41Sopenharmony_ci  bool headers_completed_ = false;
10031cb0ef41Sopenharmony_ci  bool pending_pause_ = false;
10041cb0ef41Sopenharmony_ci  uint64_t header_nread_ = 0;
10051cb0ef41Sopenharmony_ci  uint64_t chunk_extensions_nread_ = 0;
10061cb0ef41Sopenharmony_ci  uint64_t max_http_header_size_;
10071cb0ef41Sopenharmony_ci  uint64_t last_message_start_;
10081cb0ef41Sopenharmony_ci  ConnectionsList* connectionsList_;
10091cb0ef41Sopenharmony_ci
10101cb0ef41Sopenharmony_ci  BaseObjectPtr<BindingData> binding_data_;
10111cb0ef41Sopenharmony_ci
10121cb0ef41Sopenharmony_ci  // These are helper functions for filling `http_parser_settings`, which turn
10131cb0ef41Sopenharmony_ci  // a member function of Parser into a C-style HTTP parser callback.
10141cb0ef41Sopenharmony_ci  template <typename Parser, Parser> struct Proxy;
10151cb0ef41Sopenharmony_ci  template <typename Parser, typename ...Args, int (Parser::*Member)(Args...)>
10161cb0ef41Sopenharmony_ci  struct Proxy<int (Parser::*)(Args...), Member> {
10171cb0ef41Sopenharmony_ci    static int Raw(llhttp_t* p, Args ... args) {
10181cb0ef41Sopenharmony_ci      Parser* parser = ContainerOf(&Parser::parser_, p);
10191cb0ef41Sopenharmony_ci      int rv = (parser->*Member)(std::forward<Args>(args)...);
10201cb0ef41Sopenharmony_ci      if (rv == 0) {
10211cb0ef41Sopenharmony_ci        rv = parser->MaybePause();
10221cb0ef41Sopenharmony_ci      }
10231cb0ef41Sopenharmony_ci      return rv;
10241cb0ef41Sopenharmony_ci    }
10251cb0ef41Sopenharmony_ci  };
10261cb0ef41Sopenharmony_ci
10271cb0ef41Sopenharmony_ci  typedef int (Parser::*Call)();
10281cb0ef41Sopenharmony_ci  typedef int (Parser::*DataCall)(const char* at, size_t length);
10291cb0ef41Sopenharmony_ci
10301cb0ef41Sopenharmony_ci  static const llhttp_settings_t settings;
10311cb0ef41Sopenharmony_ci};
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_cibool ParserComparator::operator()(const Parser* lhs, const Parser* rhs) const {
10341cb0ef41Sopenharmony_ci  if (lhs->last_message_start_ == 0 && rhs->last_message_start_ == 0) {
10351cb0ef41Sopenharmony_ci    // When both parsers are idle, guarantee strict order by
10361cb0ef41Sopenharmony_ci    // comparing pointers as ints.
10371cb0ef41Sopenharmony_ci    return lhs < rhs;
10381cb0ef41Sopenharmony_ci  } else if (lhs->last_message_start_ == 0) {
10391cb0ef41Sopenharmony_ci    return true;
10401cb0ef41Sopenharmony_ci  } else if (rhs->last_message_start_ == 0) {
10411cb0ef41Sopenharmony_ci    return false;
10421cb0ef41Sopenharmony_ci  }
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci  return lhs->last_message_start_ < rhs->last_message_start_;
10451cb0ef41Sopenharmony_ci}
10461cb0ef41Sopenharmony_ci
10471cb0ef41Sopenharmony_civoid ConnectionsList::New(const FunctionCallbackInfo<Value>& args) {
10481cb0ef41Sopenharmony_ci  Local<Context> context = args.GetIsolate()->GetCurrentContext();
10491cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(context);
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci  new ConnectionsList(env, args.This());
10521cb0ef41Sopenharmony_ci}
10531cb0ef41Sopenharmony_ci
10541cb0ef41Sopenharmony_civoid ConnectionsList::All(const FunctionCallbackInfo<Value>& args) {
10551cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci  ConnectionsList* list;
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
10601cb0ef41Sopenharmony_ci
10611cb0ef41Sopenharmony_ci  std::vector<Local<Value>> result;
10621cb0ef41Sopenharmony_ci  result.reserve(list->all_connections_.size());
10631cb0ef41Sopenharmony_ci  for (auto parser : list->all_connections_) {
10641cb0ef41Sopenharmony_ci    result.emplace_back(parser->object());
10651cb0ef41Sopenharmony_ci  }
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci  return args.GetReturnValue().Set(
10681cb0ef41Sopenharmony_ci      Array::New(isolate, result.data(), result.size()));
10691cb0ef41Sopenharmony_ci}
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_civoid ConnectionsList::Idle(const FunctionCallbackInfo<Value>& args) {
10721cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
10731cb0ef41Sopenharmony_ci
10741cb0ef41Sopenharmony_ci  ConnectionsList* list;
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
10771cb0ef41Sopenharmony_ci
10781cb0ef41Sopenharmony_ci  std::vector<Local<Value>> result;
10791cb0ef41Sopenharmony_ci  result.reserve(list->all_connections_.size());
10801cb0ef41Sopenharmony_ci  for (auto parser : list->all_connections_) {
10811cb0ef41Sopenharmony_ci    if (parser->last_message_start_ == 0) {
10821cb0ef41Sopenharmony_ci      result.emplace_back(parser->object());
10831cb0ef41Sopenharmony_ci    }
10841cb0ef41Sopenharmony_ci  }
10851cb0ef41Sopenharmony_ci
10861cb0ef41Sopenharmony_ci  return args.GetReturnValue().Set(
10871cb0ef41Sopenharmony_ci      Array::New(isolate, result.data(), result.size()));
10881cb0ef41Sopenharmony_ci}
10891cb0ef41Sopenharmony_ci
10901cb0ef41Sopenharmony_civoid ConnectionsList::Active(const FunctionCallbackInfo<Value>& args) {
10911cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
10921cb0ef41Sopenharmony_ci
10931cb0ef41Sopenharmony_ci  ConnectionsList* list;
10941cb0ef41Sopenharmony_ci
10951cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
10961cb0ef41Sopenharmony_ci
10971cb0ef41Sopenharmony_ci  std::vector<Local<Value>> result;
10981cb0ef41Sopenharmony_ci  result.reserve(list->active_connections_.size());
10991cb0ef41Sopenharmony_ci  for (auto parser : list->active_connections_) {
11001cb0ef41Sopenharmony_ci    result.emplace_back(parser->object());
11011cb0ef41Sopenharmony_ci  }
11021cb0ef41Sopenharmony_ci
11031cb0ef41Sopenharmony_ci  return args.GetReturnValue().Set(
11041cb0ef41Sopenharmony_ci      Array::New(isolate, result.data(), result.size()));
11051cb0ef41Sopenharmony_ci}
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_civoid ConnectionsList::Expired(const FunctionCallbackInfo<Value>& args) {
11081cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci  ConnectionsList* list;
11111cb0ef41Sopenharmony_ci
11121cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&list, args.Holder());
11131cb0ef41Sopenharmony_ci  CHECK(args[0]->IsNumber());
11141cb0ef41Sopenharmony_ci  CHECK(args[1]->IsNumber());
11151cb0ef41Sopenharmony_ci  uint64_t headers_timeout =
11161cb0ef41Sopenharmony_ci    static_cast<uint64_t>(args[0].As<Uint32>()->Value()) * 1000000;
11171cb0ef41Sopenharmony_ci  uint64_t request_timeout =
11181cb0ef41Sopenharmony_ci    static_cast<uint64_t>(args[1].As<Uint32>()->Value()) * 1000000;
11191cb0ef41Sopenharmony_ci
11201cb0ef41Sopenharmony_ci  if (headers_timeout == 0 && request_timeout == 0) {
11211cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(Array::New(isolate, 0));
11221cb0ef41Sopenharmony_ci  } else if (request_timeout > 0 && headers_timeout > request_timeout) {
11231cb0ef41Sopenharmony_ci    std::swap(headers_timeout, request_timeout);
11241cb0ef41Sopenharmony_ci  }
11251cb0ef41Sopenharmony_ci
11261cb0ef41Sopenharmony_ci  // On IoT or embedded devices the uv_hrtime() may return the timestamp
11271cb0ef41Sopenharmony_ci  // that is smaller than configured timeout for headers or request
11281cb0ef41Sopenharmony_ci  // to prevent subtracting two unsigned integers
11291cb0ef41Sopenharmony_ci  // that can yield incorrect results we should check
11301cb0ef41Sopenharmony_ci  // if the 'now' is bigger than the timeout for headers or request
11311cb0ef41Sopenharmony_ci  const uint64_t now = uv_hrtime();
11321cb0ef41Sopenharmony_ci  const uint64_t headers_deadline =
11331cb0ef41Sopenharmony_ci      (headers_timeout > 0 && now > headers_timeout) ? now - headers_timeout
11341cb0ef41Sopenharmony_ci                                                     : 0;
11351cb0ef41Sopenharmony_ci  const uint64_t request_deadline =
11361cb0ef41Sopenharmony_ci      (request_timeout > 0 && now > request_timeout) ? now - request_timeout
11371cb0ef41Sopenharmony_ci                                                     : 0;
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ci  if (headers_deadline == 0 && request_deadline == 0) {
11401cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(Array::New(isolate, 0));
11411cb0ef41Sopenharmony_ci  }
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_ci  auto iter = list->active_connections_.begin();
11441cb0ef41Sopenharmony_ci  auto end = list->active_connections_.end();
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_ci  std::vector<Local<Value>> result;
11471cb0ef41Sopenharmony_ci  result.reserve(list->active_connections_.size());
11481cb0ef41Sopenharmony_ci  while (iter != end) {
11491cb0ef41Sopenharmony_ci    Parser* parser = *iter;
11501cb0ef41Sopenharmony_ci    iter++;
11511cb0ef41Sopenharmony_ci
11521cb0ef41Sopenharmony_ci    // Check for expiration.
11531cb0ef41Sopenharmony_ci    if (
11541cb0ef41Sopenharmony_ci      (!parser->headers_completed_ && headers_deadline > 0 &&
11551cb0ef41Sopenharmony_ci        parser->last_message_start_ < headers_deadline) ||
11561cb0ef41Sopenharmony_ci      (
11571cb0ef41Sopenharmony_ci        request_deadline > 0 &&
11581cb0ef41Sopenharmony_ci        parser->last_message_start_ < request_deadline)
11591cb0ef41Sopenharmony_ci    ) {
11601cb0ef41Sopenharmony_ci      result.emplace_back(parser->object());
11611cb0ef41Sopenharmony_ci
11621cb0ef41Sopenharmony_ci      list->active_connections_.erase(parser);
11631cb0ef41Sopenharmony_ci    }
11641cb0ef41Sopenharmony_ci  }
11651cb0ef41Sopenharmony_ci
11661cb0ef41Sopenharmony_ci  return args.GetReturnValue().Set(
11671cb0ef41Sopenharmony_ci      Array::New(isolate, result.data(), result.size()));
11681cb0ef41Sopenharmony_ci}
11691cb0ef41Sopenharmony_ci
11701cb0ef41Sopenharmony_ciconst llhttp_settings_t Parser::settings = {
11711cb0ef41Sopenharmony_ci  Proxy<Call, &Parser::on_message_begin>::Raw,
11721cb0ef41Sopenharmony_ci  Proxy<DataCall, &Parser::on_url>::Raw,
11731cb0ef41Sopenharmony_ci  Proxy<DataCall, &Parser::on_status>::Raw,
11741cb0ef41Sopenharmony_ci  Proxy<DataCall, &Parser::on_header_field>::Raw,
11751cb0ef41Sopenharmony_ci  Proxy<DataCall, &Parser::on_header_value>::Raw,
11761cb0ef41Sopenharmony_ci  Proxy<Call, &Parser::on_headers_complete>::Raw,
11771cb0ef41Sopenharmony_ci  Proxy<DataCall, &Parser::on_chunk_extension>::Raw,
11781cb0ef41Sopenharmony_ci  Proxy<DataCall, &Parser::on_body>::Raw,
11791cb0ef41Sopenharmony_ci  Proxy<Call, &Parser::on_message_complete>::Raw,
11801cb0ef41Sopenharmony_ci  Proxy<Call, &Parser::on_chunk_header>::Raw,
11811cb0ef41Sopenharmony_ci  Proxy<Call, &Parser::on_chunk_complete>::Raw,
11821cb0ef41Sopenharmony_ci
11831cb0ef41Sopenharmony_ci  // on_url_complete
11841cb0ef41Sopenharmony_ci  nullptr,
11851cb0ef41Sopenharmony_ci  // on_status_complete
11861cb0ef41Sopenharmony_ci  nullptr,
11871cb0ef41Sopenharmony_ci  // on_header_field_complete
11881cb0ef41Sopenharmony_ci  nullptr,
11891cb0ef41Sopenharmony_ci  // on_header_value_complete
11901cb0ef41Sopenharmony_ci  nullptr,
11911cb0ef41Sopenharmony_ci};
11921cb0ef41Sopenharmony_ci
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_civoid InitializeHttpParser(Local<Object> target,
11951cb0ef41Sopenharmony_ci                          Local<Value> unused,
11961cb0ef41Sopenharmony_ci                          Local<Context> context,
11971cb0ef41Sopenharmony_ci                          void* priv) {
11981cb0ef41Sopenharmony_ci  Realm* realm = Realm::GetCurrent(context);
11991cb0ef41Sopenharmony_ci  Environment* env = realm->env();
12001cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
12011cb0ef41Sopenharmony_ci  BindingData* const binding_data =
12021cb0ef41Sopenharmony_ci      realm->AddBindingData<BindingData>(context, target);
12031cb0ef41Sopenharmony_ci  if (binding_data == nullptr) return;
12041cb0ef41Sopenharmony_ci
12051cb0ef41Sopenharmony_ci  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, Parser::New);
12061cb0ef41Sopenharmony_ci  t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount);
12071cb0ef41Sopenharmony_ci
12081cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
12091cb0ef41Sopenharmony_ci         Integer::New(env->isolate(), HTTP_REQUEST));
12101cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
12111cb0ef41Sopenharmony_ci         Integer::New(env->isolate(), HTTP_RESPONSE));
12121cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageBegin"),
12131cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnMessageBegin));
12141cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
12151cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
12161cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
12171cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
12181cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
12191cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnBody));
12201cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
12211cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
12221cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
12231cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnExecute));
12241cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnTimeout"),
12251cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kOnTimeout));
12261cb0ef41Sopenharmony_ci
12271cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientNone"),
12281cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kLenientNone));
12291cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientHeaders"),
12301cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kLenientHeaders));
12311cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientChunkedLength"),
12321cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kLenientChunkedLength));
12331cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientKeepAlive"),
12341cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kLenientKeepAlive));
12351cb0ef41Sopenharmony_ci  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientAll"),
12361cb0ef41Sopenharmony_ci         Integer::NewFromUnsigned(env->isolate(), kLenientAll));
12371cb0ef41Sopenharmony_ci
12381cb0ef41Sopenharmony_ci  Local<Array> methods = Array::New(env->isolate());
12391cb0ef41Sopenharmony_ci#define V(num, name, string)                                                  \
12401cb0ef41Sopenharmony_ci    methods->Set(env->context(),                                              \
12411cb0ef41Sopenharmony_ci        num, FIXED_ONE_BYTE_STRING(env->isolate(), #string)).Check();
12421cb0ef41Sopenharmony_ci  HTTP_METHOD_MAP(V)
12431cb0ef41Sopenharmony_ci#undef V
12441cb0ef41Sopenharmony_ci  target->Set(env->context(),
12451cb0ef41Sopenharmony_ci              FIXED_ONE_BYTE_STRING(env->isolate(), "methods"),
12461cb0ef41Sopenharmony_ci              methods).Check();
12471cb0ef41Sopenharmony_ci
12481cb0ef41Sopenharmony_ci  t->Inherit(AsyncWrap::GetConstructorTemplate(env));
12491cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "close", Parser::Close);
12501cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "free", Parser::Free);
12511cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "remove", Parser::Remove);
12521cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "execute", Parser::Execute);
12531cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "finish", Parser::Finish);
12541cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "initialize", Parser::Initialize);
12551cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "pause", Parser::Pause<true>);
12561cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "resume", Parser::Pause<false>);
12571cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "consume", Parser::Consume);
12581cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "unconsume", Parser::Unconsume);
12591cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "getCurrentBuffer", Parser::GetCurrentBuffer);
12601cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "duration", Parser::Duration);
12611cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "headersCompleted", Parser::HeadersCompleted);
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci  SetConstructorFunction(context, target, "HTTPParser", t);
12641cb0ef41Sopenharmony_ci
12651cb0ef41Sopenharmony_ci  Local<FunctionTemplate> c =
12661cb0ef41Sopenharmony_ci      NewFunctionTemplate(isolate, ConnectionsList::New);
12671cb0ef41Sopenharmony_ci  c->InstanceTemplate()
12681cb0ef41Sopenharmony_ci    ->SetInternalFieldCount(ConnectionsList::kInternalFieldCount);
12691cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, c, "all", ConnectionsList::All);
12701cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, c, "idle", ConnectionsList::Idle);
12711cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, c, "active", ConnectionsList::Active);
12721cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, c, "expired", ConnectionsList::Expired);
12731cb0ef41Sopenharmony_ci  SetConstructorFunction(context, target, "ConnectionsList", c);
12741cb0ef41Sopenharmony_ci}
12751cb0ef41Sopenharmony_ci
12761cb0ef41Sopenharmony_ci}  // anonymous namespace
12771cb0ef41Sopenharmony_ci}  // namespace node
12781cb0ef41Sopenharmony_ci
12791cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(http_parser, node::InitializeHttpParser)
1280