summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-10-05 12:33:05 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-10-06 22:31:57 -0700
commit471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2 (patch)
tree7dc01b1fdf361c1832a481ec85f88127396aec25
parentf018be3b5f6dad3a92cf41706ad5ed74dc221f6e (diff)
downloadandroid-node-v8-471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2.tar.gz
android-node-v8-471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2.tar.bz2
android-node-v8-471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2.zip
uv_write2 uv_read2_start binding
-rw-r--r--src/pipe_wrap.cc8
-rw-r--r--src/pipe_wrap.h2
-rw-r--r--src/stream_wrap.cc80
-rw-r--r--src/stream_wrap.h7
-rw-r--r--src/tcp_wrap.cc474
-rw-r--r--src/tcp_wrap.h37
6 files changed, 363 insertions, 245 deletions
diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc
index c4f965d65f..1bf59bd2de 100644
--- a/src/pipe_wrap.cc
+++ b/src/pipe_wrap.cc
@@ -86,16 +86,16 @@ Handle<Value> PipeWrap::New(const Arguments& args) {
assert(args.IsConstructCall());
HandleScope scope;
- PipeWrap* wrap = new PipeWrap(args.This());
+ PipeWrap* wrap = new PipeWrap(args.This(), args[0]->IsTrue());
assert(wrap);
return scope.Close(args.This());
}
-PipeWrap::PipeWrap(Handle<Object> object) : StreamWrap(object,
- (uv_stream_t*) &handle_) {
- int r = uv_pipe_init(uv_default_loop(), &handle_, 0);
+PipeWrap::PipeWrap(Handle<Object> object, bool ipc)
+ : StreamWrap(object, (uv_stream_t*) &handle_) {
+ int r = uv_pipe_init(uv_default_loop(), &handle_, ipc);
assert(r == 0); // How do we proxy this error up to javascript?
// Suggestion: uv_pipe_init() returns void.
handle_.data = reinterpret_cast<void*>(this);
diff --git a/src/pipe_wrap.h b/src/pipe_wrap.h
index 1ec51c71f6..df18e8f5bd 100644
--- a/src/pipe_wrap.h
+++ b/src/pipe_wrap.h
@@ -12,7 +12,7 @@ class PipeWrap : StreamWrap {
static void Initialize(v8::Handle<v8::Object> target);
private:
- PipeWrap(v8::Handle<v8::Object> object);
+ PipeWrap(v8::Handle<v8::Object> object, bool ipc);
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> Bind(const v8::Arguments& args);
diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc
index 56d57b23be..548f978987 100644
--- a/src/stream_wrap.cc
+++ b/src/stream_wrap.cc
@@ -2,6 +2,7 @@
#include <node_buffer.h>
#include <handle_wrap.h>
#include <stream_wrap.h>
+#include <tcp_wrap.h>
#include <req_wrap.h>
@@ -95,7 +96,14 @@ Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
UNWRAP
- int r = uv_read_start(wrap->stream_, OnAlloc, OnRead);
+ bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
+ ((uv_pipe_t*)wrap->stream_)->ipc;
+ int r;
+ if (ipc_pipe) {
+ r = uv_read2_start(wrap->stream_, OnAlloc, OnRead2);
+ } else {
+ r = uv_read_start(wrap->stream_, OnAlloc, OnRead);
+ }
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()).code);
@@ -170,9 +178,13 @@ uv_buf_t StreamWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
return buf;
}
-void StreamWrap::OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
+
+void StreamWrap::OnReadCommon(uv_stream_t* handle, ssize_t nread,
+ uv_buf_t buf, uv_handle_type pending) {
HandleScope scope;
+ assert(pending == UV_UNKNOWN_HANDLE); // TODO
+
StreamWrap* wrap = static_cast<StreamWrap*>(handle->data);
// We should not be getting this callback if someone as already called
@@ -201,25 +213,59 @@ void StreamWrap::OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
}
if (nread > 0) {
- Local<Value> argv[3] = {
+ int argc = 3;
+ Local<Value> argv[4] = {
slab_v,
Integer::New(wrap->slab_offset_),
Integer::New(nread)
};
- MakeCallback(wrap->object_, "onread", 3, argv);
+
+ if (pending == UV_TCP) {
+ // Instantiate the client javascript object and handle.
+ Local<Object> pending_obj = TCPWrap::Instantiate();
+
+ // Unwrap the client javascript object.
+ assert(pending_obj->InternalFieldCount() > 0);
+ TCPWrap* pending_wrap =
+ static_cast<TCPWrap*>(pending_obj->GetPointerFromInternalField(0));
+
+ int r = uv_accept(handle, pending_wrap->GetStream());
+ assert(r == 0);
+
+ argv[3] = pending_obj;
+ argc++;
+ } else {
+ // We only support sending UV_TCP right now.
+ assert(pending == UV_UNKNOWN_HANDLE);
+ }
+
+ MakeCallback(wrap->object_, "onread", argc, argv);
}
}
+void StreamWrap::OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
+ OnReadCommon(handle, nread, buf, UV_UNKNOWN_HANDLE);
+}
+
+
+void StreamWrap::OnRead2(uv_pipe_t* handle, ssize_t nread, uv_buf_t buf,
+ uv_handle_type pending) {
+ OnReadCommon((uv_stream_t*)handle, nread, buf, pending);
+}
+
+
Handle<Value> StreamWrap::Write(const Arguments& args) {
HandleScope scope;
UNWRAP
+ bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
+ ((uv_pipe_t*)wrap->stream_)->ipc;
+
// The first argument is a buffer.
assert(Buffer::HasInstance(args[0]));
Local<Object> buffer_obj = args[0]->ToObject();
-
size_t offset = 0;
size_t length = Buffer::Length(buffer_obj);
@@ -239,7 +285,29 @@ Handle<Value> StreamWrap::Write(const Arguments& args) {
buf.base = Buffer::Data(buffer_obj) + offset;
buf.len = length;
- int r = uv_write(&req_wrap->req_, wrap->stream_, &buf, 1, StreamWrap::AfterWrite);
+ int r;
+
+ if (!ipc_pipe) {
+ r = uv_write(&req_wrap->req_, wrap->stream_, &buf, 1, StreamWrap::AfterWrite);
+ } else {
+ uv_stream_t* send_stream = NULL;
+
+ if (args.Length() > 3) {
+ assert(args[3]->IsObject());
+ Local<Object> send_stream_obj = args[3]->ToObject();
+ assert(send_stream_obj->InternalFieldCount() > 0);
+ StreamWrap* send_stream_wrap = static_cast<StreamWrap*>(
+ send_stream_obj->GetPointerFromInternalField(0));
+ send_stream = send_stream_wrap->GetStream();
+ }
+
+ r = uv_write2(&req_wrap->req_,
+ wrap->stream_,
+ &buf,
+ 1,
+ send_stream,
+ StreamWrap::AfterWrite);
+ }
req_wrap->Dispatched();
diff --git a/src/stream_wrap.h b/src/stream_wrap.h
index dd246327c6..93ad7f08c8 100644
--- a/src/stream_wrap.h
+++ b/src/stream_wrap.h
@@ -32,9 +32,14 @@ class StreamWrap : public HandleWrap {
// Callbacks for libuv
static void AfterWrite(uv_write_t* req, int status);
static uv_buf_t OnAlloc(uv_handle_t* handle, size_t suggested_size);
- static void OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf);
static void AfterShutdown(uv_shutdown_t* req, int status);
+ static void OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf);
+ static void OnRead2(uv_pipe_t* handle, ssize_t nread, uv_buf_t buf,
+ uv_handle_type pending);
+ static void OnReadCommon(uv_stream_t* handle, ssize_t nread,
+ uv_buf_t buf, uv_handle_type pending);
+
size_t slab_offset_;
uv_stream_t* stream_;
};
diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc
index 9c0786c1a8..3ba5ef055c 100644
--- a/src/tcp_wrap.cc
+++ b/src/tcp_wrap.cc
@@ -3,6 +3,7 @@
#include <req_wrap.h>
#include <handle_wrap.h>
#include <stream_wrap.h>
+#include <tcp_wrap.h>
// Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop.
#if defined(__MINGW32__) || defined(_MSC_VER)
@@ -45,8 +46,7 @@ using v8::Context;
using v8::Arguments;
using v8::Integer;
-Persistent<Function> tcpConstructor;
-
+static Persistent<Function> tcpConstructor;
static Persistent<String> family_symbol;
static Persistent<String> address_symbol;
static Persistent<String> port_symbol;
@@ -55,314 +55,322 @@ static Persistent<String> port_symbol;
typedef class ReqWrap<uv_connect_t> ConnectWrap;
-class TCPWrap : public StreamWrap {
- public:
+Local<Object> TCPWrap::Instantiate() {
+ HandleScope scope;
+ return scope.Close(tcpConstructor->NewInstance());
+}
- static void Initialize(Handle<Object> target) {
- HandleWrap::Initialize(target);
- StreamWrap::Initialize(target);
- HandleScope scope;
+void TCPWrap::Initialize(Handle<Object> target) {
+ HandleWrap::Initialize(target);
+ StreamWrap::Initialize(target);
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
- t->SetClassName(String::NewSymbol("TCP"));
+ HandleScope scope;
- t->InstanceTemplate()->SetInternalFieldCount(1);
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
+ t->SetClassName(String::NewSymbol("TCP"));
- NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close);
+ t->InstanceTemplate()->SetInternalFieldCount(1);
- NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart);
- NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop);
- NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write);
- NODE_SET_PROTOTYPE_METHOD(t, "shutdown", StreamWrap::Shutdown);
+ NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close);
- NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
- NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen);
- NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
- NODE_SET_PROTOTYPE_METHOD(t, "bind6", Bind6);
- NODE_SET_PROTOTYPE_METHOD(t, "connect6", Connect6);
- NODE_SET_PROTOTYPE_METHOD(t, "getsockname", GetSockName);
- NODE_SET_PROTOTYPE_METHOD(t, "getpeername", GetPeerName);
+ NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart);
+ NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop);
+ NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write);
+ NODE_SET_PROTOTYPE_METHOD(t, "shutdown", StreamWrap::Shutdown);
- tcpConstructor = Persistent<Function>::New(t->GetFunction());
+ NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
+ NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen);
+ NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
+ NODE_SET_PROTOTYPE_METHOD(t, "bind6", Bind6);
+ NODE_SET_PROTOTYPE_METHOD(t, "connect6", Connect6);
+ NODE_SET_PROTOTYPE_METHOD(t, "getsockname", GetSockName);
+ NODE_SET_PROTOTYPE_METHOD(t, "getpeername", GetPeerName);
- family_symbol = NODE_PSYMBOL("family");
- address_symbol = NODE_PSYMBOL("address");
- port_symbol = NODE_PSYMBOL("port");
+ tcpConstructor = Persistent<Function>::New(t->GetFunction());
- target->Set(String::NewSymbol("TCP"), tcpConstructor);
- }
+ family_symbol = NODE_PSYMBOL("family");
+ address_symbol = NODE_PSYMBOL("address");
+ port_symbol = NODE_PSYMBOL("port");
- private:
- static Handle<Value> New(const Arguments& args) {
- // This constructor should not be exposed to public javascript.
- // Therefore we assert that we are not trying to call this as a
- // normal function.
- assert(args.IsConstructCall());
+ target->Set(String::NewSymbol("TCP"), tcpConstructor);
+}
- HandleScope scope;
- TCPWrap* wrap = new TCPWrap(args.This());
- assert(wrap);
- return scope.Close(args.This());
- }
+Handle<Value> TCPWrap::New(const Arguments& args) {
+ // This constructor should not be exposed to public javascript.
+ // Therefore we assert that we are not trying to call this as a
+ // normal function.
+ assert(args.IsConstructCall());
- TCPWrap(Handle<Object> object) : StreamWrap(object,
- (uv_stream_t*) &handle_) {
- int r = uv_tcp_init(uv_default_loop(), &handle_);
- assert(r == 0); // How do we proxy this error up to javascript?
- // Suggestion: uv_tcp_init() returns void.
- UpdateWriteQueueSize();
- }
+ HandleScope scope;
+ TCPWrap* wrap = new TCPWrap(args.This());
+ assert(wrap);
- ~TCPWrap() {
- assert(object_.IsEmpty());
- }
+ return scope.Close(args.This());
+}
+
+
+TCPWrap::TCPWrap(Handle<Object> object)
+ : StreamWrap(object, (uv_stream_t*) &handle_) {
+ int r = uv_tcp_init(uv_default_loop(), &handle_);
+ assert(r == 0); // How do we proxy this error up to javascript?
+ // Suggestion: uv_tcp_init() returns void.
+ UpdateWriteQueueSize();
+}
+
+
+TCPWrap::~TCPWrap() {
+ assert(object_.IsEmpty());
+}
- static Handle<Value> GetSockName(const Arguments& args) {
- HandleScope scope;
- struct sockaddr_storage address;
- int family;
- int port;
- char ip[INET6_ADDRSTRLEN];
-
- UNWRAP
-
- int addrlen = sizeof(address);
- int r = uv_tcp_getsockname(&wrap->handle_,
- reinterpret_cast<sockaddr*>(&address),
- &addrlen);
-
- Local<Object> sockname = Object::New();
- if (r != 0) {
- SetErrno(uv_last_error(uv_default_loop()).code);
- } else {
- family = address.ss_family;
- if (family == AF_INET) {
- struct sockaddr_in* addrin = (struct sockaddr_in*)&address;
- uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN);
- port = ntohs(addrin->sin_port);
- } else if (family == AF_INET6) {
- struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)&address;
- uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN);
- port = ntohs(addrin6->sin6_port);
- }
-
- sockname->Set(port_symbol, Integer::New(port));
- sockname->Set(family_symbol, Integer::New(family));
- sockname->Set(address_symbol, String::New(ip));
+
+Handle<Value> TCPWrap::GetSockName(const Arguments& args) {
+ HandleScope scope;
+ struct sockaddr_storage address;
+ int family;
+ int port;
+ char ip[INET6_ADDRSTRLEN];
+
+ UNWRAP
+
+ int addrlen = sizeof(address);
+ int r = uv_tcp_getsockname(&wrap->handle_,
+ reinterpret_cast<sockaddr*>(&address),
+ &addrlen);
+
+ Local<Object> sockname = Object::New();
+ if (r != 0) {
+ SetErrno(uv_last_error(uv_default_loop()).code);
+ } else {
+ family = address.ss_family;
+ if (family == AF_INET) {
+ struct sockaddr_in* addrin = (struct sockaddr_in*)&address;
+ uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN);
+ port = ntohs(addrin->sin_port);
+ } else if (family == AF_INET6) {
+ struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)&address;
+ uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN);
+ port = ntohs(addrin6->sin6_port);
}
- return scope.Close(sockname);
+ sockname->Set(port_symbol, Integer::New(port));
+ sockname->Set(family_symbol, Integer::New(family));
+ sockname->Set(address_symbol, String::New(ip));
}
-
- static Handle<Value> GetPeerName(const Arguments& args) {
- HandleScope scope;
- struct sockaddr_storage address;
- int family;
- int port;
- char ip[INET6_ADDRSTRLEN];
-
- UNWRAP
-
- int addrlen = sizeof(address);
- int r = uv_tcp_getpeername(&wrap->handle_,
- reinterpret_cast<sockaddr*>(&address),
- &addrlen);
-
- Local<Object> sockname = Object::New();
- if (r != 0) {
- SetErrno(uv_last_error(uv_default_loop()).code);
- } else {
- family = address.ss_family;
- if (family == AF_INET) {
- struct sockaddr_in* addrin = (struct sockaddr_in*)&address;
- uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN);
- port = ntohs(addrin->sin_port);
- } else if (family == AF_INET6) {
- struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)&address;
- uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN);
- port = ntohs(addrin6->sin6_port);
- }
-
- sockname->Set(port_symbol, Integer::New(port));
- sockname->Set(family_symbol, Integer::New(family));
- sockname->Set(address_symbol, String::New(ip));
+ return scope.Close(sockname);
+}
+
+
+Handle<Value> TCPWrap::GetPeerName(const Arguments& args) {
+ HandleScope scope;
+ struct sockaddr_storage address;
+ int family;
+ int port;
+ char ip[INET6_ADDRSTRLEN];
+
+ UNWRAP
+
+ int addrlen = sizeof(address);
+ int r = uv_tcp_getpeername(&wrap->handle_,
+ reinterpret_cast<sockaddr*>(&address),
+ &addrlen);
+
+ Local<Object> sockname = Object::New();
+ if (r != 0) {
+ SetErrno(uv_last_error(uv_default_loop()).code);
+ } else {
+ family = address.ss_family;
+ if (family == AF_INET) {
+ struct sockaddr_in* addrin = (struct sockaddr_in*)&address;
+ uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN);
+ port = ntohs(addrin->sin_port);
+ } else if (family == AF_INET6) {
+ struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)&address;
+ uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN);
+ port = ntohs(addrin6->sin6_port);
}
- return scope.Close(sockname);
+ sockname->Set(port_symbol, Integer::New(port));
+ sockname->Set(family_symbol, Integer::New(family));
+ sockname->Set(address_symbol, String::New(ip));
}
+ return scope.Close(sockname);
+}
- static Handle<Value> Bind(const Arguments& args) {
- HandleScope scope;
- UNWRAP
+Handle<Value> TCPWrap::Bind(const Arguments& args) {
+ HandleScope scope;
- String::AsciiValue ip_address(args[0]->ToString());
- int port = args[1]->Int32Value();
+ UNWRAP
- struct sockaddr_in address = uv_ip4_addr(*ip_address, port);
- int r = uv_tcp_bind(&wrap->handle_, address);
+ String::AsciiValue ip_address(args[0]->ToString());
+ int port = args[1]->Int32Value();
- // Error starting the tcp.
- if (r) SetErrno(uv_last_error(uv_default_loop()).code);
+ struct sockaddr_in address = uv_ip4_addr(*ip_address, port);
+ int r = uv_tcp_bind(&wrap->handle_, address);
- return scope.Close(Integer::New(r));
- }
+ // Error starting the tcp.
+ if (r) SetErrno(uv_last_error(uv_default_loop()).code);
- static Handle<Value> Bind6(const Arguments& args) {
- HandleScope scope;
+ return scope.Close(Integer::New(r));
+}
- UNWRAP
- String::AsciiValue ip6_address(args[0]->ToString());
- int port = args[1]->Int32Value();
+Handle<Value> TCPWrap::Bind6(const Arguments& args) {
+ HandleScope scope;
- struct sockaddr_in6 address = uv_ip6_addr(*ip6_address, port);
- int r = uv_tcp_bind6(&wrap->handle_, address);
+ UNWRAP
- // Error starting the tcp.
- if (r) SetErrno(uv_last_error(uv_default_loop()).code);
+ String::AsciiValue ip6_address(args[0]->ToString());
+ int port = args[1]->Int32Value();
- return scope.Close(Integer::New(r));
- }
+ struct sockaddr_in6 address = uv_ip6_addr(*ip6_address, port);
+ int r = uv_tcp_bind6(&wrap->handle_, address);
- static Handle<Value> Listen(const Arguments& args) {
- HandleScope scope;
+ // Error starting the tcp.
+ if (r) SetErrno(uv_last_error(uv_default_loop()).code);
- UNWRAP
+ return scope.Close(Integer::New(r));
+}
- int backlog = args[0]->Int32Value();
- int r = uv_listen((uv_stream_t*)&wrap->handle_, backlog, OnConnection);
+Handle<Value> TCPWrap::Listen(const Arguments& args) {
+ HandleScope scope;
- // Error starting the tcp.
- if (r) SetErrno(uv_last_error(uv_default_loop()).code);
+ UNWRAP
- return scope.Close(Integer::New(r));
- }
+ int backlog = args[0]->Int32Value();
- static void OnConnection(uv_stream_t* handle, int status) {
- HandleScope scope;
+ int r = uv_listen((uv_stream_t*)&wrap->handle_, backlog, OnConnection);
- TCPWrap* wrap = static_cast<TCPWrap*>(handle->data);
- assert(&wrap->handle_ == (uv_tcp_t*)handle);
+ // Error starting the tcp.
+ if (r) SetErrno(uv_last_error(uv_default_loop()).code);
- // We should not be getting this callback if someone as already called
- // uv_close() on the handle.
- assert(wrap->object_.IsEmpty() == false);
+ return scope.Close(Integer::New(r));
+}
- Handle<Value> argv[1];
- if (status == 0) {
- // Instantiate the client javascript object and handle.
- Local<Object> client_obj = tcpConstructor->NewInstance();
+void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
+ HandleScope scope;
- // Unwrap the client javascript object.
- assert(client_obj->InternalFieldCount() > 0);
- TCPWrap* client_wrap =
- static_cast<TCPWrap*>(client_obj->GetPointerFromInternalField(0));
+ TCPWrap* wrap = static_cast<TCPWrap*>(handle->data);
+ assert(&wrap->handle_ == (uv_tcp_t*)handle);
- int r = uv_accept(handle, (uv_stream_t*)&client_wrap->handle_);
+ // We should not be getting this callback if someone as already called
+ // uv_close() on the handle.
+ assert(wrap->object_.IsEmpty() == false);
- // uv_accept should always work.
- assert(r == 0);
+ Handle<Value> argv[1];
- // Successful accept. Call the onconnection callback in JavaScript land.
- argv[0] = client_obj;
- } else {
- SetErrno(uv_last_error(uv_default_loop()).code);
- argv[0] = v8::Null();
- }
+ if (status == 0) {
+ // Instantiate the client javascript object and handle.
+ Local<Object> client_obj = Instantiate();
- MakeCallback(wrap->object_, "onconnection", 1, argv);
- }
+ // Unwrap the client javascript object.
+ assert(client_obj->InternalFieldCount() > 0);
+ TCPWrap* client_wrap =
+ static_cast<TCPWrap*>(client_obj->GetPointerFromInternalField(0));
- static void AfterConnect(uv_connect_t* req, int status) {
- ConnectWrap* req_wrap = (ConnectWrap*) req->data;
- TCPWrap* wrap = (TCPWrap*) req->handle->data;
+ int r = uv_accept(handle, (uv_stream_t*)&client_wrap->handle_);
- HandleScope scope;
+ // uv_accept should always work.
+ assert(r == 0);
- // The wrap and request objects should still be there.
- assert(req_wrap->object_.IsEmpty() == false);
- assert(wrap->object_.IsEmpty() == false);
+ // Successful accept. Call the onconnection callback in JavaScript land.
+ argv[0] = client_obj;
+ } else {
+ SetErrno(uv_last_error(uv_default_loop()).code);
+ argv[0] = v8::Null();
+ }
- if (status) {
- SetErrno(uv_last_error(uv_default_loop()).code);
- }
+ MakeCallback(wrap->object_, "onconnection", 1, argv);
+}
- Local<Value> argv[3] = {
- Integer::New(status),
- Local<Value>::New(wrap->object_),
- Local<Value>::New(req_wrap->object_)
- };
- MakeCallback(req_wrap->object_, "oncomplete", 3, argv);
+void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
+ ConnectWrap* req_wrap = (ConnectWrap*) req->data;
+ TCPWrap* wrap = (TCPWrap*) req->handle->data;
- delete req_wrap;
+ HandleScope scope;
+
+ // The wrap and request objects should still be there.
+ assert(req_wrap->object_.IsEmpty() == false);
+ assert(wrap->object_.IsEmpty() == false);
+
+ if (status) {
+ SetErrno(uv_last_error(uv_default_loop()).code);
}
- static Handle<Value> Connect(const Arguments& args) {
- HandleScope scope;
+ Local<Value> argv[3] = {
+ Integer::New(status),
+ Local<Value>::New(wrap->object_),
+ Local<Value>::New(req_wrap->object_)
+ };
- UNWRAP
+ MakeCallback(req_wrap->object_, "oncomplete", 3, argv);
- String::AsciiValue ip_address(args[0]->ToString());
- int port = args[1]->Int32Value();
+ delete req_wrap;
+}
- struct sockaddr_in address = uv_ip4_addr(*ip_address, port);
- // I hate when people program C++ like it was C, and yet I do it too.
- // I'm too lazy to come up with the perfect class hierarchy here. Let's
- // just do some type munging.
- ConnectWrap* req_wrap = new ConnectWrap();
-
- int r = uv_tcp_connect(&req_wrap->req_, &wrap->handle_, address,
- AfterConnect);
+Handle<Value> TCPWrap::Connect(const Arguments& args) {
+ HandleScope scope;
- req_wrap->Dispatched();
+ UNWRAP
- if (r) {
- SetErrno(uv_last_error(uv_default_loop()).code);
- delete req_wrap;
- return scope.Close(v8::Null());
- } else {
- return scope.Close(req_wrap->object_);
- }
- }
+ String::AsciiValue ip_address(args[0]->ToString());
+ int port = args[1]->Int32Value();
- static Handle<Value> Connect6(const Arguments& args) {
- HandleScope scope;
+ struct sockaddr_in address = uv_ip4_addr(*ip_address, port);
- UNWRAP
+ // I hate when people program C++ like it was C, and yet I do it too.
+ // I'm too lazy to come up with the perfect class hierarchy here. Let's
+ // just do some type munging.
+ ConnectWrap* req_wrap = new ConnectWrap();
+
+ int r = uv_tcp_connect(&req_wrap->req_, &wrap->handle_, address,
+ AfterConnect);
- String::AsciiValue ip_address(args[0]->ToString());
- int port = args[1]->Int32Value();
+ req_wrap->Dispatched();
- struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port);
+ if (r) {
+ SetErrno(uv_last_error(uv_default_loop()).code);
+ delete req_wrap;
+ return scope.Close(v8::Null());
+ } else {
+ return scope.Close(req_wrap->object_);
+ }
+}
- ConnectWrap* req_wrap = new ConnectWrap();
- int r = uv_tcp_connect6(&req_wrap->req_, &wrap->handle_, address,
- AfterConnect);
+Handle<Value> TCPWrap::Connect6(const Arguments& args) {
+ HandleScope scope;
- req_wrap->Dispatched();
+ UNWRAP
- if (r) {
- SetErrno(uv_last_error(uv_default_loop()).code);
- delete req_wrap;
- return scope.Close(v8::Null());
- } else {
- return scope.Close(req_wrap->object_);
- }
- }
+ String::AsciiValue ip_address(args[0]->ToString());
+ int port = args[1]->Int32Value();
+
+ struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port);
+ ConnectWrap* req_wrap = new ConnectWrap();
- uv_tcp_t handle_;
-};
+ int r = uv_tcp_connect6(&req_wrap->req_, &wrap->handle_, address,
+ AfterConnect);
+
+ req_wrap->Dispatched();
+
+ if (r) {
+ SetErrno(uv_last_error(uv_default_loop()).code);
+ delete req_wrap;
+ return scope.Close(v8::Null());
+ } else {
+ return scope.Close(req_wrap->object_);
+ }
+}
} // namespace node
diff --git a/src/tcp_wrap.h b/src/tcp_wrap.h
new file mode 100644
index 0000000000..f0bf9efab5
--- /dev/null
+++ b/src/tcp_wrap.h
@@ -0,0 +1,37 @@
+#ifndef TCP_WRAP_H_
+#define TCP_WRAP_H_
+#include <stream_wrap.h>
+
+namespace node {
+
+class TCPWrap : public StreamWrap {
+ public:
+ static v8::Local<v8::Object> Instantiate();
+ static TCPWrap* Unwrap(v8::Local<v8::Object> obj);
+ static void Initialize(v8::Handle<v8::Object> target);
+
+ private:
+ TCPWrap(v8::Handle<v8::Object> object);
+ ~TCPWrap();
+
+ static v8::Handle<v8::Value> New(const v8::Arguments& args);
+ static v8::Handle<v8::Value> GetSockName(const v8::Arguments& args);
+ static v8::Handle<v8::Value> GetPeerName(const v8::Arguments& args);
+ static v8::Handle<v8::Value> Bind(const v8::Arguments& args);
+ static v8::Handle<v8::Value> Bind6(const v8::Arguments& args);
+ static v8::Handle<v8::Value> Listen(const v8::Arguments& args);
+ static v8::Handle<v8::Value> Connect(const v8::Arguments& args);
+ static v8::Handle<v8::Value> Connect6(const v8::Arguments& args);
+ static v8::Handle<v8::Value> Open(const v8::Arguments& args);
+
+ static void OnConnection(uv_stream_t* handle, int status);
+ static void AfterConnect(uv_connect_t* req, int status);
+
+ uv_tcp_t handle_;
+};
+
+
+} // namespace node
+
+
+#endif // TCP_WRAP_H_