Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
in the middle putting in event code. broken.
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Jun 28, 2009
1 parent bd952ac commit 2ecd7ff
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 63 deletions.
56 changes: 56 additions & 0 deletions src/events.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "events.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h> /* inet_ntop */
#include <netinet/in.h> /* sockaddr_in, sockaddr_in6 */

using namespace v8;
using namespace node;

Persistent<FunctionTemplate> EventEmitter::constructor_template;

void
EventEmitter::Initialize (v8::Handle<v8::Object> target)
{
HandleScope scope;

Local<FunctionTemplate> t = FunctionTemplate::New();
constructor_template = Persistent<FunctionTemplate>::New(t);

// All prototype methods are defined in events.js

target->Set(String::NewSymbol("EventEmitter"), constructor_template->GetFunction());
}

bool
EventEmitter::Emit (const char *type, int argc, Handle<Value> argv[])
{
Local<Value> emit_v = handle_->Get(String::NewSymbol("emit"));
assert(emit_v->IsFunction());
Local<Function> emit = Local<Function>::Cast(emit_v);

Local<Array> event_args = Array::New(argc);
for (int i = 0; i < argc; i++) {
event_args->Set(Integer::New(i), argv[i]);
}

Handle<Value> emit_argv[2] = { String::NewSymbol(type), event_args };

TryCatch try_catch;

emit->Call(handle_, 2, emit_argv);

if (try_catch.HasCaught()) {
FatalException(try_catch);
return false;
}

return true;
}
21 changes: 21 additions & 0 deletions src/events.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef node_events_h
#define node_events_h

#include "node.h"
#include <v8.h>

namespace node {

class EventEmitter : public ObjectWrap {
public:
static void Initialize (v8::Handle<v8::Object> target);
static v8::Persistent<v8::FunctionTemplate> constructor_template;

bool Emit (const char *type, int argc, v8::Handle<v8::Value> argv[]);

EventEmitter (v8::Handle<v8::Object> handle)
: ObjectWrap(handle) { };
};

} // namespace node
#endif
33 changes: 33 additions & 0 deletions src/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
(function () {

// node.EventEmitter is defined in src/events.cc
var emitter = node.EventEmitter.prototype;

emitter.addListener = function (type, listener) {
if (!this._events) this._events = {};
if (!this._events.hasOwnProperty(type)) this._events[type] = [];
this._events[type].push(listener);
};

emitter.listeners = function (type, listener) {
if (!this._events) this._events = {};
if (!this._events.hasOwnProperty(type)) this._events[type] = [];
return this._events[type];
};

/* This function is called often from C++.
* See events.cc
*/
emitter.emit = function (type, args) {
if (this["on" + type] instanceof Function) {
this["on" + type].apply(this, args);
}
if (!this._events) return;
if (!this._events.hasOwnProperty(type)) return;
for (var i = 0; i < this._events[type].length; i++) {
var listener = this._events[type][i];
listener.apply(this, args);
}
};

})(); // end annonymous namespace
77 changes: 17 additions & 60 deletions src/net.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "net.h"
#include "events.h"

#include <assert.h>
#include <stdlib.h>
Expand All @@ -18,21 +19,12 @@ using namespace node;
#define RAW_SYMBOL String::NewSymbol("raw")
#define ASCII_SYMBOL String::NewSymbol("ascii")

#define ON_RECEIVE_SYMBOL String::NewSymbol("onReceive")
#define ON_DISCONNECT_SYMBOL String::NewSymbol("onDisconnect")
#define ON_CONNECT_SYMBOL String::NewSymbol("onConnect")
#define ON_DRAIN_SYMBOL String::NewSymbol("onDrain")
#define ON_TIMEOUT_SYMBOL String::NewSymbol("onTimeout")
#define ON_ERROR_SYMBOL String::NewSymbol("onError")
#define ON_EOF_SYMBOL String::NewSymbol("onEOF")

#define ENCODING_SYMBOL String::NewSymbol("encoding")
#define TIMEOUT_SYMBOL String::NewSymbol("timeout")
#define SERVER_SYMBOL String::NewSymbol("server")
#define REMOTE_ADDRESS_SYMBOL String::NewSymbol("remoteAddress")

