diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-10-05 12:33:05 -0700 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-10-06 22:31:57 -0700 |
commit | 471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2 (patch) | |
tree | 7dc01b1fdf361c1832a481ec85f88127396aec25 /src | |
parent | f018be3b5f6dad3a92cf41706ad5ed74dc221f6e (diff) | |
download | android-node-v8-471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2.tar.gz android-node-v8-471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2.tar.bz2 android-node-v8-471c5701c30ae0d8abfb2dbd83bd176cf18cb8e2.zip |
uv_write2 uv_read2_start binding
Diffstat (limited to 'src')
-rw-r--r-- | src/pipe_wrap.cc | 8 | ||||
-rw-r--r-- | src/pipe_wrap.h | 2 | ||||
-rw-r--r-- | src/stream_wrap.cc | 80 | ||||
-rw-r--r-- | src/stream_wrap.h | 7 | ||||
-rw-r--r-- | src/tcp_wrap.cc | 474 | ||||
-rw-r--r-- | src/tcp_wrap.h | 37 |
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_ |