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