#define PROTOCOL_SYMBOL String::NewSymbol("protocol")
#define CONNECTION_HANDLER_SYMBOL String::NewSymbol("connectionHandler")

#define READY_STATE_SYMBOL String::NewSymbol("readyState")
#define OPEN_SYMBOL String::NewSymbol("open")
Expand Down Expand Up @@ -65,6 +57,7 @@ Connection::Initialize (v8::Handle<v8::Object> target)
Local<FunctionTemplate> t = FunctionTemplate::New(New);

constructor_template = Persistent<FunctionTemplate>::New(t);
constructor_template->Inherit(EventEmitter::constructor_template);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

NODE_SET_PROTOTYPE_METHOD(constructor_template, "connect", Connect);
Expand Down Expand Up @@ -102,7 +95,7 @@ Connection::ReadyStateGetter (Local<String> _, const AccessorInfo& info)
}

Connection::Connection (Handle<Object> handle)
: ObjectWrap(handle)
: EventEmitter(handle)
{
encoding_ = RAW;

Expand Down Expand Up @@ -439,11 +432,6 @@ Connection::OnReceive (const void *buf, size_t len)
{
HandleScope scope;

Handle<Value> callback_v = handle_->Get(ON_RECEIVE_SYMBOL);
if (!callback_v->IsFunction()) return;

Handle<Function> callback = Handle<Function>::Cast(callback_v);

const int argc = 1;
Handle<Value> argv[argc];

Expand All @@ -466,47 +454,31 @@ Connection::OnReceive (const void *buf, size_t len)
argv[0] = Local<Value>::New(Null());
}

TryCatch try_catch;
callback->Call(handle_, argc, argv);

if (try_catch.HasCaught())
FatalException(try_catch);
Emit("Receive", argc, argv);
}

void
Connection::OnDisconnect ()
{
HandleScope scope;
Local<Value> callback_v = handle_->Get(ON_DISCONNECT_SYMBOL);
if (!callback_v->IsFunction()) return;
Handle<Function> callback = Handle<Function>::Cast(callback_v);

Handle<Value> argv[1];
argv[0] = socket_.errorno == 0 ? False() : True();

TryCatch try_catch;
callback->Call(handle_, 1, argv);
if (try_catch.HasCaught())
node::FatalException(try_catch);
Emit("Disconnect", 1, argv);
}

#define DEFINE_SIMPLE_CALLBACK(name, symbol) \
#define DEFINE_SIMPLE_CALLBACK(name, type) \
void name () \
{ \
HandleScope scope; \
Local<Value> callback_v = handle_->Get(symbol); \
if (!callback_v->IsFunction()) return; \
Handle<Function> callback = Handle<Function>::Cast(callback_v); \
TryCatch try_catch; \
callback->Call(handle_, 0, NULL); \
if (try_catch.HasCaught()) \
node::FatalException(try_catch); \
Emit (type, 0, NULL); \
}

DEFINE_SIMPLE_CALLBACK(Connection::OnConnect, ON_CONNECT_SYMBOL)
DEFINE_SIMPLE_CALLBACK(Connection::OnDrain, ON_DRAIN_SYMBOL)
DEFINE_SIMPLE_CALLBACK(Connection::OnTimeout, ON_TIMEOUT_SYMBOL)
DEFINE_SIMPLE_CALLBACK(Connection::OnEOF, ON_EOF_SYMBOL)
DEFINE_SIMPLE_CALLBACK(Connection::OnConnect, "Connect")
DEFINE_SIMPLE_CALLBACK(Connection::OnDrain, "Drain")
DEFINE_SIMPLE_CALLBACK(Connection::OnTimeout, "Timeout")
DEFINE_SIMPLE_CALLBACK(Connection::OnEOF, "EOF")

Persistent<FunctionTemplate> Acceptor::constructor_template;

Expand All @@ -517,7 +489,7 @@ Acceptor::Initialize (Handle<Object> target)

Local<FunctionTemplate> t = FunctionTemplate::New(New);
constructor_template = Persistent<FunctionTemplate>::New(t);

constructor_template->Inherit(EventEmitter::constructor_template);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

NODE_SET_PROTOTYPE_METHOD(constructor_template, "listen", Listen);
Expand All @@ -527,24 +499,21 @@ Acceptor::Initialize (Handle<Object> target)
}

