From fa490f64971a38c98d74dc6b55b2d88dd1f6c463 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 31 Jan 2012 17:41:46 +0100 Subject: [PATCH] uv: upgrade to 3eb94e9 --- deps/uv/src/unix/pipe.c | 1 - deps/uv/src/unix/udp.c | 10 ++- deps/uv/src/win/fs.c | 2 +- deps/uv/src/win/udp.c | 139 +++++++++++++++++++++++++-------- deps/uv/test/test-fs.c | 3 + deps/uv/test/test-list.h | 2 + deps/uv/test/test-udp-multicast-join.c | 2 +- deps/uv/test/test-udp-options.c | 85 ++++++++++++++++++++ deps/uv/uv.gyp | 1 + deps/uv/vcbuild.bat | 14 +++- 10 files changed, 223 insertions(+), 36 deletions(-) create mode 100644 deps/uv/test/test-udp-options.c diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c index 5509136..f1be9e9 100644 --- a/deps/uv/src/unix/pipe.c +++ b/deps/uv/src/unix/pipe.c @@ -251,7 +251,6 @@ void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) { pipe = watcher->data; assert(pipe->type == UV_NAMED_PIPE); - assert(pipe->pipe_fname != NULL); sockfd = uv__accept(pipe->fd, (struct sockaddr *)&saddr, sizeof saddr); if (sockfd == -1) { diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 91f7d1a..349bfae 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -340,7 +340,15 @@ static int uv__bind(uv_udp_t* handle, goto out; } -#ifdef SO_REUSEPORT /* Apple's version of SO_REUSEADDR... */ + /* On the BSDs, SO_REUSEADDR lets you reuse an address that's in the TIME_WAIT + * state (i.e. was until recently tied to a socket) while SO_REUSEPORT lets + * multiple processes bind to the same address. Yes, it's something of a + * misnomer but then again, SO_REUSEADDR was already taken. + * + * None of the above applies to Linux: SO_REUSEADDR implies SO_REUSEPORT on + * Linux and hence it does not have SO_REUSEPORT at all. + */ +#ifdef SO_REUSEPORT yes = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof yes) == -1) { uv__set_sys_error(handle->loop, errno); diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 6948f7e..5248ac2 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -541,7 +541,7 @@ static int uv__is_root(const wchar_t* path) { size_t len = wcslen(path); /* Test for \ */ - if (len == 0 && IS_SLASH(path[0])) { + if (len == 1 && IS_SLASH(path[0])) { return 1; } diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 0a9990a..39221de 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -166,9 +166,9 @@ static int uv__bind(uv_udp_t* handle, struct sockaddr* addr, int addrsize, unsigned int flags) { - DWORD err; int r; SOCKET sock; + DWORD no = 0, yes = 1; if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) { /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ @@ -190,7 +190,6 @@ static int uv__bind(uv_udp_t* handle, } if (domain == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { - DWORD off = 0; /* On windows IPV6ONLY is on by default. */ /* If the user doesn't specify it libuv turns it off. */ @@ -200,14 +199,22 @@ static int uv__bind(uv_udp_t* handle, setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, - (const char*) &off, - sizeof off); + (char*) &no, + sizeof no); } - r = bind(handle->socket, addr, addrsize); + r = setsockopt(sock, + 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) { - err = WSAGetLastError(); uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } @@ -244,15 +251,6 @@ int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, } -int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, - const char* interface_addr, uv_membership membership) { - - /* not implemented yet */ - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; -} - - static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { uv_req_t* req; uv_buf_t buf; @@ -579,16 +577,50 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, } -int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; -} +int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, + const char* interface_addr, uv_membership membership) { + int optname; + struct ip_mreq mreq; + /* If the socket is unbound, bind to inaddr_any. */ + if (!(handle->flags & UV_HANDLE_BOUND) && + uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) { + return -1; + } -int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { - if (setsockopt(handle->socket, IPPROTO_IP, IP_MULTICAST_TTL, - (const char*)&ttl, sizeof ttl) == -1) { - uv__set_sys_error(handle->loop, WSAGetLastError()); + if (handle->flags & UV_HANDLE_IPV6) { + uv__set_artificial_error(handle->loop, UV_ENOSYS); + return -1; + } + + memset(&mreq, 0, sizeof mreq); + + if (interface_addr) { + mreq.imr_interface.s_addr = inet_addr(interface_addr); + } else { + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } + + mreq.imr_multiaddr.s_addr = inet_addr(multicast_addr); + + switch (membership) { + case UV_JOIN_GROUP: + optname = IP_ADD_MEMBERSHIP; + break; + case UV_LEAVE_GROUP: + optname = IP_DROP_MEMBERSHIP; + break; + default: + uv__set_artificial_error(handle->loop, UV_EFAULT); + return -1; + } + + if (setsockopt(handle->socket, + IPPROTO_IP, + optname, + (char*) &mreq, + sizeof mreq) == SOCKET_ERROR) { + uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } @@ -596,18 +628,63 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { } -int uv_udp_set_broadcast(uv_udp_t* handle, int on) { - if (setsockopt(handle->socket, SOL_SOCKET, SO_BROADCAST, (const char*)&on, - sizeof on) == -1) { - uv__set_sys_error(handle->loop, WSAGetLastError()); +int uv_udp_set_broadcast(uv_udp_t* handle, int value) { + BOOL optval = (BOOL) value; + + /* If the socket is unbound, bind to inaddr_any. */ + if (!(handle->flags & UV_HANDLE_BOUND) && + uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) { return -1; } + if (setsockopt(handle->socket, + SOL_SOCKET, + SO_BROADCAST, + (char*) &optval, + sizeof optval)) { + uv__set_sys_error(handle->loop, WSAGetLastError()); + return -1; + } return 0; } -int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; -} +#define SOCKOPT_SETTER(name, option4, option6) \ + int uv_udp_set_##name(uv_udp_t* handle, int value) { \ + DWORD optval = (DWORD) value; \ + \ + /* If the socket is unbound, bind to inaddr_any. */ \ + if (!(handle->flags & UV_HANDLE_BOUND) && \ + uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) { \ + return -1; \ + } \ + \ + if (!(handle->flags & UV_HANDLE_IPV6)) { \ + /* Set IPv4 socket option */ \ + if (setsockopt(handle->socket, \ + IPPROTO_IP, \ + option4, \ + (char*) &optval, \ + sizeof optval)) { \ + uv__set_sys_error(handle->loop, WSAGetLastError()); \ + return -1; \ + } \ + } else { \ + /* Set IPv6 socket option */ \ + if (setsockopt(handle->socket, \ + IPPROTO_IPV6, \ + option6, \ + (char*) &optval, \ + sizeof optval)) { \ + uv__set_sys_error(handle->loop, WSAGetLastError()); \ + return -1; \ + } \ + } \ + return 0; \ + } + +SOCKOPT_SETTER(multicast_loop, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP) +SOCKOPT_SETTER(multicast_ttl, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS) +SOCKOPT_SETTER(ttl, IP_TTL, IPV6_HOPLIMIT) + +#undef SOCKOPT_SETTER diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 1601ac4..b88636b 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -1293,6 +1293,9 @@ TEST_IMPL(fs_stat_root) { int r; uv_loop_t* loop = uv_default_loop(); + r = uv_fs_stat(loop, &stat_req, "\\", NULL); + ASSERT(r == 0); + r = uv_fs_stat(loop, &stat_req, "c:\\", NULL); ASSERT(r == 0); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index acc5cea..02fabcb 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -50,6 +50,7 @@ TEST_DECLARE (udp_multicast_join) TEST_DECLARE (udp_dgram_too_big) TEST_DECLARE (udp_dual_stack) TEST_DECLARE (udp_ipv6_only) +TEST_DECLARE (udp_options) TEST_DECLARE (pipe_bind_error_addrinuse) TEST_DECLARE (pipe_bind_error_addrnotavail) TEST_DECLARE (pipe_bind_error_inval) @@ -187,6 +188,7 @@ TASK_LIST_START TEST_ENTRY (udp_dgram_too_big) TEST_ENTRY (udp_dual_stack) TEST_ENTRY (udp_ipv6_only) + TEST_ENTRY (udp_options) TEST_ENTRY (udp_multicast_join) TEST_ENTRY (pipe_bind_error_addrinuse) diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index 159dba0..b32ef07 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/test/test-udp-multicast-join.c @@ -99,7 +99,7 @@ TEST_IMPL(udp_multicast_join) { int r; uv_udp_send_t req; uv_buf_t buf; - struct sockaddr_in addr = uv_ip4_addr("239.255.0.1", TEST_PORT); + struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT); r = uv_udp_init(uv_default_loop(), &server); ASSERT(r == 0); diff --git a/deps/uv/test/test-udp-options.c b/deps/uv/test/test-udp-options.c new file mode 100644 index 0000000..b474574 --- /dev/null +++ b/deps/uv/test/test-udp-options.c @@ -0,0 +1,85 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include +#include + + +TEST_IMPL(udp_options) { + uv_loop_t* loop; + uv_udp_t h; + int i, r; + + loop = uv_default_loop(); + + r = uv_udp_init(loop, &h); + ASSERT(r == 0); + + uv_unref(loop); /* don't keep the loop alive */ + + r = uv_udp_bind(&h, uv_ip4_addr("0.0.0.0", TEST_PORT), 0); + ASSERT(r == 0); + + r = uv_udp_set_broadcast(&h, 1); + r |= uv_udp_set_broadcast(&h, 1); + r |= uv_udp_set_broadcast(&h, 0); + r |= uv_udp_set_broadcast(&h, 0); + ASSERT(r == 0); + + /* values 0-255 should work */ + for (i = 0; i <= 255; i++) { + r = uv_udp_set_ttl(&h, i); + ASSERT(r == 0); + } + + /* anything >255 should fail */ + r = uv_udp_set_ttl(&h, 256); + ASSERT(r == -1); + ASSERT(uv_last_error(loop).code == UV_EINVAL); + /* don't test ttl=-1, it's a valid value on some platforms */ + + r = uv_udp_set_multicast_loop(&h, 1); + r |= uv_udp_set_multicast_loop(&h, 1); + r |= uv_udp_set_multicast_loop(&h, 0); + r |= uv_udp_set_multicast_loop(&h, 0); + ASSERT(r == 0); + + /* values 0-255 should work */ + for (i = 0; i <= 255; i++) { + r = uv_udp_set_multicast_ttl(&h, i); + ASSERT(r == 0); + } + + /* anything >255 should fail */ + r = uv_udp_set_multicast_ttl(&h, 256); + ASSERT(r == -1); + ASSERT(uv_last_error(loop).code == UV_EINVAL); + /* don't test ttl=-1, it's a valid value on some platforms */ + + r = uv_run(loop); + ASSERT(r == 0); + + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index dc0c0f3..1bc9ff9 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -317,6 +317,7 @@ 'test/test-tty.c', 'test/test-udp-dgram-too-big.c', 'test/test-udp-ipv6.c', + 'test/test-udp-options.c', 'test/test-udp-send-and-recv.c', 'test/test-udp-multicast-join.c', 'test/test-counters-init.c', diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat index bccefff..644f574 100644 --- a/deps/uv/vcbuild.bat +++ b/deps/uv/vcbuild.bat @@ -64,9 +64,21 @@ echo Project files generated. @rem Skip project generation if requested. if defined nobuild goto run -if not defined VCINSTALLDIR echo Build skipped. To build, this file needs to run from VS cmd prompt.& goto run +@rem If not running in the VS build env, try to start it. If that fails, bail +@rem out. +if defined VCINSTALLDIR goto msbuild-found +if not defined VS100COMNTOOLS goto msbuild-not-found +if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto msbuild-not-found +call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" +if not defined VCINSTALLDIR goto msbuild-not-found +goto msbuild-found + +:msbuild-not-found +echo Build skipped. To build, this file needs to run from VS cmd prompt. +goto run @rem Build the sln with msbuild. +:msbuild-found msbuild uv.sln /t:%target% /p:Configuration=%config% /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo if errorlevel 1 goto exit -- 2.7.4