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