From 09c2ae5c3e85dfc8c6194bf48c6b1d6f81c1c24f Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 4 May 2009 12:08:13 +0200 Subject: [PATCH] Slight change in tcp connection constructor For server-side sockets, no longer pass the server object to the js constructor. This is set later with SetAcceptor. I think the change is a bit strage and convoluted but it allows one give protocol /classes/ to the c++ constructors instead of protocol instances. This is nice because derived classes (like HTTP) don't need to copy the protocol instanciation code. --- src/http.cc | 67 +++++++++++++++++++++---------------------- src/http.h | 6 +++- src/net.cc | 45 +++++++++++++++-------------- src/net.h | 6 +++- test/test-pingpong.js | 4 +-- 5 files changed, 67 insertions(+), 61 deletions(-) diff --git a/src/http.cc b/src/http.cc index 5ce7fd58c6..a87ee1ab88 100644 --- a/src/http.cc +++ b/src/http.cc @@ -12,6 +12,10 @@ #define ON_MESSAGE_COMPLETE_SYMBOL String::NewSymbol("onMessageComplete") #define PATH_SYMBOL String::NewSymbol("path") +#define QUERY_STRING_SYMBOL String::NewSymbol("query_string") +#define URI_SYMBOL String::NewSymbol("uri") +#define FRAGMENT_SYMBOL String::NewSymbol("fragment") + #define STATUS_CODE_SYMBOL String::NewSymbol("status_code") #define HTTP_VERSION_SYMBOL String::NewSymbol("http_version") @@ -20,7 +24,7 @@ using namespace node; using namespace std; -// Helper Functions +// Native Helper Functions static Persistent _fill_field; static Persistent _append_header_field; @@ -91,20 +95,10 @@ HTTPConnection::v8New (const Arguments& args) if (args[0]->IsFunction() == false) return ThrowException(String::New("Must pass a class as the first argument.")); - Handle protocol = Handle::Cast(args[0]); - - int argc = args.Length(); - Handle argv[argc]; - - argv[0] = args.This(); - for (int i = 1; i < args.Length(); i++) { - argv[i] = args[i]; - } - - Local protocol_instance = protocol->NewInstance(argc, argv); + Local protocol_class = Local::Cast(args[0]); // changeme the type should come from javascript - new HTTPConnection(args.This(), protocol_instance, HTTP_RESPONSE); + new HTTPConnection(args.This(), protocol_class, HTTP_RESPONSE); return args.This(); } @@ -136,19 +130,21 @@ HTTPConnection::on_message_begin (http_parser *parser) return 0; } -int -HTTPConnection::on_path (http_parser *parser, const char *buf, size_t len) -{ - HTTPConnection *connection = static_cast (parser->data); - - HandleScope scope; - - Local message_handler_v = - connection->handle_->GetHiddenValue(MESSAGE_HANDLER_SYMBOL); - fillField(message_handler_v, PATH_SYMBOL, String::New(buf, len)); - - return 0; +#define DEFINE_FILL_VALUE_CALLBACK(callback_name, symbol) \ +int \ +HTTPConnection::callback_name (http_parser *parser, const char *buf, size_t len) \ +{ \ + HTTPConnection *connection = static_cast (parser->data); \ + HandleScope scope; \ + Local message_handler_v = \ + connection->handle_->GetHiddenValue(MESSAGE_HANDLER_SYMBOL); \ + fillField(message_handler_v, symbol, String::New(buf, len)); \ + return 0; \ } +DEFINE_FILL_VALUE_CALLBACK(on_path, PATH_SYMBOL) +DEFINE_FILL_VALUE_CALLBACK(on_query_string, QUERY_STRING_SYMBOL) +DEFINE_FILL_VALUE_CALLBACK(on_uri, URI_SYMBOL) +DEFINE_FILL_VALUE_CALLBACK(on_fragment, FRAGMENT_SYMBOL) int HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t len) @@ -188,7 +184,12 @@ HTTPConnection::on_headers_complete (http_parser *parser) // VERSION char version[10]; - snprintf(version, 10, "%d.%d", connection->parser_.version_major, connection->parser_.version_minor); + snprintf( version + , 10 + , "%d.%d" + , connection->parser_.version_major + , connection->parser_.version_minor + ); message_handler->Set(HTTP_VERSION_SYMBOL, String::New(version)); @@ -237,9 +238,7 @@ HTTPConnection::on_body (http_parser *parser, const char *buf, size_t len) } argv[0] = array; } - on_body->Call(message_handler, 1, argv); - return 0; } @@ -258,21 +257,19 @@ HTTPConnection::on_message_complete (http_parser *parser) Handle on_msg_complete = Handle::Cast(on_msg_complete_v); on_msg_complete->Call(message_handler, 0, NULL); } - connection->handle_->DeleteHiddenValue(MESSAGE_HANDLER_SYMBOL); - return 0; } -HTTPConnection::HTTPConnection (Handle handle, Handle protocol, enum http_parser_type type) - : Connection(handle, protocol) +HTTPConnection::HTTPConnection (Handle handle, Handle protocol_class, enum http_parser_type type) + : Connection(handle, protocol_class) { http_parser_init (&parser_, type); parser_.on_message_begin = on_message_begin; parser_.on_path = on_path; - parser_.on_query_string = NULL; - parser_.on_uri = NULL; - parser_.on_fragment = NULL; + parser_.on_query_string = on_query_string; + parser_.on_uri = on_uri; + 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; diff --git a/src/http.h b/src/http.h index 9ae9353316..cb17fb75f1 100644 --- a/src/http.h +++ b/src/http.h @@ -12,15 +12,19 @@ public: static void Initialize (v8::Handle target); HTTPConnection (v8::Handle handle, - v8::Handle protocol, + v8::Handle protocol_class, enum http_parser_type type); static v8::Handle v8New (const v8::Arguments& args); + protected: void OnReceive (const void *buf, size_t len); static int on_message_begin (http_parser *parser); static int on_path (http_parser *parser, const char *at, size_t length); + static int on_query_string (http_parser *parser, const char *at, size_t length); + static int on_uri (http_parser *parser, const char *at, size_t length); + static int on_fragment (http_parser *parser, const char *at, size_t length); static int on_header_field (http_parser *parser, const char *buf, size_t len); static int on_header_value (http_parser *parser, const char *buf, size_t len); static int on_headers_complete (http_parser *parser); diff --git a/src/net.cc b/src/net.cc index dc81a61e3c..2e3b1ecf7c 100644 --- a/src/net.cc +++ b/src/net.cc @@ -26,6 +26,7 @@ using namespace node; #define CONNECT_SYMBOL String::NewSymbol("connect") #define ENCODING_SYMBOL String::NewSymbol("encoding") #define TIMEOUT_SYMBOL String::NewSymbol("timeout") +#define SERVER_SYMBOL String::NewSymbol("server") #define PROTOCOL_SYMBOL String::NewSymbol("protocol") @@ -59,13 +60,19 @@ Connection::Initialize (v8::Handle target) NODE_SET_METHOD(t->InstanceTemplate(), "sendEOF", Connection::v8SendEOF); } -Connection::Connection (Handle handle, Handle protocol) +Connection::Connection (Handle handle, Handle protocol_class) : ObjectWrap(handle) { HandleScope scope; + // Instanciate the protocol object + Handle argv[] = { handle_ }; + Local protocol = protocol_class->NewInstance(1, argv); handle_->Set(PROTOCOL_SYMBOL, protocol); + // TODO use SetNamedPropertyHandler (or whatever) for encoding and timeout + // instead of just reading it once? + encoding_ = RAW; Local encoding_v = protocol->Get(ENCODING_SYMBOL); if (encoding_v->IsString()) { @@ -108,28 +115,21 @@ Connection::GetProtocol (void) return Local(); } +void +Connection::SetAcceptor (Handle acceptor_handle) +{ + HandleScope scope; + handle_->Set(SERVER_SYMBOL, acceptor_handle); +} + Handle Connection::v8New (const Arguments& args) { HandleScope scope; - if (args[0]->IsFunction() == false) return ThrowException(String::New("Must pass a class as the first argument.")); - - Handle protocol = Handle::Cast(args[0]); - - int argc = args.Length(); - Handle argv[argc]; - - argv[0] = args.This(); - for (int i = 1; i < args.Length(); i++) { - argv[i] = args[i]; - } - - Local protocol_instance = protocol->NewInstance(argc, argv); - - new Connection(args.This(), protocol_instance); - + Handle protocol_class = Handle::Cast(args[0]); + new Connection(args.This(), protocol_class); return args.This(); } @@ -370,17 +370,18 @@ Acceptor::OnConnection (struct sockaddr *addr, socklen_t len) { HandleScope scope; - Local protocol_v = handle_->GetHiddenValue(PROTOCOL_SYMBOL); - if (!protocol_v->IsFunction()) { + Local protocol_class_v = handle_->GetHiddenValue(PROTOCOL_SYMBOL); + if (!protocol_class_v->IsFunction()) { Close(); return NULL; } - Local protocol = Local::Cast(protocol_v); + Local protocol_class = Local::Cast(protocol_class_v); - Handle argv[] = { protocol, handle_ }; - Local connection_handle = tcp_connection_constructor->NewInstance(2, argv); + Handle argv[] = { protocol_class }; + Local connection_handle = tcp_connection_constructor->NewInstance(1, argv); Connection *connection = NODE_UNWRAP(Connection, connection_handle); + connection->SetAcceptor(handle_); return connection; } diff --git a/src/net.h b/src/net.h index 60cad4ae64..5384d855e5 100644 --- a/src/net.h +++ b/src/net.h @@ -7,11 +7,13 @@ namespace node { +class Acceptor; + class Connection : public ObjectWrap { public: static void Initialize (v8::Handle target); - Connection (v8::Handle handle, v8::Handle protocol); + Connection (v8::Handle handle, v8::Handle protocol_class); virtual ~Connection () { Close(); } int Connect (struct addrinfo *address) { @@ -30,6 +32,8 @@ public: oi_socket_close (&socket_); } + void SetAcceptor (v8::Handle acceptor_handle); + protected: static v8::Handle v8New (const v8::Arguments& args); static v8::Handle v8Connect (const v8::Arguments& args); diff --git a/test/test-pingpong.js b/test/test-pingpong.js index 8cc4654143..dfb206d637 100644 --- a/test/test-pingpong.js +++ b/test/test-pingpong.js @@ -4,7 +4,7 @@ var port = 12123; var N = 1000; var count = 0; -function Ponger (socket, server) { +function Ponger (socket) { this.encoding = "UTF8"; this.timeout = 0; @@ -28,7 +28,7 @@ function Ponger (socket, server) { this.onDisconnect = function () { puts("ponger: onDisconnect"); - server.close(); + socket.server.close(); }; }