From 13fb6f7fa17f3a915c25d594f4a1b638ad64f5fe Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 25 Nov 2010 05:05:35 +0100 Subject: [PATCH] Make Socket, Bind, Listen, Accept work for windows --- src/node_net.cc | 85 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/src/node_net.cc b/src/node_net.cc index bafae4be15..b803fd3248 100644 --- a/src/node_net.cc +++ b/src/node_net.cc @@ -13,6 +13,7 @@ #ifdef __MINGW32__ # include +# include #else // __POSIX__ # include @@ -162,6 +163,8 @@ static Handle SocketPair(const Arguments& args) { return scope.Close(a); } +#endif + // Creates a new non-blocking socket fd // t.socket("TCP"); @@ -219,7 +222,11 @@ static Handle Socket(const Arguments& args) { } } +#ifdef __POSIX__ 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")); @@ -250,10 +257,15 @@ static socklen_t addrlen; static inline Handle ParseAddressArgs(Handle first, Handle second, bool is_bind) { +#ifdef __POSIX__ // No unix sockets on windows static struct sockaddr_un un; +#endif static struct sockaddr_in in; static struct sockaddr_in6 in6; +#ifdef __POSIX__ // No unix sockets on windows + static struct sockaddr_un un; + if (first->IsString() && !second->IsString()) { // UNIX String::Utf8Value path(first->ToString()); @@ -270,6 +282,11 @@ static inline Handle ParseAddressArgs(Handle first, addrlen = sizeof(un) - sizeof(un.sun_path) + path.length() + 1; } else { +#else // __MINGW32__ + if (first->IsString() && !second->IsString()) { + return ErrnoException(errno, "ParseAddressArgs", "Unix sockets are not supported on windows"); + } else { +#endif // TCP or UDP memset(&in, 0, sizeof in); memset(&in6, 0, sizeof in6); @@ -321,9 +338,13 @@ static Handle Bind(const Arguments& args) { if (!error.IsEmpty()) return ThrowException(error); int flags = 1; +#ifdef __POSIX__ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); - 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) { return ThrowException(ErrnoException(errno, "bind")); @@ -332,8 +353,6 @@ static Handle Bind(const Arguments& args) { return Undefined(); } -#endif // __POSIX__ - static Handle Close(const Arguments& args) { HandleScope scope; @@ -414,6 +433,11 @@ static Handle Connect(const Arguments& args) { return Undefined(); } +#endif // __POSIX__ + + +#ifdef __POSIX__ + #define ADDRESS_TO_JS(info, address_storage) \ do { \ char ip[INET6_ADDRSTRLEN]; \ @@ -445,6 +469,37 @@ do { \ } \ } 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 GetSockName(const Arguments& args) { HandleScope scope; @@ -489,6 +544,8 @@ static Handle GetPeerName(const Arguments& args) { return scope.Close(info); } +#endif // __POSIX__ + static Handle Listen(const Arguments& args) { HandleScope scope; @@ -496,7 +553,7 @@ static Handle Listen(const Arguments& args) { FD_ARG(args[0]) 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")); } @@ -522,12 +579,23 @@ static Handle Accept(const Arguments& args) { struct sockaddr_storage address_storage; socklen_t len = sizeof(struct sockaddr_storage); +#ifdef __POSIX__ int peer_fd = accept(fd, (struct sockaddr*) &address_storage, &len); if (peer_fd < 0) { if (errno == EAGAIN) return scope.Close(Null()); 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)) { int fcntl_errno = errno; @@ -545,6 +613,8 @@ static Handle Accept(const Arguments& args) { } +#ifdef __POSIX__ + static Handle SocketError(const Arguments& args) { HandleScope scope; @@ -1352,10 +1422,9 @@ void InitNet(Handle target) { recv_msg_template = Persistent::New(FunctionTemplate::New(RecvMsg)); target->Set(String::NewSymbol("recvMsg"), recv_msg_template->GetFunction()); - - NODE_SET_METHOD(target, "socket", Socket); #endif //__POSIX__ + NODE_SET_METHOD(target, "socket", Socket); NODE_SET_METHOD(target, "close", Close); #ifdef __POSIX__ @@ -1364,9 +1433,13 @@ void InitNet(Handle target) { NODE_SET_METHOD(target, "socketpair", SocketPair); NODE_SET_METHOD(target, "connect", Connect); +#endif // __POSIX__ + NODE_SET_METHOD(target, "bind", Bind); NODE_SET_METHOD(target, "listen", Listen); NODE_SET_METHOD(target, "accept", Accept); + +#ifdef __POSIX__ NODE_SET_METHOD(target, "socketError", SocketError); NODE_SET_METHOD(target, "toRead", ToRead); NODE_SET_METHOD(target, "setNoDelay", SetNoDelay);