Browse Source

Clean up http_parser binding - add asserts

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
a668d07484
  1. 97
      src/node_http_parser.cc

97
src/node_http_parser.cc

@ -23,30 +23,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
printf ("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);
free (strings);
}
namespace node { namespace node {
using namespace v8; using namespace v8;
static int deep = 0;
static Persistent<String> on_message_begin_sym; static Persistent<String> on_message_begin_sym;
static Persistent<String> on_path_sym; static Persistent<String> on_path_sym;
static Persistent<String> on_query_string_sym; static Persistent<String> on_query_string_sym;
@ -92,7 +74,6 @@ static Persistent<String> should_keep_alive_sym;
Local<Value> cb_value = parser->handle_->Get(name##_sym); \ Local<Value> cb_value = parser->handle_->Get(name##_sym); \
if (!cb_value->IsFunction()) return 0; \ if (!cb_value->IsFunction()) return 0; \
Local<Function> cb = Local<Function>::Cast(cb_value); \ Local<Function> cb = Local<Function>::Cast(cb_value); \
\
Local<Value> ret = cb->Call(parser->handle_, 0, NULL); \ Local<Value> ret = cb->Call(parser->handle_, 0, NULL); \
return ret.IsEmpty() ? -1 : 0; \ return ret.IsEmpty() ? -1 : 0; \
} }
@ -149,21 +130,7 @@ class Parser : public ObjectWrap {
public: public:
Parser(enum http_parser_type type) : ObjectWrap() { Parser(enum http_parser_type type) : ObjectWrap() {
buffer_ = NULL; buffer_ = NULL;
Init(type);
http_parser_init(&parser_, type);
parser_.on_message_begin = on_message_begin;
parser_.on_path = on_path;
parser_.on_query_string = on_query_string;
parser_.on_url = on_url;
parser_.on_fragment = on_fragment;
parser_.on_header_field = on_header_field;
parser_.on_header_value = on_header_value;
parser_.on_headers_complete = on_headers_complete;
parser_.on_body = on_body;
parser_.on_message_complete = on_message_complete;
parser_.data = this;
} }
~Parser() { ~Parser() {
@ -213,6 +180,7 @@ class Parser : public ObjectWrap {
Local<Value> argv[1] = { message_info }; Local<Value> argv[1] = { message_info };
Local<Value> ret = cb->Call(parser->handle_, 1, argv); Local<Value> ret = cb->Call(parser->handle_, 1, argv);
return ret.IsEmpty() ? -1 : 0; return ret.IsEmpty() ? -1 : 0;
} }
@ -233,6 +201,7 @@ class Parser : public ObjectWrap {
} }
parser->Wrap(args.This()); parser->Wrap(args.This());
assert(!parser->buffer_);
return args.This(); return args.This();
} }
@ -243,8 +212,8 @@ class Parser : public ObjectWrap {
Parser *parser = ObjectWrap::Unwrap<Parser>(args.This()); Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
assert(!parser->buffer_);
if (parser->buffer_) { if (parser->buffer_) {
print_trace();
return ThrowException(Exception::TypeError( return ThrowException(Exception::TypeError(
String::New("Already parsing a buffer"))); String::New("Already parsing a buffer")));
} }
@ -273,13 +242,9 @@ class Parser : public ObjectWrap {
// Assign 'buffer_' while we parse. The callbacks will access that varible. // Assign 'buffer_' while we parse. The callbacks will access that varible.
parser->buffer_ = buffer; parser->buffer_ = buffer;
buffer_ref(parser->buffer_);
size_t nparsed = size_t nparsed =
http_parser_execute(&(parser->parser_), buffer_p(buffer, off), len); http_parser_execute(&(parser->parser_), buffer_p(buffer, off), len);
buffer_unref(parser->buffer_);
// Unassign the 'buffer_' variable // Unassign the 'buffer_' variable
assert(parser->buffer_); assert(parser->buffer_);
parser->buffer_ = NULL; parser->buffer_ = NULL;
@ -297,25 +262,64 @@ class Parser : public ObjectWrap {
return ThrowException(e); return ThrowException(e);
} }
assert(!parser->buffer_);
return scope.Close(nparsed_obj); return scope.Close(nparsed_obj);
} }
static Handle<Value> ExecuteEOF(const Arguments& args) { static Handle<Value> Finish(const Arguments& args) {
HandleScope scope; HandleScope scope;
Parser *parser = ObjectWrap::Unwrap<Parser>(args.This()); Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
assert(!parser->buffer_); assert(!parser->buffer_);
http_parser_execute(&parser->parser_, NULL, 0);
parser->Ref();
http_parser_execute(&(parser->parser_), NULL, 0);
parser->Unref();
return Undefined(); return Undefined();
} }
static Handle<Value> Reinitialize(const Arguments& args) {
HandleScope scope;
Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
String::Utf8Value type(args[0]->ToString());
if (0 == strcasecmp(*type, "request")) {
parser->Init(HTTP_REQUEST);
} else if (0 == strcasecmp(*type, "response")) {
parser->Init(HTTP_RESPONSE);
} else {
return ThrowException(Exception::Error(
String::New("Argument be 'request' or 'response'")));
}
return Undefined();
}
private: private:
http_parser parser_; void Init (enum http_parser_type type) {
assert(buffer_ == NULL); // don't call this during Execute()
http_parser_init(&parser_, type);
parser_.on_message_begin = on_message_begin;
parser_.on_path = on_path;
parser_.on_query_string = on_query_string;
parser_.on_url = on_url;
parser_.on_fragment = on_fragment;
parser_.on_header_field = on_header_field;
parser_.on_header_value = on_header_value;
parser_.on_headers_complete = on_headers_complete;
parser_.on_body = on_body;
parser_.on_message_complete = on_message_complete;
parser_.data = this;
}
struct buffer * buffer_; // The buffer currently being parsed. struct buffer * buffer_; // The buffer currently being parsed.
http_parser parser_;
}; };
@ -324,10 +328,11 @@ void InitHttpParser(Handle<Object> target) {
Local<FunctionTemplate> t = FunctionTemplate::New(Parser::New); Local<FunctionTemplate> t = FunctionTemplate::New(Parser::New);
t->InstanceTemplate()->SetInternalFieldCount(1); t->InstanceTemplate()->SetInternalFieldCount(1);
//t->SetClassName(String::NewSymbol("HTTPParser")); t->SetClassName(String::NewSymbol("HTTPParser"));
NODE_SET_PROTOTYPE_METHOD(t, "execute", Parser::Execute); NODE_SET_PROTOTYPE_METHOD(t, "execute", Parser::Execute);
NODE_SET_PROTOTYPE_METHOD(t, "executeEOF", Parser::ExecuteEOF); NODE_SET_PROTOTYPE_METHOD(t, "finish", Parser::Finish);
NODE_SET_PROTOTYPE_METHOD(t, "reinitialize", Parser::Reinitialize);
target->Set(String::NewSymbol("HTTPParser"), t->GetFunction()); target->Set(String::NewSymbol("HTTPParser"), t->GetFunction());

Loading…
Cancel
Save