begin clean up of Socket
authorRyan <ry@tinyclouds.org>
Tue, 21 Apr 2009 17:56:30 +0000 (19:56 +0200)
committerRyan <ry@tinyclouds.org>
Tue, 21 Apr 2009 17:56:30 +0000 (19:56 +0200)
src/net.cc
src/node.cc
wscript

index b381ed9..28a24c4 100644 (file)
 
 using namespace v8;
 
-static Persistent<String> readyState_str; 
-
-static Persistent<Integer> readyStateCONNECTING; 
-static Persistent<Integer> readyStateOPEN; 
-static Persistent<Integer> readyStateCLOSED; 
+static struct addrinfo tcp_hints = 
+/* ai_flags      */ { AI_PASSIVE
+/* ai_family     */ , AF_UNSPEC
+/* ai_socktype   */ , SOCK_STREAM
+/* ai_protocol   */ , 0
+/* ai_addrlen    */ , 0
+/* ai_addr       */ , 0
+/* ai_canonname  */ , 0
+/* ai_next       */ , 0
+                    };
 
-enum encoding {UTF8, RAW};
 
 class Socket {
 public:
   Socket (Handle<Object> obj, double timeout);
   ~Socket ();
 
-  int ConnectTCP (char *port, char *host);
-  void Write (Handle<Value> arg);
-  void Disconnect ();
-
   void SetEncoding (enum encoding);
   void SetTimeout (double);
 
-  void OnConnect ();
-  void OnRead (const void *buf, size_t count);
-  void OnDrain ();
-  void OnError (oi_error e);
-  void OnClose ();
+  static Handle<Value> New (const Arguments& args);
+  static Handle<Value> Write (const Arguments& args);
+  static Handle<Value> Close (const Arguments& args);
+  static Handle<Value> ConnectTCP (const Arguments& args);
+
+  static void OnConnect (oi_socket *socket);
+  static void OnRead (oi_socket *s, const void *buf, size_t count);
+  static void OnDrain (oi_socket *s);
+  static void OnError (oi_socket *s, oi_error e);
+  static void OnClose (oi_socket *s);
+  static void OnTimeout (oi_socket *s);
 
 private:
+  static Socket* Unwrap (Handle<Object> handle);
+  static void MakeWeak (Persistent<Value> _, void *data);
+  enum {UTF8, RAW} encoding_;
   oi_socket socket_;
   struct addrinfo *address_;
-  Persistent<Object> js_object_;
+  Persistent<Object> handle_;
 };
 
-static void
-on_connect (oi_socket *socket)
-{
-  Socket *s = static_cast<Socket*> (socket->data);
-  s->OnConnect();
-}
-
-static void
-on_read (oi_socket *socket, const void *buf, size_t count)
-{
-  Socket *s = static_cast<Socket*> (socket->data);
-  s->OnRead(buf, count);
-}
-
-static void
-on_drain (oi_socket *socket)
-{
-  Socket *s = static_cast<Socket*> (socket->data);
-  s->OnDrain();
-}
-
-static void
-on_error (oi_socket *socket, oi_error e)
-{
-  Socket *s = static_cast<Socket*> (socket->data);
-  s->OnError(e);
-}
-
-static void
-on_timeout (oi_socket *socket)
-{
-  Socket *s = static_cast<Socket*> (socket->data);
-  s->OnTimeout(e);
-}
-
-static void
-on_close (oi_socket *socket)
-{
-  Socket *s = static_cast<Socket*> (socket->data);
-  s->OnClose();
-}
-
-
-static Handle<Value>
-NewSocket (const Arguments& args)
+Handle<Value>
+Socket::New(const Arguments& args)
 {
   if (args.Length() > 1)
     return Undefined();
@@ -97,7 +63,7 @@ NewSocket (const Arguments& args)
 
   // Default options 
   double timeout = 60.0; // in seconds
-  enum {RAW, UTF8} encoding = RAW;
+  enum {UTF8, RAW} encoding ;
 
   // Set options from argument.
   if (args.Length() == 1 && args[0]->IsObject()) {
@@ -120,30 +86,30 @@ NewSocket (const Arguments& args)
     }
   }
 
-  Socket *s = new Socket(args.This(), timeout);
+  Socket *s = new Socket(args.Holder(), timeout);
   if(s == NULL)
     return Undefined(); // XXX raise error?
 
   return args.This();
 }
 
