Browse Source

Make Socket, Bind, Listen, Accept work for windows

v0.7.4-release
Bert Belder 14 years ago
parent
commit
13fb6f7fa1
  1. 85
      src/node_net.cc

85
src/node_net.cc

@ -13,6 +13,7 @@
#ifdef __MINGW32__ #ifdef __MINGW32__
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h>
#else // __POSIX__ #else // __POSIX__
# include <sys/ioctl.h> # include <sys/ioctl.h>
@ -162,6 +163,8 @@ static Handle<Value> SocketPair(const Arguments& args) {
return scope.Close(a); return scope.Close(a);
} }
#endif
// Creates a new non-blocking socket fd // Creates a new non-blocking socket fd
// t.socket("TCP"); // t.socket("TCP");
@ -219,7 +222,11 @@ static Handle<Value> Socket(const Arguments& args) {
} }
} }
#ifdef __POSIX__
int fd = socket(domain, type, 0); int fd = socket(domain, type, 0);
#else // __MINGW32__
int fd = _open_osfhandle(socket(domain, type, 0), 0);
#endif
if (fd < 0) return ThrowException(ErrnoException(errno, "socket")); if (fd < 0) return ThrowException(ErrnoException(errno, "socket"));
@ -250,10 +257,15 @@ static socklen_t addrlen;
static inline Handle<Value> ParseAddressArgs(Handle<Value> first, static inline Handle<Value> ParseAddressArgs(Handle<Value> first,
Handle<Value> second, Handle<Value> second,
bool is_bind) { bool is_bind) {
#ifdef __POSIX__ // No unix sockets on windows
static struct sockaddr_un un; static struct sockaddr_un un;
#endif
static struct sockaddr_in in; static struct sockaddr_in in;
static struct sockaddr_in6 in6; static struct sockaddr_in6 in6;
#ifdef __POSIX__ // No unix sockets on windows
static struct sockaddr_un un;
if (first->IsString() && !second->IsString()) { if (first->IsString() && !second->IsString()) {
// UNIX // UNIX
String::Utf8Value path(first->ToString()); String::Utf8Value path(first->ToString());
@ -270,6 +282,11 @@ static inline Handle<Value> ParseAddressArgs(Handle<Value> first,
addrlen = sizeof(un) - sizeof(un.sun_path) + path.length() + 1; addrlen = sizeof(un) - sizeof(un.sun_path) + path.length() + 1;
} else { } else {
#else // __MINGW32__
if (first->IsString() && !second->IsString()) {
return ErrnoException(errno, "ParseAddressArgs", "Unix sockets are not supported on windows");
} else {
#endif
// TCP or UDP // TCP or UDP
memset(&in, 0, sizeof in); memset(&in, 0, sizeof in);
memset(&in6, 0, sizeof in6); memset(&in6, 0, sizeof in6);
@ -321,9 +338,13 @@ static Handle<Value> Bind(const Arguments& args) {
if (!error.IsEmpty()) return ThrowException(error); if (!error.IsEmpty()) return ThrowException(error);
int flags = 1; int flags = 1;
#ifdef __POSIX__
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
int r = bind(fd, addr, addrlen); int r = bind(fd, addr, addrlen);
#else // __MINGW32__
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&flags, sizeof(flags));
int r = bind(_get_osfhandle(fd), addr, addrlen);
#endif
if (r < 0) { if (r < 0) {
return ThrowException(ErrnoException(errno, "bind")); return ThrowException(ErrnoException(errno, "bind"));
@ -332,8 +353,6 @@ static Handle<Value> Bind(const Arguments& args) {
return Undefined(); return Undefined();
} }
#endif // __POSIX__
static Handle<Value> Close(const Arguments& args) { static Handle<Value> Close(const Arguments& args) {
HandleScope scope; HandleScope scope;
@ -414,6 +433,11 @@ static Handle<Value> Connect(const Arguments& args) {
return Undefined(); return Undefined();
} }
#endif // __POSIX__
#ifdef __POSIX__
#define ADDRESS_TO_JS(info, address_storage) \ #define ADDRESS_TO_JS(info, address_storage) \
do { \ do { \
char ip[INET6_ADDRSTRLEN]; \ char ip[INET6_ADDRSTRLEN]; \
@ -445,6 +469,37 @@ do { \
} \ } \
} while (0) } while (0)
#else // __MINGW32__
#define ADDRESS_TO_JS(info, address_storage) \
do { \
char ip[INET6_ADDRSTRLEN]; \
int port; \
struct sockaddr_in *a4; \
struct sockaddr_in6 *a6; \
switch ((address_storage).ss_family) { \
case AF_INET6: \
a6 = (struct sockaddr_in6*)&(address_storage); \
inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
port = ntohs(a6->sin6_port); \
(info)->Set(address_symbol, String::New(ip)); \
(info)->Set(port_symbol, Integer::New(port)); \
break; \
case AF_INET: \
a4 = (struct sockaddr_in*)&(address_storage); \
inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
port = ntohs(a4->sin_port); \
(info)->Set(address_symbol, String::New(ip)); \
(info)->Set(port_symbol, Integer::New(port)); \
break; \
default: \
(info)->Set(address_symbol, String::Empty()); \
} \
} while (0)
#endif // __MINGW32__
#ifdef __POSIX__
static Handle<Value> GetSockName(const Arguments& args) { static Handle<Value> GetSockName(const Arguments& args) {
HandleScope scope; HandleScope scope;
@ -489,6 +544,8 @@ static Handle<Value> GetPeerName(const Arguments& args) {
return scope.Close(info); return scope.Close(info);
} }
#endif // __POSIX__
static Handle<Value> Listen(const Arguments& args) { static Handle<Value> Listen(const Arguments& args) {
HandleScope scope; HandleScope scope;
@ -496,7 +553,7 @@ static Handle<Value> Listen(const Arguments& args) {
FD_ARG(args[0]) FD_ARG(args[0])
int backlog = args[1]->IsInt32() ? args[1]->Int32Value() : 128; int backlog = args[1]->IsInt32() ? args[1]->Int32Value() : 128;
if (0 > listen(fd, backlog)) { if (0 > listen(_get_osfhandle(fd), backlog)) {
return ThrowException(ErrnoException(errno, "listen")); return ThrowException(ErrnoException(errno, "listen"));
} }
@ -522,12 +579,23 @@ static Handle<Value> Accept(const Arguments& args) {
struct sockaddr_storage address_storage; struct sockaddr_storage address_storage;
socklen_t len = sizeof(struct sockaddr_storage); socklen_t len = sizeof(struct sockaddr_storage);
#ifdef __POSIX__
int peer_fd = accept(fd, (struct sockaddr*) &address_storage, &len); int peer_fd = accept(fd, (struct sockaddr*) &address_storage, &len);
if (peer_fd < 0) { if (peer_fd < 0) {
if (errno == EAGAIN) return scope.Close(Null()); if (errno == EAGAIN) return scope.Close(Null());
return ThrowException(ErrnoException(errno, "accept")); return ThrowException(ErrnoException(errno, "accept"));
} }
#else // __MINGW32__
int peer_handle = accept(_get_osfhandle(fd), (struct sockaddr*) &address_storage, &len);
if (peer_handle == INVALID_SOCKET) {
if (WSAGetLastError() == WSAEWOULDBLOCK) return scope.Close(Null());
return ThrowException(ErrnoException(errno, "accept"));
}
int peer_fd = _open_osfhandle(peer_handle, 0);
#endif // __MINGW32__
if (!SetSockFlags(peer_fd)) { if (!SetSockFlags(peer_fd)) {
int fcntl_errno = errno; int fcntl_errno = errno;
@ -545,6 +613,8 @@ static Handle<Value> Accept(const Arguments& args) {
} }
#ifdef __POSIX__
static Handle<Value> SocketError(const Arguments& args) { static Handle<Value> SocketError(const Arguments& args) {
HandleScope scope; HandleScope scope;
@ -1352,10 +1422,9 @@ void InitNet(Handle<Object> target) {
recv_msg_template = recv_msg_template =
Persistent<FunctionTemplate>::New(FunctionTemplate::New(RecvMsg)); Persistent<FunctionTemplate>::New(FunctionTemplate::New(RecvMsg));
target->Set(String::NewSymbol("recvMsg"), recv_msg_template->GetFunction()); target->Set(String::NewSymbol("recvMsg"), recv_msg_template->GetFunction());
NODE_SET_METHOD(target, "socket", Socket);
#endif //__POSIX__ #endif //__POSIX__
NODE_SET_METHOD(target, "socket", Socket);
NODE_SET_METHOD(target, "close", Close); NODE_SET_METHOD(target, "close", Close);
#ifdef __POSIX__ #ifdef __POSIX__
@ -1364,9 +1433,13 @@ void InitNet(Handle<Object> target) {
NODE_SET_METHOD(target, "socketpair", SocketPair); NODE_SET_METHOD(target, "socketpair", SocketPair);
NODE_SET_METHOD(target, "connect", Connect); NODE_SET_METHOD(target, "connect", Connect);
#endif // __POSIX__
NODE_SET_METHOD(target, "bind", Bind); NODE_SET_METHOD(target, "bind", Bind);
NODE_SET_METHOD(target, "listen", Listen); NODE_SET_METHOD(target, "listen", Listen);
NODE_SET_METHOD(target, "accept", Accept); NODE_SET_METHOD(target, "accept", Accept);
#ifdef __POSIX__
NODE_SET_METHOD(target, "socketError", SocketError); NODE_SET_METHOD(target, "socketError", SocketError);
NODE_SET_METHOD(target, "toRead", ToRead); NODE_SET_METHOD(target, "toRead", ToRead);
NODE_SET_METHOD(target, "setNoDelay", SetNoDelay); NODE_SET_METHOD(target, "setNoDelay", SetNoDelay);

Loading…
Cancel
Save