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
49 namespace node {
50 namespace { // NOLINT(build/namespaces)
51
52 using v8::Array;
53 using v8::Boolean;
54 using v8::Context;
55 using v8::EscapableHandleScope;
56 using v8::Exception;
57 using v8::Function;
58 using v8::FunctionCallbackInfo;
59 using v8::FunctionTemplate;
60 using v8::HandleScope;
61 using v8::Int32;
62 using v8::Integer;
63 using v8::Isolate;
64 using v8::Local;
65 using v8::MaybeLocal;
66 using v8::Number;
67 using v8::Object;
68 using v8::String;
69 using v8::Uint32;
70 using v8::Undefined;
71 using v8::Value;
72
73 const uint32_t kOnMessageBegin = 0;
74 const uint32_t kOnHeaders = 1;
75 const uint32_t kOnHeadersComplete = 2;
76 const uint32_t kOnBody = 3;
77 const uint32_t kOnMessageComplete = 4;
78 const uint32_t kOnExecute = 5;
79 const uint32_t kOnTimeout = 6;
80 // Any more fields than this will be flushed into JS
81 const size_t kMaxHeaderFieldsCount = 32;
82 // Maximum size of chunk extensions
83 const size_t kMaxChunkExtensionsSize = 16384;
84
85 const uint32_t kLenientNone = 0;
86 const uint32_t kLenientHeaders = 1 << 0;
87 const uint32_t kLenientChunkedLength = 1 << 1;
88 const uint32_t kLenientKeepAlive = 1 << 2;
89 const uint32_t kLenientAll = kLenientHeaders | kLenientChunkedLength |
90 kLenientKeepAlive;
91
IsOWS(char c)92 inline bool IsOWS(char c) {
93 return c == ' ' || c == '\t';
94 }
95
96 class BindingData : public BaseObject {
97 public:
BindingData(Realm * realm,Local<Object> obj)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
MemoryInfo(MemoryTracker * tracker) const105 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
113 struct StringPtr {
StringPtrnode::__anond50947330111::StringPtr114 StringPtr() {
115 on_heap_ = false;
116 Reset();
117 }
118
119
~StringPtrnode::__anond50947330111::StringPtr120 ~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.
Savenode::__anond50947330111::StringPtr128 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
Resetnode::__anond50947330111::StringPtr138 void Reset() {
139 if (on_heap_) {
140 delete[] str_;
141 on_heap_ = false;
142 }
143
144 str_ = nullptr;
145 size_ = 0;
146 }
147
148
Updatenode::__anond50947330111::StringPtr149 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
ToStringnode::__anond50947330111::StringPtr170 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.
ToTrimmedStringnode::__anond50947330111::StringPtr179 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
192 class Parser;
193
194 struct ParserComparator {
195 bool operator()(const Parser* lhs, const Parser* rhs) const;
196 };
197
198 class 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
Push(Parser * parser)210 void Push(Parser* parser) {
211 all_connections_.insert(parser);
212 }
213
Pop(Parser * parser)214 void Pop(Parser* parser) {
215 all_connections_.erase(parser);
216 }
217
PushActive(Parser * parser)218 void PushActive(Parser* parser) {
219 active_connections_.insert(parser);
220 }
221
PopActive(Parser * parser)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:
ConnectionsList(Environment * env,Local<Object> object)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
240 class Parser : public AsyncWrap, public StreamListener {
241 friend class ConnectionsList;
242 friend struct ParserComparator;
243
244 public:
Parser(BindingData * binding_data,Local<Object> wrap)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()
SET_MEMORY_INFO_NAME(Parser)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
on_url(const char * at,size_t length)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
on_status(const char * at,size_t length)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
on_header_field(const char * at,size_t length)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
on_header_value(const char * at,size_t length)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
on_headers_complete()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
on_body(const char * at,size_t length)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
on_message_complete()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
on_chunk_extension(const char * at,size_t length)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
on_chunk_header()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
on_chunk_complete()543 int on_chunk_complete() {
544 header_nread_ = 0;
545 return 0;
546 }
547
New(const FunctionCallbackInfo<Value> & args)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
Close(const FunctionCallbackInfo<Value> & args)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
Free(const FunctionCallbackInfo<Value> & args)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
Remove(const FunctionCallbackInfo<Value> & args)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
Save()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);
Execute(const FunctionCallbackInfo<Value> & args)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
Finish(const FunctionCallbackInfo<Value> & args)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
Initialize(const FunctionCallbackInfo<Value> & args)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>
Pause(const FunctionCallbackInfo<Value> & args)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
Consume(const FunctionCallbackInfo<Value> & args)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
Unconsume(const FunctionCallbackInfo<Value> & args)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
GetCurrentBuffer(const FunctionCallbackInfo<Value> & args)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
Duration(const FunctionCallbackInfo<Value> & args)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
HeadersCompleted(const FunctionCallbackInfo<Value> & args)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
OnStreamAlloc(size_t suggested_size)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
OnStreamRead(ssize_t nread,const uv_buf_t & buf)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
Execute(const char * data,size_t len)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
CreateHeaders()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
Flush()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
Init(llhttp_type_t type,uint64_t max_http_header_size,uint32_t lenient_flags)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
TrackHeader(size_t len)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
MaybePause()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
IsNotIndicativeOfMemoryLeakAtExit() const983 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> {
Rawnode::__anond50947330111::Parser::Proxy1017 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
operator ()(const Parser * lhs,const Parser * rhs) const1033 bool 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
New(const FunctionCallbackInfo<Value> & args)1047 void 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
All(const FunctionCallbackInfo<Value> & args)1054 void 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
Idle(const FunctionCallbackInfo<Value> & args)1071 void 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
Active(const FunctionCallbackInfo<Value> & args)1090 void 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
Expired(const FunctionCallbackInfo<Value> & args)1107 void 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
1170 const 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
InitializeHttpParser(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)1194 void 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
1279 NODE_BINDING_CONTEXT_AWARE_INTERNAL(http_parser, node::InitializeHttpParser)
1280