diff options
Diffstat (limited to 'deps/uv/src/win')
-rw-r--r-- | deps/uv/src/win/core.c | 2 | ||||
-rw-r--r-- | deps/uv/src/win/error.c | 75 | ||||
-rw-r--r-- | deps/uv/src/win/fs.c | 8 | ||||
-rw-r--r-- | deps/uv/src/win/internal.h | 3 | ||||
-rw-r--r-- | deps/uv/src/win/tcp.c | 84 | ||||
-rw-r--r-- | deps/uv/src/win/timer.c | 21 | ||||
-rw-r--r-- | deps/uv/src/win/udp.c | 92 | ||||
-rw-r--r-- | deps/uv/src/win/winsock.c | 59 |
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"); } } |