• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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