Browse Source

uv_write2 uv_read2_start binding

v0.7.4-release
Ryan Dahl 13 years ago
parent
commit
471c5701c3
  1. 8
      src/pipe_wrap.cc
  2. 2
      src/pipe_wrap.h
  3. 80
      src/stream_wrap.cc
  4. 7
      src/stream_wrap.h
  5. 474
      src/tcp_wrap.cc
  6. 37
      src/tcp_wrap.h

8
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);

2
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);

80
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();

7
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_;
};

474
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

37
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_
Loading…
Cancel
Save