summaryrefslogtreecommitdiff
path: root/src/tcp_wrap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcp_wrap.cc')
-rw-r--r--src/tcp_wrap.cc474
1 files changed, 241 insertions, 233 deletions
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