From 9c3770d999988a6543df3ee64019697f7649bbd8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 4 May 2009 17:19:04 +0200 Subject: [PATCH] Implement HTTPServer (untested!) Mostly this is setting up the proper interface to be able to create the HTTP server. --- src/http.cc | 67 ++++++++++++++++++++++++++++++++++++++++++++++------- src/http.h | 15 ++++++++++-- src/net.cc | 31 ++++++++++++++++++------- src/net.h | 6 ++++- src/node.cc | 2 ++ 5 files changed, 101 insertions(+), 20 deletions(-) diff --git a/src/http.cc b/src/http.cc index fae75c971c..bed07efc72 100644 --- a/src/http.cc +++ b/src/http.cc @@ -70,7 +70,8 @@ appendHeaderValue (Handle message, Handle d) _append_header_value->Call(message->ToObject(), 2, argv); } -Persistent HTTPConnection::constructor_template; +Persistent HTTPConnection::client_constructor_template; +Persistent HTTPConnection::server_constructor_template; void HTTPConnection::Initialize (Handle target) @@ -78,11 +79,17 @@ HTTPConnection::Initialize (Handle target) HandleScope scope; Local t = FunctionTemplate::New(HTTPConnection::v8NewClient); - constructor_template = Persistent::New(t); - - constructor_template->Inherit(Connection::constructor_template); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - target->Set(String::NewSymbol("HTTPClient"), constructor_template->GetFunction()); + client_constructor_template = Persistent::New(t); + client_constructor_template->Inherit(Connection::constructor_template); + client_constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + target->Set(String::NewSymbol("HTTPClient"), client_constructor_template->GetFunction()); + + t = FunctionTemplate::New(HTTPConnection::v8NewServer); + server_constructor_template = Persistent::New(t); + server_constructor_template->Inherit(Connection::constructor_template); + server_constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + target->Set(String::NewSymbol("HTTPServerSideSocket"), + server_constructor_template->GetFunction()); } Handle @@ -284,19 +291,61 @@ HTTPConnection::HTTPConnection (Handle handle, Handle protocol parser_.data = this; } -HTTPServer::HTTPServer (Handle handle, Handle options) - :Acceptor(handle, options) +Persistent HTTPServer::constructor_template; + +void +HTTPServer::Initialize (Handle target) { + HandleScope scope; + + Local t = FunctionTemplate::New(HTTPServer::v8New); + constructor_template = Persistent::New(t); + + constructor_template->Inherit(Acceptor::constructor_template); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + target->Set(String::NewSymbol("HTTPServer"), constructor_template->GetFunction()); } Handle HTTPServer::v8New (const Arguments& args) { + HandleScope scope; + + if (args.Length() < 1 || args[0]->IsFunction() == false) + return ThrowException(String::New("Must at give connection handler as the first argument")); + + Local protocol_class = Local::Cast(args[0]); + Local options; + + if (args.Length() > 1 && args[1]->IsObject()) { + options = args[1]->ToObject(); + } else { + options = Object::New(); + } + + new HTTPServer(args.Holder(), protocol_class, options); + + return args.This(); } Connection* HTTPServer::OnConnection (struct sockaddr *addr, socklen_t len) { -} + HandleScope scope; + + Local protocol_class = GetProtocolClass(); + if (protocol_class.IsEmpty()) { + Close(); + return NULL; + } + Handle argv[] = { protocol_class }; + Local connection_handle = + HTTPConnection::server_constructor_template->GetFunction()->NewInstance(1, argv); + + HTTPConnection *connection = NODE_UNWRAP(HTTPConnection, connection_handle); + connection->SetAcceptor(handle_); + + return connection; +} diff --git a/src/http.h b/src/http.h index d62f169c76..df8959145e 100644 --- a/src/http.h +++ b/src/http.h @@ -11,8 +11,10 @@ class HTTPConnection : public Connection { public: static void Initialize (v8::Handle target); + static v8::Persistent client_constructor_template; + static v8::Persistent server_constructor_template; + protected: - static v8::Persistent constructor_template; static v8::Handle v8NewClient (const v8::Arguments& args); static v8::Handle v8NewServer (const v8::Arguments& args); @@ -34,14 +36,23 @@ protected: static int on_message_complete (http_parser *parser); http_parser parser_; + + friend class HTTPServer; }; class HTTPServer : public Acceptor { public: - HTTPServer (v8::Handle handle, v8::Handle options); + static void Initialize (v8::Handle target); protected: + static v8::Persistent constructor_template; static v8::Handle v8New (const v8::Arguments& args); + + HTTPServer (v8::Handle handle, + v8::Handle protocol_class, + v8::Handle options) + :Acceptor(handle, protocol_class, options) {}; + Connection* OnConnection (struct sockaddr *addr, socklen_t len); }; diff --git a/src/net.cc b/src/net.cc index 253f73d1d1..02814f89be 100644 --- a/src/net.cc +++ b/src/net.cc @@ -29,6 +29,7 @@ using namespace node; #define SERVER_SYMBOL String::NewSymbol("server") #define PROTOCOL_SYMBOL String::NewSymbol("protocol") +#define PROTOCOL_CLASS_SYMBOL String::NewSymbol("protocol_class") static const struct addrinfo tcp_hints = /* ai_flags */ { AI_PASSIVE @@ -350,11 +351,13 @@ Acceptor::Initialize (Handle target) constructor_template = Persistent::New(t); } -Acceptor::Acceptor (Handle handle, Handle options) +Acceptor::Acceptor (Handle handle, Handle protocol_class, Handle options) : ObjectWrap(handle) { HandleScope scope; + handle_->SetHiddenValue(PROTOCOL_CLASS_SYMBOL, protocol_class); + int backlog = 1024; // default value Local backlog_v = options->Get(String::NewSymbol("backlog")); if (backlog_v->IsInt32()) { @@ -377,12 +380,12 @@ Acceptor::OnConnection (struct sockaddr *addr, socklen_t len) { HandleScope scope; - Local protocol_class_v = handle_->GetHiddenValue(PROTOCOL_SYMBOL); - if (!protocol_class_v->IsFunction()) { + Local protocol_class = GetProtocolClass(); + if (protocol_class.IsEmpty()) { + printf("protocol class was empty!"); Close(); return NULL; } - Local protocol_class = Local::Cast(protocol_class_v); Handle argv[] = { protocol_class }; Local connection_handle = @@ -413,9 +416,7 @@ Acceptor::v8New (const Arguments& args) if (args.Length() < 1 || args[0]->IsFunction() == false) return ThrowException(String::New("Must at give connection handler as the first argument")); - /// set the handler - args.Holder()->SetHiddenValue(PROTOCOL_SYMBOL, args[0]); - + Local protocol_class = Local::Cast(args[0]); Local options; if (args.Length() > 1 && args[1]->IsObject()) { @@ -424,7 +425,7 @@ Acceptor::v8New (const Arguments& args) options = Object::New(); } - new Acceptor(args.Holder(), options); + new Acceptor(args.This(), protocol_class, options); return args.This(); } @@ -466,3 +467,17 @@ Acceptor::v8Close (const Arguments& args) acceptor->Close(); return Undefined(); } + +Local +Acceptor::GetProtocolClass (void) +{ + HandleScope scope; + + Local protocol_class_v = handle_->GetHiddenValue(PROTOCOL_CLASS_SYMBOL); + if (protocol_class_v->IsFunction()) { + Local protocol_class = Local::Cast(protocol_class_v); + return scope.Close(protocol_class); + } + + return Local(); +} diff --git a/src/net.h b/src/net.h index 115cef6b8f..5cf9b0a693 100644 --- a/src/net.h +++ b/src/net.h @@ -99,9 +99,13 @@ protected: static v8::Handle v8Listen (const v8::Arguments& args); static v8::Handle v8Close (const v8::Arguments& args); - Acceptor (v8::Handle handle, v8::Handle options); + Acceptor (v8::Handle handle, + v8::Handle protocol_class, + v8::Handle options); virtual ~Acceptor () { Close(); } + v8::Local GetProtocolClass (void); + int Listen (struct addrinfo *address) { int r = oi_server_listen (&server_, address); if(r != 0) return r; diff --git a/src/node.cc b/src/node.cc index 3d236753e7..b53de86fac 100644 --- a/src/node.cc +++ b/src/node.cc @@ -250,7 +250,9 @@ main (int argc, char *argv[]) Acceptor::Initialize(g); Connection::Initialize(g); + HTTPConnection::Initialize(g); + HTTPServer::Initialize(g); // NATIVE JAVASCRIPT MODULES TryCatch try_catch;