Acceptor::Acceptor (Handle<Object> handle, Handle<Function> connection_handler, Handle<Object> options)
: ObjectWrap(handle)
: EventEmitter(handle)
{
HandleScope scope;

#if 0
handle_->SetHiddenValue(CONNECTION_HANDLER_SYMBOL, connection_handler);

int backlog = 1024; // default value
Local<Value> backlog_v = options->Get(String::NewSymbol("backlog"));
if (backlog_v->IsInt32()) {
backlog = backlog_v->IntegerValue();
}
#endif

Local<Value> on_error_v = options->Get(ON_ERROR_SYMBOL);
if (on_error_v->IsFunction()) {
handle_->Set(ON_ERROR_SYMBOL, on_error_v);
}

oi_server_init(&server_, backlog);
oi_server_init(&server_, 1024);
server_.on_connection = Acceptor::on_connection;
server_.data = this;
}
Expand Down Expand Up @@ -588,16 +557,6 @@ Connection*
Acceptor::OnConnection (struct sockaddr *addr, socklen_t len)
{
HandleScope scope;

Local<Value> connection_handler_v =
handle_->GetHiddenValue(CONNECTION_HANDLER_SYMBOL);
if (!connection_handler_v->IsFunction()) {
printf("Connection handler was empty!");
Close();
return NULL;
}
Local<Function> connection_handler =
Local<Function>::Cast(connection_handler_v);

TryCatch try_catch;

Expand All @@ -617,10 +576,8 @@ Acceptor::OnConnection (struct sockaddr *addr, socklen_t len)
connection->SetAcceptor(handle_);

Handle<Value> argv[1] = { js_connection };
Local<Value> ret = connection_handler->Call(handle_, 1, argv);

if (ret.IsEmpty())
FatalException(try_catch);
Emit("Connection", 1, argv);

return connection;
}
Expand Down
5 changes: 3 additions & 2 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
#define node_net_h

#include "node.h"
#include "events.h"
#include <v8.h>
#include <oi_socket.h>

namespace node {

class Acceptor;

class Connection : public ObjectWrap {
class Connection : public EventEmitter {
public:
static void Initialize (v8::Handle<v8::Object> target);

Expand Down Expand Up @@ -107,7 +108,7 @@ class Connection : public ObjectWrap {
friend class Acceptor;
};

class Acceptor : public ObjectWrap {
class Acceptor : public EventEmitter {
public:
static void Initialize (v8::Handle<v8::Object> target);

Expand Down
3 changes: 3 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "node.h"

#include "events.h"
#include "net.h"
#include "file.h"
#include "http.h"
Expand Down Expand Up @@ -312,6 +313,7 @@ Load (int argc, char *argv[])
NODE_SET_METHOD(node_obj, "debug", debug);
NODE_SET_METHOD(node_obj, "reallyExit", node_exit);

EventEmitter::Initialize(node_obj);
Timer::Initialize(node_obj);
Process::Initialize(node_obj);

Expand All @@ -331,6 +333,7 @@ Load (int argc, char *argv[])
HTTPServer::Initialize(http);
HTTPConnection::Initialize(http);

ExecuteNativeJS("events.js", native_events);
ExecuteNativeJS("http.js", native_http);
ExecuteNativeJS("file.js", native_file);
ExecuteNativeJS("node.js", native_node);
Expand Down
6 changes: 6 additions & 0 deletions src/node.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
node.tcp.Server = function (on_connection, options) {
this.__proto__ = node.tcp.LowLevelServer ();
node.debug("hello world");
if (on_connection) this.addListener("Connection", on_connection);
};

// Timers

function setTimeout (callback, delay) {
Expand Down
8 changes: 7 additions & 1 deletion wscript
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,12 @@ def build(bld):
js2c.JS2C(source, targets)

native_cc = bld.new_task_gen(
source="src/http.js src/file.js src/node.js",
source = """
src/events.js
src/http.js
src/file.js
src/node.js
""",
target="src/natives.h",
rule=javascript_in_c,
before="cxx"
Expand All @@ -155,6 +160,7 @@ def build(bld):
node.target = 'node'
node.source = """
src/node.cc
src/events.cc
src/http.cc
src/net.cc
src/file.cc
Expand Down

0 comments on commit 2ecd7ff

Please sign in to comment.