summaryrefslogtreecommitdiff
path: root/deps/uv/src/win
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src/win')
-rw-r--r--deps/uv/src/win/core.c2
-rw-r--r--deps/uv/src/win/error.c75
-rw-r--r--deps/uv/src/win/fs.c8
-rw-r--r--deps/uv/src/win/internal.h3
-rw-r--r--deps/uv/src/win/tcp.c84
-rw-r--r--deps/uv/src/win/timer.c21
-rw-r--r--deps/uv/src/win/udp.c92
-rw-r--r--deps/uv/src/win/winsock.c59
8 files changed, 195 insertions, 149 deletions
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 67558b4904..e56536a7fa 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -115,6 +115,8 @@ static void uv_loop_init(uv_loop_t* loop) {
loop->active_tcp_streams = 0;
loop->active_udp_streams = 0;
+ loop->timer_counter = 0;
+
loop->last_err = uv_ok_;
}
diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c
index ff79f9c814..40852cffcb 100644
--- a/deps/uv/src/win/error.c
+++ b/deps/uv/src/win/error.c
@@ -66,31 +66,6 @@ void uv_fatal_error(const int errorno, const char* syscall) {
uv_err_code uv_translate_sys_error(int sys_errno) {
switch (sys_errno) {
case ERROR_SUCCESS: return UV_OK;
- case ERROR_BEGINNING_OF_MEDIA: return UV_EIO;
- case ERROR_BUS_RESET: return UV_EIO;
- case ERROR_CRC: return UV_EIO;
- case ERROR_DEVICE_DOOR_OPEN: return UV_EIO;
- case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO;
- case ERROR_DISK_CORRUPT: return UV_EIO;
- case ERROR_EOM_OVERFLOW: return UV_EIO;
- case ERROR_FILEMARK_DETECTED: return UV_EIO;
- case ERROR_GEN_FAILURE: return UV_EIO;
- case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO;
- case ERROR_IO_DEVICE: return UV_EIO;
- case ERROR_NO_DATA_DETECTED: return UV_EIO;
- case ERROR_NO_SIGNAL_SENT: return UV_EIO;
- case ERROR_OPEN_FAILED: return UV_EIO;
- case ERROR_SETMARK_DETECTED: return UV_EIO;
- case ERROR_SIGNAL_REFUSED: return UV_EIO;
- case ERROR_DIRECTORY: return UV_ENOENT;
- case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
- case ERROR_INVALID_NAME: return UV_ENOENT;
- case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT;
- case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
- case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
- case WSANO_DATA: return UV_ENOENT;
- case ERROR_ACCESS_DENIED: return UV_EPERM;
- case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM;
case ERROR_NOACCESS: return UV_EACCES;
case WSAEACCES: return UV_EACCES;
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
@@ -99,8 +74,14 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case WSAEAFNOSUPPORT: return UV_EAFNOSUPPORT;
case WSAEWOULDBLOCK: return UV_EAGAIN;
case WSAEALREADY: return UV_EALREADY;
+ case ERROR_INVALID_FLAGS: return UV_EBADF;
+ case ERROR_INVALID_HANDLE: return UV_EBADF;
case ERROR_LOCK_VIOLATION: return UV_EBUSY;
+ case ERROR_PIPE_BUSY: return UV_EBUSY;
case ERROR_SHARING_VIOLATION: return UV_EBUSY;
+ case ERROR_OPERATION_ABORTED: return UV_ECANCELED;
+ case WSAEINTR: return UV_ECANCELED;
+ case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET;
case ERROR_CONNECTION_ABORTED: return UV_ECONNABORTED;
case WSAECONNABORTED: return UV_ECONNABORTED;
case ERROR_CONNECTION_REFUSED: return UV_ECONNREFUSED;
@@ -113,11 +94,29 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case WSAEFAULT: return UV_EFAULT;
case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH;
case WSAEHOSTUNREACH: return UV_EHOSTUNREACH;
- case ERROR_OPERATION_ABORTED: return UV_ECANCELED;
- case WSAEINTR: return UV_ECANCELED;
+ case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL;
case ERROR_INVALID_DATA: return UV_EINVAL;
+ case ERROR_INVALID_PARAMETER: return UV_EINVAL;
case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL;
case WSAEINVAL: return UV_EINVAL;
+ case WSAEPFNOSUPPORT: return UV_EINVAL;
+ case WSAESOCKTNOSUPPORT: return UV_EINVAL;
+ case ERROR_BEGINNING_OF_MEDIA: return UV_EIO;
+ case ERROR_BUS_RESET: return UV_EIO;
+ case ERROR_CRC: return UV_EIO;
+ case ERROR_DEVICE_DOOR_OPEN: return UV_EIO;
+ case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO;
+ case ERROR_DISK_CORRUPT: return UV_EIO;
+ case ERROR_EOM_OVERFLOW: return UV_EIO;
+ case ERROR_FILEMARK_DETECTED: return UV_EIO;
+ case ERROR_GEN_FAILURE: return UV_EIO;
+ case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO;
+ case ERROR_IO_DEVICE: return UV_EIO;
+ case ERROR_NO_DATA_DETECTED: return UV_EIO;
+ case ERROR_NO_SIGNAL_SENT: return UV_EIO;
+ case ERROR_OPEN_FAILED: return UV_EIO;
+ case ERROR_SETMARK_DETECTED: return UV_EIO;
+ case ERROR_SIGNAL_REFUSED: return UV_EIO;
case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP;
case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE;
case WSAEMFILE: return UV_EMFILE;
@@ -126,6 +125,14 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH;
case WSAENETUNREACH: return UV_ENETUNREACH;
case WSAENOBUFS: return UV_ENOBUFS;
+ case ERROR_DIRECTORY: return UV_ENOENT;
+ case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
+ case ERROR_INVALID_NAME: return UV_ENOENT;
+ case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT;
+ case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
+ case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
+ case WSAHOST_NOT_FOUND: return UV_ENOENT;
+ case WSANO_DATA: return UV_ENOENT;
case ERROR_NOT_ENOUGH_MEMORY: return UV_ENOMEM;
case ERROR_OUTOFMEMORY: return UV_ENOMEM;
case ERROR_CANNOT_MAKE: return UV_ENOSPC;
@@ -133,26 +140,22 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case ERROR_EA_TABLE_FULL: return UV_ENOSPC;
case ERROR_END_OF_MEDIA: return UV_ENOSPC;
case ERROR_HANDLE_DISK_FULL: return UV_ENOSPC;
- case ERROR_WRITE_PROTECT: return UV_EROFS;
case ERROR_NOT_CONNECTED: return UV_ENOTCONN;
case WSAENOTCONN: return UV_ENOTCONN;
case ERROR_DIR_NOT_EMPTY: return UV_ENOTEMPTY;
+ case WSAENOTSOCK: return UV_ENOTSOCK;
case ERROR_NOT_SUPPORTED: return UV_ENOTSUP;
- case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL;
- case ERROR_INVALID_FLAGS: return UV_EBADF;
- case ERROR_INVALID_HANDLE: return UV_EBADF;
- case ERROR_INVALID_PARAMETER: return UV_EINVAL;
- case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET;
case ERROR_BROKEN_PIPE: return UV_EOF;
+ case ERROR_ACCESS_DENIED: return UV_EPERM;
+ case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM;
case ERROR_BAD_PIPE: return UV_EPIPE;
case ERROR_NO_DATA: return UV_EPIPE;
case ERROR_PIPE_NOT_CONNECTED: return UV_EPIPE;
case WSAESHUTDOWN: return UV_EPIPE;
- case ERROR_PIPE_BUSY: return UV_EBUSY;
+ case WSAEPROTONOSUPPORT: return UV_EPROTONOSUPPORT;
+ case ERROR_WRITE_PROTECT: return UV_EROFS;
case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT;
case WSAETIMEDOUT: return UV_ETIMEDOUT;
- case WSAHOST_NOT_FOUND: return UV_ENOENT;
- case WSAENOTSOCK: return UV_ENOTSOCK;
case ERROR_NOT_SAME_DEVICE: return UV_EXDEV;
default: return UV_UNKNOWN;
}
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 9b920c817a..60e67a41d5 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -889,7 +889,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
return;
}
- if (fs__stat_handle(handle, &req->stat) != 0) {
+ if (fs__stat_handle(handle, &req->statbuf) != 0) {
DWORD error = GetLastError();
if (do_lstat && error == ERROR_SYMLINK_NOT_SUPPORTED) {
/* We opened a reparse point but it was not a symlink. Try again. */
@@ -904,7 +904,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
return;
}
- req->ptr = &req->stat;
+ req->ptr = &req->statbuf;
req->result = 0;
CloseHandle(handle);
}
@@ -935,12 +935,12 @@ static void fs__fstat(uv_fs_t* req) {
return;
}
- if (fs__stat_handle(handle, &req->stat) != 0) {
+ if (fs__stat_handle(handle, &req->statbuf) != 0) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
- req->ptr = &req->stat;
+ req->ptr = &req->statbuf;
req->result = 0;
}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index f0d0d7a55a..9920f704ab 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -335,9 +335,6 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
OVERLAPPED* overlapped);
-/* Whether ipv6 is supported */
-extern int uv_allow_ipv6;
-
/* Whether there are any non-IFS LSPs stacked on TCP */
extern int uv_tcp_non_ifs_lsp_ipv4;
extern int uv_tcp_non_ifs_lsp_ipv6;
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index ff7b27b805..7158216131 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -81,7 +81,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
- SOCKET socket, int imported) {
+ SOCKET socket, int family, int imported) {
DWORD yes = 1;
int non_ifs_lsp;
@@ -107,8 +107,11 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
}
}
- non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
- uv_tcp_non_ifs_lsp_ipv4;
+ if (family == AF_INET6) {
+ non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6;
+ } else {
+ non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
+ }
if (pSetFileCompletionNotificationModes && !non_ifs_lsp) {
if (pSetFileCompletionNotificationModes((HANDLE) socket,
@@ -134,6 +137,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
handle->socket = socket;
+ if (family == AF_INET6) {
+ handle->flags |= UV_HANDLE_IPV6;
+ } else {
+ assert(!(handle->flags & UV_HANDLE_IPV6));
+ }
+
return 0;
}
@@ -230,14 +239,14 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
static int uv__bind(uv_tcp_t* handle,
- int domain,
+ int family,
struct sockaddr* addr,
int addrsize) {
DWORD err;
int r;
if (handle->socket == INVALID_SOCKET) {
- SOCKET sock = socket(domain, SOCK_STREAM, 0);
+ SOCKET sock = socket(family, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
@@ -250,7 +259,7 @@ static int uv__bind(uv_tcp_t* handle,
return -1;
}
- if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) {
+ if (uv_tcp_set_socket(handle->loop, handle, sock, family, 0) < 0) {
closesocket(sock);
return -1;
}
@@ -285,17 +294,10 @@ int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
- if (uv_allow_ipv6) {
- handle->flags |= UV_HANDLE_IPV6;
- return uv__bind(handle,
- AF_INET6,
- (struct sockaddr*)&addr,
- sizeof(struct sockaddr_in6));
-
- } else {
- uv__set_sys_error(handle->loop, WSAEAFNOSUPPORT);
- return -1;
- }
+ return uv__bind(handle,
+ AF_INET6,
+ (struct sockaddr*)&addr,
+ sizeof(struct sockaddr_in6));
}
@@ -584,6 +586,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
uv_loop_t* loop = server->loop;
int rv = 0;
+ int family;
uv_tcp_accept_t* req = server->pending_accepts;
@@ -598,7 +601,17 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
return -1;
}
- if (uv_tcp_set_socket(client->loop, client, req->accept_socket, 0) == -1) {
+ if (server->flags & UV_HANDLE_IPV6) {
+ family = AF_INET6;
+ } else {
+ family = AF_INET;
+ }
+
+ if (uv_tcp_set_socket(client->loop,
+ client,
+ req->accept_socket,
+ family,
+ 0) < 0) {
closesocket(req->accept_socket);
rv = -1;
} else {
@@ -733,11 +746,6 @@ int uv__tcp_connect6(uv_connect_t* req,
BOOL success;
DWORD bytes;
- if (!uv_allow_ipv6) {
- uv__set_sys_error(loop, WSAEAFNOSUPPORT);
- return -1;
- }
-
if (handle->flags & UV_HANDLE_BIND_ERROR) {
uv__set_sys_error(loop, handle->bind_error);
return -1;
@@ -1148,7 +1156,11 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
return -1;
}
- if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) {
+ if (uv_tcp_set_socket(tcp->loop,
+ tcp,
+ socket,
+ socket_protocol_info->iAddressFamily,
+ 1) < 0) {
closesocket(socket);
return -1;
}
@@ -1161,10 +1173,6 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
tcp->flags |= UV_HANDLE_BOUND;
tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
- if (socket_protocol_info->iAddressFamily == AF_INET6) {
- tcp->flags |= UV_HANDLE_IPV6;
- }
-
tcp->loop->active_tcp_streams++;
return 0;
}
@@ -1381,13 +1389,31 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
+ WSAPROTOCOL_INFOW protocol_info;
+ int opt_len;
+
+ /* Detect the address family of the socket. */
+ opt_len = (int) sizeof protocol_info;
+ if (getsockopt(sock,
+ SOL_SOCKET,
+ SO_PROTOCOL_INFOW,
+ (char*) &protocol_info,
+ &opt_len) == SOCKET_ERROR) {
+ uv__set_sys_error(handle->loop, GetLastError());
+ return -1;
+ }
+
/* Make the socket non-inheritable */
if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
uv__set_sys_error(handle->loop, GetLastError());
return -1;
}
- if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) {
+ if (uv_tcp_set_socket(handle->loop,
+ handle,
+ sock,
+ protocol_info.iAddressFamily,
+ 1) < 0) {
return -1;
}
diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c
index 370f2b6dc8..0c055da941 100644
--- a/deps/uv/src/win/timer.c
+++ b/deps/uv/src/win/timer.c
@@ -45,7 +45,7 @@ void uv_update_time(uv_loop_t* loop) {
}
-int64_t uv_now(uv_loop_t* loop) {
+uint64_t uv_now(uv_loop_t* loop) {
return loop->time;
}
@@ -55,9 +55,13 @@ static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
return -1;
if (a->due > b->due)
return 1;
- if ((intptr_t)a < (intptr_t)b)
+ /*
+ * compare start_id when both has the same due. start_id is
+ * allocated with loop->timer_counter in uv_timer_start().
+ */
+ if (a->start_id < b->start_id)
return -1;
- if ((intptr_t)a > (intptr_t)b)
+ if (a->start_id > b->start_id)
return 1;
return 0;
}
@@ -83,8 +87,8 @@ void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
}
-int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout,
- int64_t repeat) {
+int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
+ uint64_t repeat) {
uv_loop_t* loop = handle->loop;
uv_timer_t* old;
@@ -98,6 +102,9 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout,
handle->flags |= UV_HANDLE_ACTIVE;
uv__handle_start(handle);
+ /* start_id is the second index to be compared in uv__timer_cmp() */
+ handle->start_id = handle->loop->timer_counter++;
+
old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle);
assert(old == NULL);
@@ -150,13 +157,13 @@ int uv_timer_again(uv_timer_t* handle) {
}
-void uv_timer_set_repeat(uv_timer_t* handle, int64_t repeat) {
+void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
assert(handle->type == UV_TIMER);
handle->repeat = repeat;
}
-int64_t uv_timer_get_repeat(uv_timer_t* handle) {
+uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
assert(handle->type == UV_TIMER);
return handle->repeat;
}
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 6d2cde30c6..23410528f5 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -56,14 +56,24 @@ int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
}
-static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle,
- SOCKET socket) {
+static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
+ int family) {
DWORD yes = 1;
WSAPROTOCOL_INFOW info;
int opt_len;
assert(handle->socket == INVALID_SOCKET);
+ /* Set SO_REUSEADDR on the socket. */
+ if (setsockopt(socket,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (char*) &yes,
+ sizeof yes) == SOCKET_ERROR) {
+ uv__set_sys_error(loop, WSAGetLastError());
+ return -1;
+ }
+
/* Set the socket to nonblocking mode */
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
uv__set_sys_error(loop, WSAGetLastError());
@@ -93,7 +103,7 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle,
/* if the user is using the default UDP driver (AFD) and has no other */
/* LSPs stacked on top. Here we check whether that is the case. */
opt_len = (int) sizeof info;
- if (!getsockopt(socket,
+ if (getsockopt(socket,
SOL_SOCKET,
SO_PROTOCOL_INFOW,
(char*) &info,
@@ -118,6 +128,12 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle,
handle->socket = socket;
+ if (family == AF_INET6) {
+ handle->flags |= UV_HANDLE_IPV6;
+ } else {
+ assert(!(handle->flags & UV_HANDLE_IPV6));
+ }
+
return 0;
}
@@ -161,33 +177,36 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
static int uv__bind(uv_udp_t* handle,
- int domain,
+ int family,
struct sockaddr* addr,
int addrsize,
unsigned int flags) {
int r;
DWORD no = 0, yes = 1;
- if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) {
+ if ((flags & UV_UDP_IPV6ONLY) && family != AF_INET6) {
/* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
uv__set_artificial_error(handle->loop, UV_EINVAL);
return -1;
}
if (handle->socket == INVALID_SOCKET) {
- SOCKET sock = socket(domain, SOCK_DGRAM, 0);
+ SOCKET sock = socket(family, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
}
- if (uv_udp_set_socket(handle->loop, handle, sock) == -1) {
+ if (uv_udp_set_socket(handle->loop, handle, sock, family) < 0) {
closesocket(sock);
return -1;
}
+
+ if (family == AF_INET6)
+ handle->flags |= UV_HANDLE_IPV6;
}
- if (domain == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
+ if (family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
/* On windows IPV6ONLY is on by default. */
/* If the user doesn't specify it libuv turns it off. */
@@ -201,16 +220,6 @@ static int uv__bind(uv_udp_t* handle,
sizeof no);
}
- r = setsockopt(handle->socket,
- SOL_SOCKET,
- SO_REUSEADDR,
- (char*) &yes,
- sizeof yes);
- if (r == SOCKET_ERROR) {
- uv__set_sys_error(handle->loop, WSAGetLastError());
- return -1;
- }
-
r = bind(handle->socket, addr, addrsize);
if (r == SOCKET_ERROR) {
uv__set_sys_error(handle->loop, WSAGetLastError());
@@ -235,17 +244,11 @@ int uv__udp_bind(uv_udp_t* handle, struct sockaddr_in addr,
int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr,
unsigned int flags) {
- if (uv_allow_ipv6) {
- handle->flags |= UV_HANDLE_IPV6;
- return uv__bind(handle,
- AF_INET6,
- (struct sockaddr*) &addr,
- sizeof(struct sockaddr_in6),
- flags);
- } else {
- uv__set_sys_error(handle->loop, WSAEAFNOSUPPORT);
- return -1;
- }
+ return uv__bind(handle,
+ AF_INET6,
+ (struct sockaddr*) &addr,
+ sizeof(struct sockaddr_in6),
+ flags);
}
@@ -641,10 +644,10 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
}
if (setsockopt(handle->socket,
- SOL_SOCKET,
- SO_BROADCAST,
- (char*) &optval,
- sizeof optval)) {
+ SOL_SOCKET,
+ SO_BROADCAST,
+ (char*) &optval,
+ sizeof optval)) {
uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
}
@@ -653,20 +656,25 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
- int r;
+ WSAPROTOCOL_INFOW protocol_info;
+ int opt_len;
DWORD yes = 1;
- if (uv_udp_set_socket(handle->loop, handle, sock) == -1) {
+ /* Detect the address family of the socket. */
+ opt_len = (int) sizeof protocol_info;
+ if (getsockopt(sock,
+ SOL_SOCKET,
+ SO_PROTOCOL_INFOW,
+ (char*) &protocol_info,
+ &opt_len) == SOCKET_ERROR) {
+ uv__set_sys_error(handle->loop, GetLastError());
return -1;
}
- r = setsockopt(handle->socket,
- SOL_SOCKET,
- SO_REUSEADDR,
- (char*) &yes,
- sizeof yes);
- if (r == SOCKET_ERROR) {
- uv__set_sys_error(handle->loop, WSAGetLastError());
+ if (uv_udp_set_socket(handle->loop,
+ handle,
+ sock,
+ protocol_info.iAddressFamily) < 0) {
return -1;
}
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index 2c3e49a103..47395bb89d 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -25,9 +25,6 @@
#include "internal.h"
-/* Whether ipv6 is supported */
-int uv_allow_ipv6;
-
/* Whether there are any non-IFS LSPs stacked on TCP */
int uv_tcp_non_ifs_lsp_ipv4;
int uv_tcp_non_ifs_lsp_ipv6;
@@ -75,6 +72,12 @@ BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) {
}
+static int error_means_no_support(DWORD error) {
+ return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT ||
+ error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT;
+}
+
+
void uv_winsock_init() {
const GUID wsaid_connectex = WSAID_CONNECTEX;
const GUID wsaid_acceptex = WSAID_ACCEPTEX;
@@ -100,48 +103,48 @@ void uv_winsock_init() {
/* Detect non-IFS LSPs */
dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
- if (dummy == INVALID_SOCKET) {
- uv_fatal_error(WSAGetLastError(), "socket");
- }
- opt_len = (int) sizeof protocol_info;
- if (!getsockopt(dummy,
- SOL_SOCKET,
- SO_PROTOCOL_INFOW,
- (char*) &protocol_info,
- &opt_len) == SOCKET_ERROR) {
- uv_fatal_error(WSAGetLastError(), "socket");
- }
+ if (dummy != INVALID_SOCKET) {
+ opt_len = (int) sizeof protocol_info;
+ if (!getsockopt(dummy,
+ SOL_SOCKET,
+ SO_PROTOCOL_INFOW,
+ (char*) &protocol_info,
+ &opt_len) == SOCKET_ERROR)
+ uv_fatal_error(WSAGetLastError(), "getsockopt");
- if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) {
- uv_tcp_non_ifs_lsp_ipv4 = 1;
- }
+ if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES))
+ uv_tcp_non_ifs_lsp_ipv4 = 1;
+
+ if (closesocket(dummy) == SOCKET_ERROR)
+ uv_fatal_error(WSAGetLastError(), "closesocket");
- if (closesocket(dummy) == SOCKET_ERROR) {
- uv_fatal_error(WSAGetLastError(), "closesocket");
+ } else if (!error_means_no_support(WSAGetLastError())) {
+ /* Any error other than "socket type not supported" is fatal. */
+ uv_fatal_error(WSAGetLastError(), "socket");
}
/* Detect IPV6 support and non-IFS LSPs */
dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
- if (dummy != INVALID_SOCKET) {
- uv_allow_ipv6 = TRUE;
+ if (dummy != INVALID_SOCKET) {
opt_len = (int) sizeof protocol_info;
if (!getsockopt(dummy,
SOL_SOCKET,
SO_PROTOCOL_INFOW,
(char*) &protocol_info,
- &opt_len) == SOCKET_ERROR) {
- uv_fatal_error(WSAGetLastError(), "socket");
- }
+ &opt_len) == SOCKET_ERROR)
+ uv_fatal_error(WSAGetLastError(), "getsockopt");
- if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) {
+ if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES))
uv_tcp_non_ifs_lsp_ipv6 = 1;
- }
- if (closesocket(dummy) == SOCKET_ERROR) {
+ if (closesocket(dummy) == SOCKET_ERROR)
uv_fatal_error(WSAGetLastError(), "closesocket");
- }
+
+ } else if (!error_means_no_support(WSAGetLastError())) {
+ /* Any error other than "socket type not supported" is fatal. */
+ uv_fatal_error(WSAGetLastError(), "socket");
}
}