-static Socket*
-Unwrapsocket (Handle<Object> obj
+Socket*
+Socket::Unwrap (Handle<Object> handle
 {
   HandleScope scope;
-  Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
+  Handle<External> field = Handle<External>::Cast(handle->GetInternalField(0));
   Socket* socket = static_cast<Socket*>(field->Value());
   return socket;
 }
 
-static Handle<Value>
-SocketConnectTCPCallback (const Arguments& args)
+Handle<Value>
+Socket::ConnectTCP (const Arguments& args)
 {
   if (args.Length() < 1)
     return Undefined();
 
   HandleScope scope;
-  Socket *socket = Unwrapsocket(args.Holder());
+  Socket *socket = Socket::Unwrap(args.Holder());
 
   String::AsciiValue port(args[0]);
 
@@ -153,171 +119,137 @@ SocketConnectTCPCallback (const Arguments& args)
     host = *host_v;
   }
 
-  int r = socket->ConnectTCP(*port, host);
+  int r;
+
+  /* FIXME Blocking DNS resolution. */
+  printf("resolving host: %s, port: %s\n", host, *port);
+  r = getaddrinfo (host, *port, &tcp_hints, &socket->address_);
+  if(r != 0)  {
+    perror("getaddrinfo");
+    return Undefined(); 
+  }
+
+  r = oi_socket_connect (&socket->socket_, socket->address_);
+  if(r != 0)  {
+    perror("oi_socket_connect");
+    return Undefined(); 
+  }
+  oi_socket_attach (&socket->socket_, node_loop());
+
+  freeaddrinfo(socket->address_);
+  socket->address_ = NULL;
   // TODO raise error if r != 0
     
   return Undefined(); 
 }
 
-static Handle<Value>
-SocketWriteCallback (const Arguments& args) 
+Handle<Value>
+Socket::Close (const Arguments& args) 
 {
   HandleScope scope;
-  Socket *socket = Unwrapsocket(args.Holder());
-  socket->Write(args[0]);
+  Socket *socket = Socket::Unwrap(args.Holder());
+  oi_socket_close(&socket->socket_);
   return Undefined();
 }
 
-static Handle<Value>
-SocketCloseCallback (const Arguments& args) 
-{
-  HandleScope scope;
-  Socket *socket = Unwrapsocket(args.Holder());
-  socket->Disconnect();
-  return Undefined();
-}
-
-static void
-DestroySocket (Persistent<Value> _, void *data)
+void
+Socket::MakeWeak (Persistent<Value> _, void *data)
 {
   Socket *s = static_cast<Socket*> (data);
   delete s;
 }
 
-Socket::Socket(Handle<Object> js_object, double timeout)
+Socket::Socket(Handle<Object> handle, double timeout)
 {
   oi_socket_init(&socket_, timeout);
-  socket_.on_connect = on_connect;
-  socket_.on_read    = on_read;
-  socket_.on_drain   = on_drain;
-  socket_.on_error   = on_error;
-  socket_.on_close   = on_close;
-  socket_.on_timeout = on_timeout;
+  socket_.on_connect = Socket::OnConnect;
+  socket_.on_read    = Socket::OnRead;
+  socket_.on_drain   = Socket::OnDrain;
+  socket_.on_error   = Socket::OnError;
+  socket_.on_close   = Socket::OnClose;
+  socket_.on_timeout = Socket::OnTimeout;
   socket_.data = this;
 
   HandleScope scope;
-  js_object_ = Persistent<Object>::New(js_object);
-  js_object_->SetInternalField (0, External::New(this));
-  js_object_.MakeWeak (this, DestroySocket);
+  handle_ = Persistent<Object>::New(handle);
+  handle_->SetInternalField (0, External::New(this));
+  handle_.MakeWeak (this, Socket::MakeWeak);
+
+  encoding_ = UTF8;
 }
 
 Socket::~Socket ()
 {
-  Disconnect();
+  oi_socket_close(&socket_);
   oi_socket_detach(&socket_);
-  js_object_.Dispose();
-  js_object_.Clear(); // necessary? 
+  handle_.Dispose();
+  handle_.Clear(); // necessary? 
 }
 
-static struct addrinfo tcp_hints = 
-/* ai_flags      */ { AI_PASSIVE
-/* ai_family     */ , AF_UNSPEC
-/* ai_socktype   */ , SOCK_STREAM
-/* ai_protocol   */ , 0
-/* ai_addrlen    */ , 0
-/* ai_addr       */ , 0
-/* ai_canonname  */ , 0
-/* ai_next       */ , 0
-                    };
-
-int
-Socket::ConnectTCP(char *port, char *host)
+Handle<Value>
+Socket::Write (const Arguments& args) 
 {
-  int r;
-
   HandleScope scope;
 
-  js_object_->Set(readyState_str, readyStateCONNECTING);
-
-  /* FIXME Blocking DNS resolution. */
-  printf("resolving host: %s, port: %s\n", host, port);
-  r = getaddrinfo (host, port, &tcp_hints, &address);
-  if(r != 0)  {
-    perror("getaddrinfo");
-    return r;
-  }
-
-  r = oi_socket_connect (&socket, address);
-  if(r != 0)  {
-    perror("oi_socket_connect");
-    return r;
-  }
-  oi_socket_attach (&socket, node_loop());
-
-  freeaddrinfo(address);
-  address = NULL;
-}
-
-void Socket::Write (Handle<Value> arg)
-{
-  HandleScope scope;
+  Socket *socket = Socket::Unwrap(args.Holder());
  
-  if (arg == Null()) {
-
-    oi_socket_write_eof(&socket);
+  if (args[0] == Null()) {
+    oi_socket_write_eof(&socket->socket_);
 
-  } else if (arg->IsString()) {
-    Local<String> s = arg->ToString();
-
-    size_t l1 = s->Utf8Length(), l2;
-    oi_buf *buf = oi_buf_new2(l1);
-    l2 = s->WriteUtf8(buf->base, l1);
-    assert(l1 == l2);
-
-    oi_socket_write(&socket, buf);
+  } else if (args[0]->IsString()) {
+    // utf8 encoding
+    Local<String> s = args[0]->ToString();
+    size_t length = s->Utf8Length();
+    oi_buf *buf = oi_buf_new2(length);
+    s->WriteUtf8(buf->base, length);
+    oi_socket_write(&socket->socket_, buf);
 
-  } else if (arg->IsArray()) {
+  } else if (args[0]->IsArray()) {
+    // raw encoding
+    Handle<Array> array = Handle<Array>::Cast(args[0]);
     size_t length = array->Length();
-    Handle<Array> array = Handle<Array>::Cast(arg);
     oi_buf *buf = oi_buf_new2(length);
     for (int i = 0; i < length; i++) {
       Local<Value> int_value = array->Get(Integer::New(i));
-      buf[i] = int_value->Int32Value();
+      buf->base[i] = int_value->Int32Value();
     }
-
-    oi_socket_write(&socket, buf);
+    oi_socket_write(&socket->socket_, buf);
 
   } else {
     // raise error bad argument.
     assert(0);
   }
-}
-void
-Socket::Disconnect()
-{
-  oi_socket_close(&socket);
+
+  return Undefined();
 }
 
 void
-Socket::OnConnect()
+Socket::OnConnect (oi_socket *s)
 {
-  HandleScope scope;
+  Socket *socket = static_cast<Socket*> (s->data);
 
-  assert(READY_STATE_CONNECTING == ReadyState());
-  js_object_->Set(readyState_str, readyStateOPEN);
+  HandleScope scope;
 
-  Handle<Value> on_connect_value = js_object_->Get( String::NewSymbol("on_connect") );
+  Handle<Value> on_connect_value = socket->handle_->Get( String::NewSymbol("onConnect") );
   if (!on_connect_value->IsFunction())
     return; 
   Handle<Function> on_connect = Handle<Function>::Cast(on_connect_value);
 
   TryCatch try_catch;
 
-  Handle<Value> r = on_connect->Call(js_object_, 0, NULL);
+  Handle<Value> r = on_connect->Call(socket->handle_, 0, NULL);
 
   if(try_catch.HasCaught())
     node_fatal_exception(try_catch);
 }
 
 void
-Socket::OnRead (const void *buf, size_t count)
+Socket::OnRead (oi_socket *s, const void *buf, size_t count)
 {
+  Socket *socket = static_cast<Socket*> (s->data);
   HandleScope scope;
 
-  assert(READY_STATE_OPEN == ReadyState());
-
-  Handle<Value> onread_value = js_object_->Get( String::NewSymbol("on_read") );
+  Handle<Value> onread_value = socket->handle_->Get( String::NewSymbol("onRead") );
   if (!onread_value->IsFunction()) return; 
   Handle<Function> onread = Handle<Function>::Cast(onread_value);
 
@@ -325,101 +257,118 @@ Socket::OnRead (const void *buf, size_t count)
   Handle<Value> argv[argc];
 
   if(count) {
-    Handle<String> chunk = String::New((const char*)buf, count); // TODO binary data?
-    argv[0] = chunk;
+    if(socket->encoding_ == UTF8) {
+      // utf8 encoding
+      Handle<String> chunk = String::New((const char*)buf, count);
+      argv[0] = chunk;
+    } else {
+      // raw encoding
+      Local<Array> array = Array::New(count);
+      for (int i = 0; i < count; i++) {
+        int val = static_cast<const int*>(buf)[i];
+        array->Set(Integer::New(i), Integer::New(val));
+      }
+      argv[0] = array;
+    }
   } else {
-    // TODO eof? delete write method?
-    argv[0] = Null();
+    argv[0] = Local<Value>::New(Null());
   }
 
   TryCatch try_catch;
 
-  Handle<Value> r = onread->Call(js_object_, argc, argv);
+  Handle<Value> r = onread->Call(socket->handle_, argc, argv);
+
+  if(try_catch.HasCaught())
+    node_fatal_exception(try_catch);
+}
+
+void
+Socket::OnClose (oi_socket *s)
+{
+  Socket *socket = static_cast<Socket*> (s->data);
+  HandleScope scope;
+
+  Handle<Value> onclose_value = socket->handle_->Get( String::NewSymbol("onClose") );
+  if (!onclose_value->IsFunction()) return; 
+  Handle<Function> onclose = Handle<Function>::Cast(onclose_value);
+
+  TryCatch try_catch;
+
+  Handle<Value> r = onclose->Call(socket->handle_, 0, NULL);
+
+  if(try_catch.HasCaught())
+    node_fatal_exception(try_catch);
+}
+
+void
+Socket::OnDrain (oi_socket *s)
+{
+  Socket *socket = static_cast<Socket*> (s->data);
+  HandleScope scope;
+
+  Handle<Value> onclose_value = socket->handle_->Get( String::NewSymbol("onDrain") );
+  if (!onclose_value->IsFunction()) return; 
+  Handle<Function> onclose = Handle<Function>::Cast(onclose_value);
+
+  TryCatch try_catch;
+
+  Handle<Value> r = onclose->Call(socket->handle_, 0, NULL);
 
   if(try_catch.HasCaught())
     node_fatal_exception(try_catch);
 }
 
+
 void
-Socket::OnClose ()
+Socket::OnError (oi_socket *s, oi_error e)
 {
+  Socket *socket = static_cast<Socket*> (s->data);
   HandleScope scope;
 
-  printf("onclose readyState %d\n", ReadyState());
+  Handle<Value> onclose_value = socket->handle_->Get( String::NewSymbol("onError") );
+  if (!onclose_value->IsFunction()) return; 
+  Handle<Function> onclose = Handle<Function>::Cast(onclose_value);
+
+  TryCatch try_catch;
 
-  assert(READY_STATE_OPEN == ReadyState());
-  js_object_->Set(readyState_str, readyStateCLOSED);
+  Handle<Value> r = onclose->Call(socket->handle_, 0, NULL);
+
+  if(try_catch.HasCaught())
+    node_fatal_exception(try_catch);
+}
 
-  Handle<Value> onclose_value = js_object_->Get( String::NewSymbol("on_close") );
+void
+Socket::OnTimeout (oi_socket *s)
+{
+  Socket *socket = static_cast<Socket*> (s->data);
+  HandleScope scope;
+
+  Handle<Value> onclose_value = socket->handle_->Get( String::NewSymbol("onTimeout") );
   if (!onclose_value->IsFunction()) return; 
   Handle<Function> onclose = Handle<Function>::Cast(onclose_value);
 
   TryCatch try_catch;
 
-  Handle<Value> r = onclose->Call(js_object_, 0, NULL);
+  Handle<Value> r = onclose->Call(socket->handle_, 0, NULL);
 
   if(try_catch.HasCaught())
     node_fatal_exception(try_catch);
 }
 
+
 void
 NodeInit_net (Handle<Object> target)
 {
   HandleScope scope;
 
-  //
-  // Socket
-  //
-  Local<FunctionTemplate> socket_template = FunctionTemplate::New(NewSocket);
-  target->Set(String::NewSymbol("Socket"), socket_template->GetFunction());
+  Local<FunctionTemplate> socket_template = FunctionTemplate::New(Socket::New);
   socket_template->InstanceTemplate()->SetInternalFieldCount(1);
+  target->Set(String::NewSymbol("Socket"), socket_template->GetFunction());
+
+  NODE_SET_METHOD(socket_template->InstanceTemplate(), "connectTCP", Socket::ConnectTCP);
+  //NODE_SET_METHOD(socket_template->InstanceTemplate(), "connectUNIX", Socket::ConnectUNIX);
+  NODE_SET_METHOD(socket_template->InstanceTemplate(), "write", Socket::Write);
+  NODE_SET_METHOD(socket_template->InstanceTemplate(), "close", Socket::Close);
 
-  // socket.connectTCP()
-  Local<FunctionTemplate> socket_connect_tcp = 
-      FunctionTemplate::New(SocketConnectTCPCallback);
-  socket_template->InstanceTemplate()->Set(String::NewSymbol("connectTCP"), 
-                                           socket_connect_tcp->GetFunction());
-
-  // socket.connectUNIX()
-  Local<FunctionTemplate> socket_connect_unix = 
-      FunctionTemplate::New(SocketConnectUNIXCallback);
-  socket_template->InstanceTemplate()->Set(String::NewSymbol("connectUNIX"), 
-                                           socket_connect_unix->GetFunction());
-
-  // socket.write()
-  Local<FunctionTemplate> socket_write =
-      FunctionTemplate::New(SocketWriteCallback);
-  socket_template->InstanceTemplate()->Set(String::NewSymbol("write"), 
-                                           socket_write->GetFunction());
-
-  // socket.close()
-  Local<FunctionTemplate> socket_close = 
-      FunctionTemplate::New(SocketCloseCallback);
-  socket_template->InstanceTemplate()->Set(String::NewSymbol("close"), 
-                                           socket_close->GetFunction());
-
-  //
-  // Server
-  //
-  Local<FunctionTemplate> server_template = FunctionTemplate::New(NewServer);
-  target->Set(String::NewSymbol("Server"), server_template->GetFunction());
-  server_template->InstanceTemplate()->SetInternalFieldCount(1);
-
-  // server.listenTCP()
-  Local<FunctionTemplate> server_listenTCP =
-      FunctionTemplate::New(ServerListenTCPCallback);
-  server_template->InstanceTemplate()->Set(String::NewSymbol("listenTCP"), 
-                                           server_listenTCP->GetFunction());
-
-  // server.listenUNIX()
-  Local<FunctionTemplate> server_listenUNIX =
-      FunctionTemplate::New(ServerListenUNIXCallback);
-  server_template->InstanceTemplate()->Set(String::NewSymbol("listenUNIX"), 
-                                           server_listenTCP->GetFunction());
-
-  // server.close()
-  Local<FunctionTemplate> server_close = FunctionTemplate::New(ServerCloseCallback);
-  server_template->InstanceTemplate()->Set(String::NewSymbol("close"), 
-                                           server_close->GetFunction());
 }
 
index e6c296d..1b73a34 100644 (file)
@@ -1,6 +1,6 @@
 #include "node.h"
 
-//#include "net.h"
+#include "net.h"
 #include "file.h"
 #include "process.h"
 #include "http.h"
@@ -116,7 +116,7 @@ static void
 OnFatalError (const char* location, const char* message)
 {
   fprintf(stderr, "Fatal error: %s %s\n", location, message);
-  ev_unloop(node_loop(), EVUNLOOP_ALL);
+  exit(1);
 }
 
 
@@ -205,7 +205,7 @@ main (int argc, char *argv[])
   g->Set(String::New("ARGV"), arguments);
 
   // BUILT-IN MODULES
-  //NodeInit_net(g);
+  NodeInit_net(g);
   NodeInit_timers(g);
   NodeInit_process(g);
   NodeInit_file(g);
diff --git a/wscript b/wscript
index 0ca9522..dc33171 100644 (file)
--- a/wscript
+++ b/wscript
@@ -128,6 +128,7 @@ def build(bld):
   node.source = """
     src/node.cc
     src/http.cc
+    src/net.cc
     src/process.cc
     src/file.cc
     src/timers.cc