diff options
author | Fedor Indutny <fedor@indutny.com> | 2014-04-07 16:36:51 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-04-07 16:36:51 +0400 |
commit | 962f96d3416ee00c78e729bc1c1b05e02d0c1ef2 (patch) | |
tree | 54b04b551eaa04e280f416b106c0de5c29b39bda | |
parent | 95dbb6bf647d90947c0c738533dadf391559be98 (diff) | |
download | node-new-962f96d3416ee00c78e729bc1c1b05e02d0c1ef2.tar.gz |
deps: update libuv to v0.11.23
82 files changed, 1807 insertions, 310 deletions
diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 3b0e5f0925..7d627a3da3 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -6,10 +6,12 @@ Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org> Brian White <mscdex@mscdex.net> Brian White <mscdex@mscdex.net> <mscdex@gmail.com> Christoph Iserlohn <christoph.iserlohn@innoq.com> +Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com> Frank Denis <github@pureftpd.org> Isaac Z. Schlueter <i@izs.me> -Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu> +Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com> Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu> +Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu> Maciej MaÅ‚ecki <maciej.malecki@notimplemented.org> <me@mmalecki.com> Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com> Rasmus Pedersen <ruysch@outlook.com> <zerhacken@yahoo.com> diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 7836488f6b..d96ec14cda 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -125,9 +125,39 @@ Oleg Efimov <o.efimov@corp.badoo.com> Lars Gierth <larsg@systemli.org> rcp <zerhacken@yahoo.com> Alexis Campailla <alexis@janeasystems.com> +Justin Venus <justin.venus@gmail.com> +Ben Kelly <ben@wanderview.com> +Kristian Evensen <kristian.evensen@gmail.com> +Sean Silva <chisophugis@gmail.com> +Linus MÃ¥rtensson <linus.martensson@sonymobile.com> +Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com> +Brent Cook <brent@boundary.com> +Brian Kaisner <bkize1@gmail.com> +Reini Urban <rurban@cpanel.net> +Maks Naumov <maksqwe1@ukr.net> +Sean Farrell <sean.farrell@rioki.org> +Christoph Iserlohn <christoph.iserlohn@innoq.com> +Steven Kabbes <stevenkabbes@gmail.com> +Tenor Biel <tenorbiel@gmail.com> +Andrej Manduch <AManduch@gmail.com> +Joshua Neuheisel <joshua@neuheisel.us> +Yorkie <yorkiefixer@gmail.com> +Sam Roberts <vieuxtech@gmail.com> +River Tarnell <river@loreley.flyingparchment.org.uk> +Nathan Sweet <nathanjsweet@gmail.com> +Dylan Cali <calid1984@gmail.com> +Austin Foxley <austinf@cetoncorp.com> +Geoffry Song <goffrie@gmail.com> +Benjamin Saunders <ben.e.saunders@gmail.com> +Rasmus Pedersen <ruysch@outlook.com> +William Light <wrl@illest.net> +Oleg Efimov <o.efimov@corp.badoo.com> +Lars Gierth <larsg@systemli.org> StarWing <weasley.wx@gmail.com> thierry-FreeBSD <thierry@FreeBSD.org> Isaiah Norton <isaiah.norton@gmail.com> Raul Martins <raulms.martins@gmail.com> David Capello <davidcapello@gmail.com> Paul Tan <pyokagan@gmail.com> +Javier Hernández <jhernandez@emergya.com> +Tonis Tiigi <tonistiigi@gmail.com> diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 3536abb57c..ea9a936d67 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,64 @@ -2014.03.11, Version 0.11.22 (Unstable) +2014.04.07, Version 0.11.23 (Unstable) + +Changes since version 0.11.22: + +* fs: avoid using readv/writev where possible (Fedor Indutny) + +* mingw: fix build with autotools (Saúl Ibarra Corretgé) + +* bsd: support IPv6 qualified link-local addresses (Saúl Ibarra Corretgé) + +* unix: add UV_HANDLE_IPV6 flag to tcp and udp handles (Saúl Ibarra Corretgé) + +* unix, windows: do not set SO_REUSEADDR by default on udp (Saúl Ibarra + Corretgé) + +* windows: fix check in uv_tty_endgame() (Maks Naumov) + +* unix, windows: add IPv6 support for uv_udp_multicast_interface (Saúl Ibarra + Corretgé) + +* unix: fallback to blocking writes if reopening a tty fails (Saúl Ibarra + Corretgé) + +* unix: fix handling uv__open_cloexec failure (Saúl Ibarra Corretgé) + +* unix, windows: add IPv6 support to uv_udp_set_membership (Saúl Ibarra + Corretgé) + +* unix, windows: removed unused status parameter (Saúl Ibarra Corretgé) + +* android: add support of ifaddrs in android (Javier Hernández) + +* build: fix SunOS and AIX build with autotools (Saúl Ibarra Corretgé) + +* build: freebsd link with libelf if dtrace enabled (Saúl Ibarra Corretgé) + +* stream: do not leak `alloc_cb` buffers on error (Fedor Indutny) + +* unix: fix setting written size on uv_wd (Saúl Ibarra Corretgé) + + +2014.04.07, Version 0.10.26 (Stable), d864907611c25ec986c5e77d4d6d6dee88f26926 + +Changes since version 0.10.25: + +* process: don't close stdio fds during spawn (Tonis Tiigi) + +* build, windows: do not fail on Windows SDK Prompt (Marc Schlaich) + +* build, windows: fix x64 configuration issue (Marc Schlaich) + +* win: fix buffer leak on error in pipe.c (Fedor Indutny) + +* kqueue: invalidate fd in uv_fs_event_t (Fedor Indutny) + +* linux: always deregister closing fds from epoll (Geoffry Song) + +* error: add ENXIO for O_NONBLOCK FIFO open() (Fedor Indutny) + + +2014.03.11, Version 0.11.22 (Unstable), cd0c19b1d3c56acf0ade7687006e12e75fbda36d Changes since version 0.11.21: diff --git a/deps/uv/LICENSE b/deps/uv/LICENSE index 8db13acf2c..4d411670e3 100644 --- a/deps/uv/LICENSE +++ b/deps/uv/LICENSE @@ -40,3 +40,7 @@ The externally maintained libraries used by libuv are: - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB. Three clause BSD license. + + - android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design + Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement + n° 289016). Three clause BSD license. diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 3aa40c6111..41833c9822 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -106,6 +106,7 @@ endif # WINNT TESTS = test/run-tests check_PROGRAMS = test/run-tests +test_run_tests_CFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ test/echo-server.c \ @@ -199,10 +200,13 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-timer-from-check.c \ test/test-timer.c \ test/test-tty.c \ + test/test-udp-bind.c \ test/test-udp-dgram-too-big.c \ test/test-udp-ipv6.c \ test/test-udp-multicast-interface.c \ + test/test-udp-multicast-interface6.c \ test/test-udp-multicast-join.c \ + test/test-udp-multicast-join6.c \ test/test-udp-multicast-ttl.c \ test/test-udp-open.c \ test/test-udp-options.c \ @@ -219,6 +223,13 @@ test_run_tests_SOURCES += test/runner-unix.c \ test/runner-unix.h endif +if AIX +test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 +endif + +if SUNOS +test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 +endif if AIX @@ -226,6 +237,11 @@ libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 libuv_la_SOURCES += src/unix/aix.c endif +if ANDROID +include_HEADERS += include/android-ifaddrs.h +libuv_la_SOURCES += src/unix/android-ifaddrs.c +endif + if DARWIN include_HEADERS += include/uv-darwin.h libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 @@ -269,6 +285,9 @@ endif if HAVE_DTRACE BUILT_SOURCES = include/uv-dtrace.h CLEANFILES += include/uv-dtrace.h +if FREEBSD +libuv_la_LDFLAGS += -lelf +endif endif if DTRACE_NEEDS_OBJECTS diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 8c928a5e2f..127e0b9712 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [0.11.22], [https://github.com/joyent/libuv/issues]) +AC_INIT([libuv], [0.11.23], [https://github.com/joyent/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS) @@ -37,14 +37,15 @@ AC_CHECK_LIB([rt], [clock_gettime]) AC_CHECK_LIB([sendfile], [sendfile]) AC_CHECK_LIB([socket], [socket]) AC_SYS_LARGEFILE -AM_CONDITIONAL([AIX], [AS_CASE([$host_os], [aix*], [true], [false])]) -AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os], [darwin*], [true], [false])]) -AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os], [freebsd*], [true], [false])]) -AM_CONDITIONAL([LINUX], [AS_CASE([$host_os], [linux*], [true], [false])]) -AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os], [netbsd*], [true], [false])]) -AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os], [openbsd*], [true], [false])]) -AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os], [solaris*], [true], [false])]) -AM_CONDITIONAL([WINNT], [AS_CASE([$host_os], [mingw*], [true], [false])]) +AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) +AM_CONDITIONAL([ANDROID],[AS_CASE([$host_os],[linux-android*],[true], [false])]) +AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) +AM_CONDITIONAL([FREEBSD],[AS_CASE([$host_os],[freebsd*], [true], [false])]) +AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) +AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) +AM_CONDITIONAL([OPENBSD],[AS_CASE([$host_os],[openbsd*], [true], [false])]) +AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) +AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) PANDORA_ENABLE_DTRACE AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"]) diff --git a/deps/uv/include/android-ifaddrs.h b/deps/uv/include/android-ifaddrs.h new file mode 100644 index 0000000000..9cd19fec12 --- /dev/null +++ b/deps/uv/include/android-ifaddrs.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1995, 1999 + * Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp + */ + +#ifndef _IFADDRS_H_ +#define _IFADDRS_H_ + +struct ifaddrs { + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + struct sockaddr *ifa_dstaddr; + void *ifa_data; +}; + +/* + * This may have been defined in <net/if.h>. Note that if <net/if.h> is + * to be included it must be included before this header file. + */ +#ifndef ifa_broadaddr +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ +#endif + +#include <sys/cdefs.h> + +__BEGIN_DECLS +extern int getifaddrs(struct ifaddrs **ifap); +extern void freeifaddrs(struct ifaddrs *ifa); +__END_DECLS + +#endif diff --git a/deps/uv/include/uv-bsd.h b/deps/uv/include/uv-bsd.h index 2d72b3d771..3458d5d7ef 100644 --- a/deps/uv/include/uv-bsd.h +++ b/deps/uv/include/uv-bsd.h @@ -31,4 +31,6 @@ #define UV_HAVE_KQUEUE 1 +#define UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS + #endif /* UV_BSD_H */ diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h index 3b6834f1cd..0981834cd6 100644 --- a/deps/uv/include/uv-errno.h +++ b/deps/uv/include/uv-errno.h @@ -400,4 +400,10 @@ # define UV__ENXIO (-4033) #endif +#if defined(EMLINK) && !defined(_WIN32) +# define UV__EMLINK (-EMLINK) +#else +# define UV__EMLINK (-4032) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index e4ebf24fad..5724ee0887 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 22 +#define UV_VERSION_PATCH 23 #define UV_VERSION_IS_RELEASE 1 #endif /* UV_VERSION_H */ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 7886e623a7..7eb4d5fd2c 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -138,6 +138,7 @@ extern "C" { XX(UNKNOWN, "unknown error") \ XX(EOF, "end of file") \ XX(ENXIO, "no such device or address") \ + XX(EMLINK, "too many links") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -405,12 +406,11 @@ typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status); typedef void (*uv_connection_cb)(uv_stream_t* server, int status); typedef void (*uv_close_cb)(uv_handle_t* handle); typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events); -typedef void (*uv_timer_cb)(uv_timer_t* handle, int status); -/* TODO: do these really need a status argument? */ -typedef void (*uv_async_cb)(uv_async_t* handle, int status); -typedef void (*uv_prepare_cb)(uv_prepare_t* handle, int status); -typedef void (*uv_check_cb)(uv_check_t* handle, int status); -typedef void (*uv_idle_cb)(uv_idle_t* handle, int status); +typedef void (*uv_timer_cb)(uv_timer_t* handle); +typedef void (*uv_async_cb)(uv_async_t* handle); +typedef void (*uv_prepare_cb)(uv_prepare_t* handle); +typedef void (*uv_check_cb)(uv_check_t* handle); +typedef void (*uv_idle_cb)(uv_idle_t* handle); typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal); typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg); typedef void (*uv_fs_cb)(uv_fs_t* req); @@ -847,7 +847,15 @@ enum uv_udp_flags { * Indicates message was truncated because read buffer was too small. The * remainder was discarded by the OS. Used in uv_udp_recv_cb. */ - UV_UDP_PARTIAL = 2 + UV_UDP_PARTIAL = 2, + /* Indicates if SO_REUSEADDR will be set when binding the handle. + * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other + * UNIX platforms, it sets the SO_REUSEADDR flag. What that means is that + * multiple threads or processes can bind to the same address without error + * (provided they all set the flag) but only the last one to bind will receive + * any traffic, in effect "stealing" the port from the previous listener. + */ + UV_UDP_REUSEADDR = 4 }; /* @@ -922,18 +930,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); * handle UDP handle. Should have been initialized with `uv_udp_init`. * addr struct sockaddr_in or struct sockaddr_in6 with the address and * port to bind to. - * flags Unused. + * flags Indicate how the socket will be bound, UV_UDP_IPV6ONLY and + * UV_UDP_REUSEADDR are supported. * * Returns: * 0 on success, or an error code < 0 on failure. - * - * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other - * UNIX platforms, it sets the SO_REUSEADDR flag. What that means is that - * multiple threads or processes can bind to the same address without error - * (provided they all set the flag) but only the last one to bind will receive - * any traffic, in effect "stealing" the port from the previous listener. - * This behavior is something of an anomaly and may be replaced by an explicit - * opt-in mechanism in future versions of libuv. */ UV_EXTERN int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c index abde00302f..871228fc8d 100644 --- a/deps/uv/src/fs-poll.c +++ b/deps/uv/src/fs-poll.c @@ -41,7 +41,7 @@ struct poll_ctx { static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b); static void poll_cb(uv_fs_t* req); -static void timer_cb(uv_timer_t* timer, int status); +static void timer_cb(uv_timer_t* timer); static void timer_close_cb(uv_handle_t* handle); static uv_stat_t zero_statbuf; @@ -148,7 +148,7 @@ void uv__fs_poll_close(uv_fs_poll_t* handle) { } -static void timer_cb(uv_timer_t* timer, int status) { +static void timer_cb(uv_timer_t* timer) { struct poll_ctx* ctx; ctx = container_of(timer, struct poll_ctx, timer_handle); diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c new file mode 100644 index 0000000000..3cda578dd1 --- /dev/null +++ b/deps/uv/src/unix/android-ifaddrs.c @@ -0,0 +1,702 @@ +/* +Copyright (c) 2013, Kenneth MacKay +Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement n° 289016) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "android-ifaddrs.h" + +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sys/socket.h> +#include <net/if_arp.h> +#include <netinet/in.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> + +typedef struct NetlinkList +{ + struct NetlinkList *m_next; + struct nlmsghdr *m_data; + unsigned int m_size; +} NetlinkList; + +static int netlink_socket(void) +{ + struct sockaddr_nl l_addr; + + int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if(l_socket < 0) + { + return -1; + } + + memset(&l_addr, 0, sizeof(l_addr)); + l_addr.nl_family = AF_NETLINK; + if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) + { + close(l_socket); + return -1; + } + + return l_socket; +} + +static int netlink_send(int p_socket, int p_request) +{ + char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))]; + + struct nlmsghdr *l_hdr; + struct rtgenmsg *l_msg; + struct sockaddr_nl l_addr; + + memset(l_buffer, 0, sizeof(l_buffer)); + + l_hdr = (struct nlmsghdr *)l_buffer; + l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); + + l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); + l_hdr->nlmsg_type = p_request; + l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + l_hdr->nlmsg_pid = 0; + l_hdr->nlmsg_seq = p_socket; + l_msg->rtgen_family = AF_UNSPEC; + + memset(&l_addr, 0, sizeof(l_addr)); + l_addr.nl_family = AF_NETLINK; + return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); +} + +static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) +{ + struct sockaddr_nl l_addr; + struct msghdr l_msg; + + struct iovec l_iov; + l_iov.iov_base = p_buffer; + l_iov.iov_len = p_len; + + for(;;) + { + int l_result; + l_msg.msg_name = (void *)&l_addr; + l_msg.msg_namelen = sizeof(l_addr); + l_msg.msg_iov = &l_iov; + l_msg.msg_iovlen = 1; + l_msg.msg_control = NULL; + l_msg.msg_controllen = 0; + l_msg.msg_flags = 0; + l_result = recvmsg(p_socket, &l_msg, 0); + + if(l_result < 0) + { + if(errno == EINTR) + { + continue; + } + return -2; + } + + /* Buffer was too small */ + if(l_msg.msg_flags & MSG_TRUNC) + { + return -1; + } + return l_result; + } +} + +static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) +{ + size_t l_size = 4096; + void *l_buffer = NULL; + + for(;;) + { + int l_read; + + free(l_buffer); + l_buffer = malloc(l_size); + if (l_buffer == NULL) + { + return NULL; + } + + l_read = netlink_recv(p_socket, l_buffer, l_size); + *p_size = l_read; + if(l_read == -2) + { + free(l_buffer); + return NULL; + } + if(l_read >= 0) + { + pid_t l_pid = getpid(); + struct nlmsghdr *l_hdr; + for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) + { + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + { + continue; + } + + if(l_hdr->nlmsg_type == NLMSG_DONE) + { + *p_done = 1; + break; + } + + if(l_hdr->nlmsg_type == NLMSG_ERROR) + { + free(l_buffer); + return NULL; + } + } + return l_buffer; + } + + l_size *= 2; + } +} + +static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) +{ + NetlinkList *l_item = malloc(sizeof(NetlinkList)); + if (l_item == NULL) + { + return NULL; + } + + l_item->m_next = NULL; + l_item->m_data = p_data; + l_item->m_size = p_size; + return l_item; +} + +static void freeResultList(NetlinkList *p_list) +{ + NetlinkList *l_cur; + while(p_list) + { + l_cur = p_list; + p_list = p_list->m_next; + free(l_cur->m_data); + free(l_cur); + } +} + +static NetlinkList *getResultList(int p_socket, int p_request) +{ + int l_size; + int l_done; + NetlinkList *l_list; + NetlinkList *l_end; + + if(netlink_send(p_socket, p_request) < 0) + { + return NULL; + } + + l_list = NULL; + l_end = NULL; + + l_done = 0; + while(!l_done) + { + NetlinkList *l_item; + + struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); + /* Error */ + if(!l_hdr) + { + freeResultList(l_list); + return NULL; + } + + l_item = newListItem(l_hdr, l_size); + if (!l_item) + { + freeResultList(l_list); + return NULL; + } + if(!l_list) + { + l_list = l_item; + } + else + { + l_end->m_next = l_item; + } + l_end = l_item; + } + return l_list; +} + +static size_t maxSize(size_t a, size_t b) +{ + return (a > b ? a : b); +} + +static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) +{ + switch(p_family) + { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + case AF_PACKET: + return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); + default: + return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); + } +} + +static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) +{ + switch(p_family) + { + case AF_INET: + memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); + break; + case AF_INET6: + memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); + break; + case AF_PACKET: + memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); + ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; + break; + default: + memcpy(p_dest->sa_data, p_data, p_size); + break; + } + p_dest->sa_family = p_family; +} + +static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) +{ + if(!*p_resultList) + { + *p_resultList = p_entry; + } + else + { + struct ifaddrs *l_cur = *p_resultList; + while(l_cur->ifa_next) + { + l_cur = l_cur->ifa_next; + } + l_cur->ifa_next = p_entry; + } +} + +static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) +{ + struct ifaddrs *l_entry; + + char *l_index; + char *l_name; + char *l_addr; + char *l_data; + + struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); + + size_t l_nameSize = 0; + size_t l_addrSize = 0; + size_t l_dataSize = 0; + + size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); + struct rtattr *l_rta; + for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + switch(l_rta->rta_type) + { + case IFLA_ADDRESS: + case IFLA_BROADCAST: + l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); + break; + case IFLA_IFNAME: + l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); + break; + case IFLA_STATS: + l_dataSize += NLMSG_ALIGN(l_rtaSize); + break; + default: + break; + } + } + + l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); + if (l_entry == NULL) + { + return -1; + } + memset(l_entry, 0, sizeof(struct ifaddrs)); + l_entry->ifa_name = ""; + + l_index = ((char *)l_entry) + sizeof(struct ifaddrs); + l_name = l_index + sizeof(int); + l_addr = l_name + l_nameSize; + l_data = l_addr + l_addrSize; + + /* Save the interface index so we can look it up when handling the + * addresses. + */ + memcpy(l_index, &l_info->ifi_index, sizeof(int)); + + l_entry->ifa_flags = l_info->ifi_flags; + + l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); + for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + void *l_rtaData = RTA_DATA(l_rta); + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + switch(l_rta->rta_type) + { + case IFLA_ADDRESS: + case IFLA_BROADCAST: + { + size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); + makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); + ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; + ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; + if(l_rta->rta_type == IFLA_ADDRESS) + { + l_entry->ifa_addr = (struct sockaddr *)l_addr; + } + else + { + l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; + } + l_addr += NLMSG_ALIGN(l_addrLen); + break; + } + case IFLA_IFNAME: + strncpy(l_name, l_rtaData, l_rtaDataSize); + l_name[l_rtaDataSize] = '\0'; + l_entry->ifa_name = l_name; + break; + case IFLA_STATS: + memcpy(l_data, l_rtaData, l_rtaDataSize); + l_entry->ifa_data = l_data; + break; + default: + break; + } + } + + addToEnd(p_resultList, l_entry); + return 0; +} + +static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) +{ + int l_num = 0; + struct ifaddrs *l_cur = *p_links; + while(l_cur && l_num < p_numLinks) + { + char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); + int l_index; + memcpy(&l_index, l_indexPtr, sizeof(int)); + if(l_index == p_index) + { + return l_cur; + } + + l_cur = l_cur->ifa_next; + ++l_num; + } + return NULL; +} + +static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) +{ + struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); + struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); + + size_t l_nameSize = 0; + size_t l_addrSize = 0; + + int l_addedNetmask = 0; + + size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); + struct rtattr *l_rta; + struct ifaddrs *l_entry; + + char *l_name; + char *l_addr; + + for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + if(l_info->ifa_family == AF_PACKET) + { + continue; + } + + switch(l_rta->rta_type) + { + case IFA_ADDRESS: + case IFA_LOCAL: + if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) + { + /* Make room for netmask */ + l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); + l_addedNetmask = 1; + } + case IFA_BROADCAST: + l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); + break; + case IFA_LABEL: + l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); + break; + default: + break; + } + } + + l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); + if (l_entry == NULL) + { + return -1; + } + memset(l_entry, 0, sizeof(struct ifaddrs)); + l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); + + l_name = ((char *)l_entry) + sizeof(struct ifaddrs); + l_addr = l_name + l_nameSize; + + l_entry->ifa_flags = l_info->ifa_flags; + if(l_interface) + { + l_entry->ifa_flags |= l_interface->ifa_flags; + } + + l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); + for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) + { + void *l_rtaData = RTA_DATA(l_rta); + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); + switch(l_rta->rta_type) + { + case IFA_ADDRESS: + case IFA_BROADCAST: + case IFA_LOCAL: + { + size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); + makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); + if(l_info->ifa_family == AF_INET6) + { + if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) + { + ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; + } + } + + /* Apparently in a point-to-point network IFA_ADDRESS contains + * the dest address and IFA_LOCAL contains the local address + */ + if(l_rta->rta_type == IFA_ADDRESS) + { + if(l_entry->ifa_addr) + { + l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; + } + else + { + l_entry->ifa_addr = (struct sockaddr *)l_addr; + } + } + else if(l_rta->rta_type == IFA_LOCAL) + { + if(l_entry->ifa_addr) + { + l_entry->ifa_dstaddr = l_entry->ifa_addr; + } + l_entry->ifa_addr = (struct sockaddr *)l_addr; + } + else + { + l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; + } + l_addr += NLMSG_ALIGN(l_addrLen); + break; + } + case IFA_LABEL: + strncpy(l_name, l_rtaData, l_rtaDataSize); + l_name[l_rtaDataSize] = '\0'; + l_entry->ifa_name = l_name; + break; + default: + break; + } + } + + if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) + { + unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); + unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); + char l_mask[16] = {0}; + unsigned i; + for(i=0; i<(l_prefix/8); ++i) + { + l_mask[i] = 0xff; + } + if(l_prefix % 8) + { + l_mask[i] = 0xff << (8 - (l_prefix % 8)); + } + + makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); + l_entry->ifa_netmask = (struct sockaddr *)l_addr; + } + + addToEnd(p_resultList, l_entry); + return 0; +} + +static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) +{ + + int l_numLinks = 0; + pid_t l_pid = getpid(); + for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) + { + unsigned int l_nlsize = p_netlinkList->m_size; + struct nlmsghdr *l_hdr; + for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) + { + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + { + continue; + } + + if(l_hdr->nlmsg_type == NLMSG_DONE) + { + break; + } + + if(l_hdr->nlmsg_type == RTM_NEWLINK) + { + if(interpretLink(l_hdr, p_resultList) == -1) + { + return -1; + } + ++l_numLinks; + } + } + } + return l_numLinks; +} + +static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) +{ + pid_t l_pid = getpid(); + for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) + { + unsigned int l_nlsize = p_netlinkList->m_size; + struct nlmsghdr *l_hdr; + for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) + { + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + { + continue; + } + + if(l_hdr->nlmsg_type == NLMSG_DONE) + { + break; + } + + if(l_hdr->nlmsg_type == RTM_NEWADDR) + { + if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) + { + return -1; + } + } + } + } + return 0; +} + +int getifaddrs(struct ifaddrs **ifap) +{ + int l_socket; + int l_result; + int l_numLinks; + NetlinkList *l_linkResults; + NetlinkList *l_addrResults; + + if(!ifap) + { + return -1; + } + *ifap = NULL; + + l_socket = netlink_socket(); + if(l_socket < 0) + { + return -1; + } + + l_linkResults = getResultList(l_socket, RTM_GETLINK); + if(!l_linkResults) + { + close(l_socket); + return -1; + } + + l_addrResults = getResultList(l_socket, RTM_GETADDR); + if(!l_addrResults) + { + close(l_socket); + freeResultList(l_linkResults); + return -1; + } + + l_result = 0; + l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); + if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) + { + l_result = -1; + } + + freeResultList(l_linkResults); + freeResultList(l_addrResults); + close(l_socket); + return l_result; +} + +void freeifaddrs(struct ifaddrs *ifa) +{ + struct ifaddrs *l_cur; + while(ifa) + { + l_cur = ifa; + ifa = ifa->ifa_next; + free(l_cur); + } +} diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 3c23e1d7fd..2c3bc82aef 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -85,7 +85,7 @@ static void uv__async_event(uv_loop_t* loop, if (h->async_cb == NULL) continue; - h->async_cb(h, 0); + h->async_cb(h); } } diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index b393097fd2..9680a2d0a9 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -605,7 +605,7 @@ int uv_cwd(char* buffer, size_t* size) { if (getcwd(buffer, *size) == NULL) return -errno; - *size = strlen(buffer); + *size = strlen(buffer) + 1; return 0; } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index cf45669cd9..8a4edcbc0a 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -217,9 +217,17 @@ skip: static ssize_t uv__fs_read(uv_fs_t* req) { ssize_t result; - if (req->off < 0) - result = readv(req->file, (struct iovec*) req->bufs, req->nbufs); - else { + if (req->off < 0) { + if (req->nbufs == 1) + result = read(req->file, req->bufs[0].base, req->bufs[0].len); + else + result = readv(req->file, (struct iovec*) req->bufs, req->nbufs); + } else { + if (req->nbufs == 1) { + result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off); + goto done; + } + #if HAVE_PREADV result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); #else @@ -265,6 +273,8 @@ static ssize_t uv__fs_read(uv_fs_t* req) { # endif #endif } + +done: if (req->bufs != req->bufsml) free(req->bufs); return result; @@ -583,9 +593,16 @@ static ssize_t uv__fs_write(uv_fs_t* req) { pthread_mutex_lock(&lock); #endif - if (req->off < 0) - r = writev(req->file, (struct iovec*) req->bufs, req->nbufs); - else { + if (req->off < 0) { + if (req->nbufs == 1) + r = write(req->file, req->bufs[0].base, req->bufs[0].len); + else + r = writev(req->file, (struct iovec*) req->bufs, req->nbufs); + } else { + if (req->nbufs == 1) { + r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off); + goto done; + } #if HAVE_PREADV r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); #else @@ -632,6 +649,7 @@ static ssize_t uv__fs_write(uv_fs_t* req) { #endif } +done: #if defined(__APPLE__) pthread_mutex_unlock(&lock); #endif diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index f9c3a400fb..1c7896d8d7 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -177,7 +177,7 @@ static void (*pFSEventStreamStop)(FSEventStreamRef); /* Runs in UV loop's thread, when there're events to report to handle */ -static void uv__fsevents_cb(uv_async_t* cb, int status) { +static void uv__fsevents_cb(uv_async_t* cb) { uv_fs_event_t* handle; handle = cb->data; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 61f5f6aa2f..e4ff91b887 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -136,7 +136,8 @@ enum { UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */ UV_TCP_NODELAY = 0x400, /* Disable Nagle. */ UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ - UV_TCP_SINGLE_ACCEPT = 0x1000 /* Only accept() when idle. */ + UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */ + UV_HANDLE_IPV6 = 0x2000 /* Handle is bound to a IPv6 socket. */ }; typedef enum { @@ -214,7 +215,7 @@ void uv__work_submit(uv_loop_t* loop, struct uv__work *w, void (*work)(struct uv__work *w), void (*done)(struct uv__work *w, int status)); -void uv__work_done(uv_async_t* handle, int status); +void uv__work_done(uv_async_t* handle); /* platform specific */ uint64_t uv__hrtime(uv_clocktype_t type); diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 97a5126f6a..5f6215998c 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -36,21 +36,24 @@ #include <fcntl.h> #include <time.h> -#ifndef __ANDROID__ #define HAVE_IFADDRS_H 1 -#endif #ifdef __UCLIBC__ # if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32 # undef HAVE_IFADDRS_H # endif #endif + #ifdef HAVE_IFADDRS_H -# include <ifaddrs.h> +# if defined(__ANDROID__) +# include "android-ifaddrs.h" +# else +# include <ifaddrs.h> +# endif # include <sys/socket.h> # include <net/ethernet.h> # include <linux/if_packet.h> -#endif +#endif /* HAVE_IFADDRS_H */ /* Available from 2.6.32 onwards. */ #ifndef CLOCK_MONOTONIC_COARSE diff --git a/deps/uv/src/unix/loop-watcher.c b/deps/uv/src/unix/loop-watcher.c index dc03c206d2..dc25760bd5 100644 --- a/deps/uv/src/unix/loop-watcher.c +++ b/deps/uv/src/unix/loop-watcher.c @@ -50,7 +50,7 @@ QUEUE* q; \ QUEUE_FOREACH(q, &loop->name##_handles) { \ h = QUEUE_DATA(q, uv_##name##_t, queue); \ - h->name##_cb(h, 0); \ + h->name##_cb(h); \ } \ } \ \ diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 53fef8436b..52e4eb2813 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -316,7 +316,7 @@ static void uv__process_child_init(const uv_process_options_t* options, if (fd <= 2) uv__nonblock(fd, 0); - if (close_fd != -1) + if (close_fd >= stdio_count) uv__close(close_fd); } diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 370894bfd6..e1f660309d 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -224,7 +224,7 @@ static void uv__stream_osx_select(void* arg) { } -static void uv__stream_osx_select_cb(uv_async_t* handle, int status) { +static void uv__stream_osx_select_cb(uv_async_t* handle) { uv__stream_select_t* s; uv_stream_t* stream; int events; @@ -1127,7 +1127,7 @@ static void uv__read(uv_stream_t* stream) { if (is_ipc) { err = uv__stream_recv_cmsg(stream, &msg); if (err != 0) { - stream->read_cb(stream, err, NULL); + stream->read_cb(stream, err, &buf); return; } } diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 9c50b2d8a1..80b5471a7b 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -89,8 +89,11 @@ int uv__tcp_bind(uv_tcp_t* tcp, errno = 0; if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) return -errno; - tcp->delayed_error = -errno; + + if (addr->sa_family == AF_INET6) + tcp->flags |= UV_HANDLE_IPV6; + return 0; } diff --git a/deps/uv/src/unix/threadpool.c b/deps/uv/src/unix/threadpool.c index 7923250a09..f2eb1cb5c6 100644 --- a/deps/uv/src/unix/threadpool.c +++ b/deps/uv/src/unix/threadpool.c @@ -191,7 +191,7 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { } -void uv__work_done(uv_async_t* handle, int status) { +void uv__work_done(uv_async_t* handle) { struct uv__work* w; uv_loop_t* loop; QUEUE* q; diff --git a/deps/uv/src/unix/timer.c b/deps/uv/src/unix/timer.c index b373f4db87..9bd0423b5d 100644 --- a/deps/uv/src/unix/timer.c +++ b/deps/uv/src/unix/timer.c @@ -159,7 +159,7 @@ void uv__run_timers(uv_loop_t* loop) { uv_timer_stop(handle); uv_timer_again(handle); - handle->timer_cb(handle, 0); + handle->timer_cb(handle); } } diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index c7ed101a75..7ae19905fb 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -39,6 +39,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { int newfd; int r; + flags = 0; newfd = -1; uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); @@ -54,10 +55,16 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { * other processes. */ if (isatty(fd)) { - newfd = uv__open_cloexec("/dev/tty", O_RDWR); + r = uv__open_cloexec("/dev/tty", O_RDWR); - if (newfd == -1) - return -errno; + if (r < 0) { + /* fallback to using blocking writes */ + if (!readable) + flags |= UV_STREAM_BLOCKING; + goto skip; + } + + newfd = r; r = uv__dup2_cloexec(newfd, fd); if (r < 0 && r != -EINVAL) { @@ -72,6 +79,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { fd = newfd; } +skip: #if defined(__APPLE__) r = uv__stream_try_select((uv_stream_t*) tty, &fd); if (r) { @@ -82,11 +90,13 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { #endif if (readable) - flags = UV_STREAM_READABLE; + flags |= UV_STREAM_READABLE; else - flags = UV_STREAM_WRITABLE; + flags |= UV_STREAM_WRITABLE; + + if (!(flags & UV_STREAM_BLOCKING)) + uv__nonblock(fd, 1); - uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = 0; diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index ae3cc8dc65..efc180c78d 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -28,13 +28,23 @@ #include <stdlib.h> #include <unistd.h> +#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) +# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#endif + +#if defined(IPV6_LEAVE_GROUP) && !defined(IPV6_DROP_MEMBERSHIP) +# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#endif + static void uv__udp_run_completed(uv_udp_t* handle); static void uv__udp_run_pending(uv_udp_t* handle); static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents); static void uv__udp_recvmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents); static void uv__udp_sendmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents); -static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain); +static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, + int domain, + unsigned int flags); void uv__udp_close(uv_udp_t* handle) { @@ -300,7 +310,7 @@ int uv__udp_bind(uv_udp_t* handle, fd = -1; /* Check for bad flags. */ - if (flags & ~UV_UDP_IPV6ONLY) + if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR)) return -EINVAL; /* Cannot set IPv6-only mode on non-IPv6 socket. */ @@ -315,9 +325,11 @@ int uv__udp_bind(uv_udp_t* handle, handle->io_watcher.fd = fd; } - err = uv__set_reuse(fd); - if (err) - goto out; + if (flags & UV_UDP_REUSEADDR) { + err = uv__set_reuse(fd); + if (err) + goto out; + } if (flags & UV_UDP_IPV6ONLY) { #ifdef IPV6_V6ONLY @@ -337,6 +349,9 @@ int uv__udp_bind(uv_udp_t* handle, goto out; } + if (addr->sa_family == AF_INET6) + handle->flags |= UV_HANDLE_IPV6; + return 0; out: @@ -346,7 +361,9 @@ out: } -static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain) { +static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, + int domain, + unsigned int flags) { unsigned char taddr[sizeof(struct sockaddr_in6)]; socklen_t addrlen; @@ -379,7 +396,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain) { abort(); } - return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, 0); + return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, flags); } @@ -394,7 +411,7 @@ int uv__udp_send(uv_udp_send_t* req, assert(nbufs > 0); - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family); + err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); if (err) return err; @@ -422,63 +439,82 @@ int uv__udp_send(uv_udp_send_t* req, } -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP); - handle->alloc_cb = NULL; - handle->recv_cb = NULL; - uv__io_init(&handle->io_watcher, uv__udp_io, -1); - QUEUE_INIT(&handle->write_queue); - QUEUE_INIT(&handle->write_completed_queue); - return 0; -} +static int uv__udp_set_membership4(uv_udp_t* handle, + const struct sockaddr_in* multicast_addr, + const char* interface_addr, + uv_membership membership) { + struct ip_mreq mreq; + int optname; + int err; + memset(&mreq, 0, sizeof mreq); -int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { - int err; + if (interface_addr) { + err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); + if (err) + return err; + } else { + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } - /* Check for already active socket. */ - if (handle->io_watcher.fd != -1) - return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ + mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; - err = uv__set_reuse(sock); - if (err) - return err; + switch (membership) { + case UV_JOIN_GROUP: + optname = IP_ADD_MEMBERSHIP; + break; + case UV_LEAVE_GROUP: + optname = IP_DROP_MEMBERSHIP; + break; + default: + return -EINVAL; + } + + if (setsockopt(handle->io_watcher.fd, + IPPROTO_IP, + optname, + &mreq, + sizeof(mreq))) { + return -errno; + } - handle->io_watcher.fd = sock; return 0; } -int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership) { - struct ip_mreq mreq; +static int uv__udp_set_membership6(uv_udp_t* handle, + const struct sockaddr_in6* multicast_addr, + const char* interface_addr, + uv_membership membership) { int optname; + struct ipv6_mreq mreq; + struct sockaddr_in6 addr6; memset(&mreq, 0, sizeof mreq); if (interface_addr) { - mreq.imr_interface.s_addr = inet_addr(interface_addr); + if (uv_ip6_addr(interface_addr, 0, &addr6)) + return -EINVAL; + mreq.ipv6mr_interface = addr6.sin6_scope_id; } else { - mreq.imr_interface.s_addr = htonl(INADDR_ANY); + mreq.ipv6mr_interface = 0; } - mreq.imr_multiaddr.s_addr = inet_addr(multicast_addr); + mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr; switch (membership) { case UV_JOIN_GROUP: - optname = IP_ADD_MEMBERSHIP; + optname = IPV6_ADD_MEMBERSHIP; break; case UV_LEAVE_GROUP: - optname = IP_DROP_MEMBERSHIP; + optname = IPV6_DROP_MEMBERSHIP; break; default: return -EINVAL; } if (setsockopt(handle->io_watcher.fd, - IPPROTO_IP, + IPPROTO_IPV6, optname, &mreq, sizeof(mreq))) { @@ -489,6 +525,57 @@ int uv_udp_set_membership(uv_udp_t* handle, } +int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { + uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP); + handle->alloc_cb = NULL; + handle->recv_cb = NULL; + uv__io_init(&handle->io_watcher, uv__udp_io, -1); + QUEUE_INIT(&handle->write_queue); + QUEUE_INIT(&handle->write_completed_queue); + return 0; +} + + +int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { + int err; + + /* Check for already active socket. */ + if (handle->io_watcher.fd != -1) + return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ + + err = uv__set_reuse(sock); + if (err) + return err; + + handle->io_watcher.fd = sock; + return 0; +} + + +int uv_udp_set_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + uv_membership membership) { + int err; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + + if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) { + err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR); + if (err) + return err; + return uv__udp_set_membership4(handle, &addr4, interface_addr, membership); + } else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) { + err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR); + if (err) + return err; + return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); + } else { + return -EINVAL; + } +} + + static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { #if defined(__sun) char arg = val; @@ -540,25 +627,56 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { } int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { - struct in_addr addr; int err; + struct sockaddr_storage addr_st; + struct sockaddr_in* addr4; + struct sockaddr_in6* addr6; + + addr4 = (struct sockaddr_in*) &addr_st; + addr6 = (struct sockaddr_in6*) &addr_st; + + if (!interface_addr) { + memset(&addr_st, 0, sizeof addr_st); + if (handle->flags & UV_HANDLE_IPV6) { + addr_st.ss_family = AF_INET6; + addr6->sin6_scope_id = 0; + } else { + addr_st.ss_family = AF_INET; + addr4->sin_addr.s_addr = htonl(INADDR_ANY); + } + } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) { + /* nothing, address was parsed */ + } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) { + /* nothing, address was parsed */ + } else { + return -EINVAL; + } - memset(&addr, 0, sizeof addr); - - if (interface_addr) { - err = uv_inet_pton(AF_INET, interface_addr, &addr.s_addr); + if (addr_st.ss_family == AF_INET) { + err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR); + if (err) + return err; + if (setsockopt(handle->io_watcher.fd, + IPPROTO_IP, + IP_MULTICAST_IF, + (void*) &addr4->sin_addr, + sizeof(addr4->sin_addr)) == -1) { + return -errno; + } + } else if (addr_st.ss_family == AF_INET6) { + err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR); if (err) return err; + if (setsockopt(handle->io_watcher.fd, + IPPROTO_IPV6, + IPV6_MULTICAST_IF, + &addr6->sin6_scope_id, + sizeof(addr6->sin6_scope_id)) == -1) { + return -errno; + } } else { - addr.s_addr = htonl(INADDR_ANY); - } - - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - IP_MULTICAST_IF, - (void*) &addr, - sizeof addr) == -1) { - return -errno; + assert(0 && "unexpected address family"); + abort(); } return 0; @@ -593,7 +711,7 @@ int uv__udp_recv_start(uv_udp_t* handle, if (uv__io_active(&handle->io_watcher, UV__POLLIN)) return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ - err = uv__udp_maybe_deferred_bind(handle, AF_INET); + err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0); if (err) return err; diff --git a/deps/uv/src/win/async.c b/deps/uv/src/win/async.c index e192ead90d..ad240ab897 100644 --- a/deps/uv/src/win/async.c +++ b/deps/uv/src/win/async.c @@ -94,6 +94,6 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, if (handle->flags & UV__HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*)handle); } else if (handle->async_cb != NULL) { - handle->async_cb(handle, 0); + handle->async_cb(handle); } } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 82f8eb602c..45ce177e64 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -84,8 +84,10 @@ extern __declspec( thread ) int uv__crt_assert_enabled; #define UV_HANDLE_EMULATE_IOCP 0x00100000 #define UV_HANDLE_BLOCKING_WRITES 0x00200000 -/* Only used by uv_tcp_t handles. */ +/* Used by uv_tcp_t and uv_udp_t handles */ #define UV_HANDLE_IPV6 0x01000000 + +/* Only used by uv_tcp_t handles. */ #define UV_HANDLE_TCP_NODELAY 0x02000000 #define UV_HANDLE_TCP_KEEPALIVE 0x04000000 #define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000 diff --git a/deps/uv/src/win/loop-watcher.c b/deps/uv/src/win/loop-watcher.c index 6dbc861edd..eb49f7cbc5 100644 --- a/deps/uv/src/win/loop-watcher.c +++ b/deps/uv/src/win/loop-watcher.c @@ -115,7 +115,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { handle = (loop)->next_##name##_handle; \ (loop)->next_##name##_handle = handle->name##_next; \ \ - handle->name##_cb(handle, 0); \ + handle->name##_cb(handle); \ } \ } diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index b832a28c60..8791604f67 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -79,7 +79,7 @@ typedef struct { static void eof_timer_init(uv_pipe_t* pipe); static void eof_timer_start(uv_pipe_t* pipe); static void eof_timer_stop(uv_pipe_t* pipe); -static void eof_timer_cb(uv_timer_t* timer, int status); +static void eof_timer_cb(uv_timer_t* timer); static void eof_timer_destroy(uv_pipe_t* pipe); static void eof_timer_close_cb(uv_handle_t* handle); @@ -1347,7 +1347,7 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, handle->flags &= ~UV_HANDLE_READABLE; uv_read_stop((uv_stream_t*) handle); - handle->read_cb((uv_stream_t*) handle, UV_EOF, &uv_null_buf_); + handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf); } @@ -1505,7 +1505,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, break; } } else { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); + uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); break; } } @@ -1695,11 +1695,10 @@ static void eof_timer_stop(uv_pipe_t* pipe) { } -static void eof_timer_cb(uv_timer_t* timer, int status) { +static void eof_timer_cb(uv_timer_t* timer) { uv_pipe_t* pipe = (uv_pipe_t*) timer->data; uv_loop_t* loop = timer->loop; - assert(status == 0); /* timers can't fail */ assert(pipe->type == UV_NAMED_PIPE); /* This should always be true, since we start the timer only */ diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c index 6c53ea37e0..16a2fc5f5f 100644 --- a/deps/uv/src/win/timer.c +++ b/deps/uv/src/win/timer.c @@ -249,6 +249,6 @@ void uv_process_timers(uv_loop_t* loop) { uv__handle_stop(timer); } - timer->timer_cb((uv_timer_t*) timer, 0); + timer->timer_cb((uv_timer_t*) timer); } } diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 1b17cb726f..7840fb2861 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -1815,7 +1815,7 @@ void uv_tty_close(uv_tty_t* handle) { void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { - if (!(handle->flags && UV_HANDLE_TTY_READABLE) && + if (!(handle->flags & UV_HANDLE_TTY_READABLE) && handle->shutdown_req != NULL && handle->write_reqs_pending == 0) { UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req); diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 282d49480e..8719fa7f44 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -62,15 +62,6 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, assert(handle->socket == INVALID_SOCKET); - /* Set SO_REUSEADDR on the socket. */ - if (setsockopt(socket, - SOL_SOCKET, - SO_REUSEADDR, - (char*) &yes, - sizeof yes) == SOCKET_ERROR) { - return WSAGetLastError(); - } - /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { return WSAGetLastError(); @@ -168,14 +159,17 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { } -static int uv_udp_try_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { +static int uv_udp_maybe_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags) { int r; int err; DWORD no = 0; + if (handle->flags & UV_HANDLE_BOUND) + return 0; + if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) { /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ return ERROR_INVALID_PARAMETER; @@ -193,6 +187,20 @@ static int uv_udp_try_bind(uv_udp_t* handle, return err; } + if (flags & UV_UDP_REUSEADDR) { + DWORD yes = 1; + /* Set SO_REUSEADDR on the socket. */ + if (setsockopt(sock, + SOL_SOCKET, + SO_REUSEADDR, + (char*) &yes, + sizeof yes) == SOCKET_ERROR) { + err = WSAGetLastError(); + closesocket(sock); + return err; + } + } + if (addr->sa_family == AF_INET6) handle->flags |= UV_HANDLE_IPV6; } @@ -324,14 +332,12 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, return WSAEALREADY; } - if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_try_bind(handle, + err = uv_udp_maybe_bind(handle, (const struct sockaddr*) &uv_addr_ip4_any_, sizeof(uv_addr_ip4_any_), 0); - if (err) - return err; - } + if (err) + return err; handle->flags |= UV_HANDLE_READING; INCREASE_ACTIVE_COUNT(loop, handle); @@ -532,25 +538,24 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, } -int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, - const char* interface_addr, uv_membership membership) { +static int uv__udp_set_membership4(uv_udp_t* handle, + const struct sockaddr_in* multicast_addr, + const char* interface_addr, + uv_membership membership) { int err; int optname; struct ip_mreq mreq; + if (handle->flags & UV_HANDLE_IPV6) + return UV_EINVAL; + /* If the socket is unbound, bind to inaddr_any. */ - if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_try_bind(handle, + err = uv_udp_maybe_bind(handle, (const struct sockaddr*) &uv_addr_ip4_any_, sizeof(uv_addr_ip4_any_), - 0); - if (err) - return uv_translate_sys_error(err); - } - - if (handle->flags & UV_HANDLE_IPV6) { - return UV_ENOSYS; - } + UV_UDP_REUSEADDR); + if (err) + return uv_translate_sys_error(err); memset(&mreq, 0, sizeof mreq); @@ -560,7 +565,7 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, mreq.imr_interface.s_addr = htonl(INADDR_ANY); } - mreq.imr_multiaddr.s_addr = inet_addr(multicast_addr); + mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; switch (membership) { case UV_JOIN_GROUP: @@ -585,39 +590,54 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, } -int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { - struct in_addr addr; +int uv__udp_set_membership6(uv_udp_t* handle, + const struct sockaddr_in6* multicast_addr, + const char* interface_addr, + uv_membership membership) { + int optname; int err; + struct ipv6_mreq mreq; + struct sockaddr_in6 addr6; - memset(&addr, 0, sizeof addr); + if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) + return UV_EINVAL; - if (handle->flags & UV_HANDLE_IPV6) { - return UV_ENOSYS; - } + err = uv_udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip6_any_, + sizeof(uv_addr_ip6_any_), + UV_UDP_REUSEADDR); - /* If the socket is unbound, bind to inaddr_any. */ - if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_try_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); - if (err) - return uv_translate_sys_error(err); - } + if (err) + return uv_translate_sys_error(err); + + memset(&mreq, 0, sizeof(mreq)); if (interface_addr) { - err = uv_inet_pton(AF_INET, interface_addr, &addr.s_addr); - if (err) - return err; + if (uv_ip6_addr(interface_addr, 0, &addr6)) + return UV_EINVAL; + mreq.ipv6mr_interface = addr6.sin6_scope_id; } else { - addr.s_addr = htonl(INADDR_ANY); + mreq.ipv6mr_interface = 0; + } + + mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr; + + switch (membership) { + case UV_JOIN_GROUP: + optname = IPV6_ADD_MEMBERSHIP; + break; + case UV_LEAVE_GROUP: + optname = IPV6_DROP_MEMBERSHIP; + break; + default: + return UV_EINVAL; } if (setsockopt(handle->socket, - IPPROTO_IP, - IP_MULTICAST_IF, - (char*) &addr, - sizeof addr) == SOCKET_ERROR) { + IPPROTO_IPV6, + optname, + (char*) &mreq, + sizeof mreq) == SOCKET_ERROR) { return uv_translate_sys_error(WSAGetLastError()); } @@ -625,19 +645,96 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) } +int uv_udp_set_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + uv_membership membership) { + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + + if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) + return uv__udp_set_membership4(handle, &addr4, interface_addr, membership); + else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) + return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); + else + return UV_EINVAL; +} + + +int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { + int err; + struct sockaddr_storage addr_st; + struct sockaddr_in* addr4; + struct sockaddr_in6* addr6; + + addr4 = (struct sockaddr_in*) &addr_st; + addr6 = (struct sockaddr_in6*) &addr_st; + + if (!interface_addr) { + memset(&addr_st, 0, sizeof addr_st); + if (handle->flags & UV_HANDLE_IPV6) { + addr_st.ss_family = AF_INET6; + addr6->sin6_scope_id = 0; + } else { + addr_st.ss_family = AF_INET; + addr4->sin_addr.s_addr = htonl(INADDR_ANY); + } + } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) { + /* nothing, address was parsed */ + } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) { + /* nothing, address was parsed */ + } else { + return UV_EINVAL; + } + + if (addr_st.ss_family == AF_INET) { + err = uv_udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + UV_UDP_REUSEADDR); + if (err) + return uv_translate_sys_error(err); + if (setsockopt(handle->socket, + IPPROTO_IP, + IP_MULTICAST_IF, + (char*) &addr4->sin_addr, + sizeof(addr4->sin_addr)) == SOCKET_ERROR) { + return uv_translate_sys_error(WSAGetLastError()); + } + } else if (addr_st.ss_family == AF_INET6) { + err = uv_udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip6_any_, + sizeof(uv_addr_ip6_any_), + UV_UDP_REUSEADDR); + if (err) + return uv_translate_sys_error(err); + if (setsockopt(handle->socket, + IPPROTO_IPV6, + IPV6_MULTICAST_IF, + (char*) &addr6->sin6_scope_id, + sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) { + return uv_translate_sys_error(WSAGetLastError()); + } + } else { + assert(0 && "unexpected address family"); + abort(); + } + + return 0; +} + + int uv_udp_set_broadcast(uv_udp_t* handle, int value) { BOOL optval = (BOOL) value; int err; /* If the socket is unbound, bind to inaddr_any. */ - if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_try_bind(handle, + err = uv_udp_maybe_bind(handle, (const struct sockaddr*) &uv_addr_ip4_any_, sizeof(uv_addr_ip4_any_), 0); - if (err) - return uv_translate_sys_error(err); - } + if (err) + return uv_translate_sys_error(err); if (setsockopt(handle->socket, SOL_SOCKET, @@ -684,14 +781,12 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { } \ \ /* If the socket is unbound, bind to inaddr_any. */ \ - if (!(handle->flags & UV_HANDLE_BOUND)) { \ - err = uv_udp_try_bind(handle, \ + err = uv_udp_maybe_bind(handle, \ (const struct sockaddr*) &uv_addr_ip4_any_, \ sizeof(uv_addr_ip4_any_), \ 0); \ - if (err) \ - return uv_translate_sys_error(err); \ - } \ + if (err) \ + return uv_translate_sys_error(err); \ \ if (!(handle->flags & UV_HANDLE_IPV6)) { \ /* Set IPv4 socket option */ \ @@ -747,7 +842,7 @@ int uv__udp_bind(uv_udp_t* handle, unsigned int flags) { int err; - err = uv_udp_try_bind(handle, addr, addrlen, flags); + err = uv_udp_maybe_bind(handle, addr, addrlen, flags); if (err) return uv_translate_sys_error(err); @@ -776,7 +871,7 @@ int uv__udp_send(uv_udp_send_t* req, } else { abort(); } - err = uv_udp_try_bind(handle, bind_addr, addrlen, 0); + err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); if (err) return uv_translate_sys_error(err); } diff --git a/deps/uv/test/benchmark-async-pummel.c b/deps/uv/test/benchmark-async-pummel.c index 4761c1928e..cca3de1062 100644 --- a/deps/uv/test/benchmark-async-pummel.c +++ b/deps/uv/test/benchmark-async-pummel.c @@ -36,7 +36,7 @@ static const char stop[] = "stop"; static const char stopped[] = "stopped"; -static void async_cb(uv_async_t* handle, int status) { +static void async_cb(uv_async_t* handle) { if (++callbacks == NUM_PINGS) { /* Tell the pummel thread to stop. */ ACCESS_ONCE(const char*, handle->data) = stop; diff --git a/deps/uv/test/benchmark-async.c b/deps/uv/test/benchmark-async.c index defed67bf8..e44165f2b8 100644 --- a/deps/uv/test/benchmark-async.c +++ b/deps/uv/test/benchmark-async.c @@ -40,7 +40,7 @@ struct ctx { }; -static void worker_async_cb(uv_async_t* handle, int status) { +static void worker_async_cb(uv_async_t* handle) { struct ctx* ctx = container_of(handle, struct ctx, worker_async); ASSERT(0 == uv_async_send(&ctx->main_async)); @@ -52,7 +52,7 @@ static void worker_async_cb(uv_async_t* handle, int status) { } -static void main_async_cb(uv_async_t* handle, int status) { +static void main_async_cb(uv_async_t* handle) { struct ctx* ctx = container_of(handle, struct ctx, main_async); ASSERT(0 == uv_async_send(&ctx->worker_async)); diff --git a/deps/uv/test/benchmark-loop-count.c b/deps/uv/test/benchmark-loop-count.c index b4ee0ed5ff..5cb813238d 100644 --- a/deps/uv/test/benchmark-loop-count.c +++ b/deps/uv/test/benchmark-loop-count.c @@ -32,18 +32,18 @@ static uv_idle_t idle_handle; static uv_timer_t timer_handle; -static void idle_cb(uv_idle_t* handle, int status) { +static void idle_cb(uv_idle_t* handle) { if (++ticks == NUM_TICKS) uv_idle_stop(handle); } -static void idle2_cb(uv_idle_t* handle, int status) { +static void idle2_cb(uv_idle_t* handle) { ticks++; } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { uv_idle_stop(&idle_handle); uv_timer_stop(&timer_handle); } diff --git a/deps/uv/test/benchmark-million-async.c b/deps/uv/test/benchmark-million-async.c index 69cc803436..5395ed54ba 100644 --- a/deps/uv/test/benchmark-million-async.c +++ b/deps/uv/test/benchmark-million-async.c @@ -50,13 +50,13 @@ static void thread_cb(void* arg) { } -static void async_cb(uv_async_t* handle, int status) { +static void async_cb(uv_async_t* handle) { container->async_events++; handle->data = handle; } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { unsigned i; done = 1; diff --git a/deps/uv/test/benchmark-million-timers.c b/deps/uv/test/benchmark-million-timers.c index 64f4a1038e..6027d6088a 100644 --- a/deps/uv/test/benchmark-million-timers.c +++ b/deps/uv/test/benchmark-million-timers.c @@ -28,7 +28,7 @@ static int timer_cb_called; static int close_cb_called; -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { timer_cb_called++; } diff --git a/deps/uv/test/benchmark-multi-accept.c b/deps/uv/test/benchmark-multi-accept.c index da0c76df1b..2f32c0caf4 100644 --- a/deps/uv/test/benchmark-multi-accept.c +++ b/deps/uv/test/benchmark-multi-accept.c @@ -90,7 +90,7 @@ static void ipc_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); -static void sv_async_cb(uv_async_t* handle, int status); +static void sv_async_cb(uv_async_t* handle); static void sv_connection_cb(uv_stream_t* server_handle, int status); static void sv_read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf); static void sv_alloc_cb(uv_handle_t* handle, @@ -98,7 +98,7 @@ static void sv_alloc_cb(uv_handle_t* handle, uv_buf_t* buf); static void cl_connect_cb(uv_connect_t* req, int status); -static void cl_idle_cb(uv_idle_t* handle, int status); +static void cl_idle_cb(uv_idle_t* handle); static void cl_close_cb(uv_handle_t* handle); static struct sockaddr_in listen_addr; @@ -275,7 +275,7 @@ static void server_cb(void *arg) { } -static void sv_async_cb(uv_async_t* handle, int status) { +static void sv_async_cb(uv_async_t* handle) { struct server_ctx* ctx; ctx = container_of(handle, struct server_ctx, async_handle); uv_close((uv_handle_t*) &ctx->server_handle, NULL); @@ -330,7 +330,7 @@ static void cl_connect_cb(uv_connect_t* req, int status) { } -static void cl_idle_cb(uv_idle_t* handle, int status) { +static void cl_idle_cb(uv_idle_t* handle) { struct client_ctx* ctx = container_of(handle, struct client_ctx, idle_handle); uv_close((uv_handle_t*) &ctx->client_handle, cl_close_cb); uv_idle_stop(&ctx->idle_handle); diff --git a/deps/uv/test/benchmark-pump.c b/deps/uv/test/benchmark-pump.c index 678634ff71..d58f46a384 100644 --- a/deps/uv/test/benchmark-pump.c +++ b/deps/uv/test/benchmark-pump.c @@ -85,7 +85,7 @@ static double gbit(int64_t bytes, int64_t passed_ms) { } -static void show_stats(uv_timer_t* handle, int status) { +static void show_stats(uv_timer_t* handle) { int64_t diff; int i; diff --git a/deps/uv/test/benchmark-udp-pummel.c b/deps/uv/test/benchmark-udp-pummel.c index d99250affc..68a2373d78 100644 --- a/deps/uv/test/benchmark-udp-pummel.c +++ b/deps/uv/test/benchmark-udp-pummel.c @@ -132,7 +132,7 @@ static void close_cb(uv_handle_t* handle) { } -static void timeout_cb(uv_timer_t* timer, int status) { +static void timeout_cb(uv_timer_t* timer) { int i; exiting = 1; diff --git a/deps/uv/test/test-active.c b/deps/uv/test/test-active.c index 0fae23cdb1..b17bd17601 100644 --- a/deps/uv/test/test-active.c +++ b/deps/uv/test/test-active.c @@ -35,7 +35,7 @@ static void close_cb(uv_handle_t* handle) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(0 && "timer_cb should not have been called"); } diff --git a/deps/uv/test/test-async-null-cb.c b/deps/uv/test/test-async-null-cb.c index d654884268..757944a276 100644 --- a/deps/uv/test/test-async-null-cb.c +++ b/deps/uv/test/test-async-null-cb.c @@ -34,7 +34,7 @@ static void thread_cb(void* dummy) { } -static void check_cb(uv_check_t* handle, int status) { +static void check_cb(uv_check_t* handle) { ASSERT(check_cb_called == 0); uv_close((uv_handle_t*) &async_handle, NULL); uv_close((uv_handle_t*) &check_handle, NULL); diff --git a/deps/uv/test/test-async.c b/deps/uv/test/test-async.c index d4d94d5fa0..6f5351bf15 100644 --- a/deps/uv/test/test-async.c +++ b/deps/uv/test/test-async.c @@ -75,11 +75,10 @@ static void close_cb(uv_handle_t* handle) { } -static void async_cb(uv_async_t* handle, int status) { +static void async_cb(uv_async_t* handle) { int n; ASSERT(handle == &async); - ASSERT(status == 0); uv_mutex_lock(&mutex); n = ++async_cb_called; @@ -92,11 +91,10 @@ static void async_cb(uv_async_t* handle, int status) { } -static void prepare_cb(uv_prepare_t* handle, int status) { +static void prepare_cb(uv_prepare_t* handle) { int r; ASSERT(handle == &prepare); - ASSERT(status == 0); if (prepare_cb_called++) return; diff --git a/deps/uv/test/test-callback-order.c b/deps/uv/test/test-callback-order.c index 84231e1b6b..8bc2c4f75d 100644 --- a/deps/uv/test/test-callback-order.c +++ b/deps/uv/test/test-callback-order.c @@ -30,7 +30,7 @@ static uv_timer_t timer_handle; /* idle_cb should run before timer_cb */ -static void idle_cb(uv_idle_t* handle, int status) { +static void idle_cb(uv_idle_t* handle) { ASSERT(idle_cb_called == 0); ASSERT(timer_cb_called == 0); uv_idle_stop(handle); @@ -38,7 +38,7 @@ static void idle_cb(uv_idle_t* handle, int status) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(idle_cb_called == 1); ASSERT(timer_cb_called == 0); uv_timer_stop(handle); @@ -46,7 +46,7 @@ static void timer_cb(uv_timer_t* handle, int status) { } -static void next_tick(uv_idle_t* handle, int status) { +static void next_tick(uv_idle_t* handle) { uv_loop_t* loop = handle->loop; uv_idle_stop(handle); uv_idle_init(loop, &idle_handle); diff --git a/deps/uv/test/test-callback-stack.c b/deps/uv/test/test-callback-stack.c index accd549697..8855c0841b 100644 --- a/deps/uv/test/test-callback-stack.c +++ b/deps/uv/test/test-callback-stack.c @@ -105,9 +105,8 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer); - ASSERT(status == 0); ASSERT(nested == 0 && "timer_cb must be called from a fresh stack"); puts("Timeout complete. Now read data..."); diff --git a/deps/uv/test/test-close-order.c b/deps/uv/test/test-close-order.c index e2f25f987d..2b24f6d657 100644 --- a/deps/uv/test/test-close-order.c +++ b/deps/uv/test/test-close-order.c @@ -38,7 +38,7 @@ static void close_cb(uv_handle_t* handle) { /* check_cb should run before any close_cb */ -static void check_cb(uv_check_t* handle, int status) { +static void check_cb(uv_check_t* handle) { ASSERT(check_cb_called == 0); ASSERT(timer_cb_called == 1); ASSERT(close_cb_called == 0); @@ -48,7 +48,7 @@ static void check_cb(uv_check_t* handle, int status) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { uv_close((uv_handle_t*) handle, close_cb); timer_cb_called++; } diff --git a/deps/uv/test/test-connection-fail.c b/deps/uv/test/test-connection-fail.c index 5700140130..328bff46e7 100644 --- a/deps/uv/test/test-connection-fail.c +++ b/deps/uv/test/test-connection-fail.c @@ -46,8 +46,7 @@ static void timer_close_cb(uv_handle_t* handle) { } -static void timer_cb(uv_timer_t* handle, int status) { - ASSERT(status == 0); +static void timer_cb(uv_timer_t* handle) { timer_cb_calls++; /* diff --git a/deps/uv/test/test-delayed-accept.c b/deps/uv/test/test-delayed-accept.c index b45100d625..4a7998909c 100644 --- a/deps/uv/test/test-delayed-accept.c +++ b/deps/uv/test/test-delayed-accept.c @@ -45,13 +45,12 @@ static void close_cb(uv_handle_t* handle) { } -static void do_accept(uv_timer_t* timer_handle, int status) { +static void do_accept(uv_timer_t* timer_handle) { uv_tcp_t* server; uv_tcp_t* accepted_handle = (uv_tcp_t*)malloc(sizeof *accepted_handle); int r; ASSERT(timer_handle != NULL); - ASSERT(status == 0); ASSERT(accepted_handle != NULL); r = uv_tcp_init(uv_default_loop(), accepted_handle); diff --git a/deps/uv/test/test-embed.c b/deps/uv/test/test-embed.c index 909d2d5d99..06137456f8 100644 --- a/deps/uv/test/test-embed.c +++ b/deps/uv/test/test-embed.c @@ -90,14 +90,14 @@ static void embed_thread_runner(void* arg) { } -static void embed_cb(uv_async_t* async, int status) { +static void embed_cb(uv_async_t* async) { uv_run(uv_default_loop(), UV_RUN_ONCE); uv_sem_post(&embed_sem); } -static void embed_timer_cb(uv_timer_t* timer, int status) { +static void embed_timer_cb(uv_timer_t* timer) { embed_timer_called++; embed_closed = 1; diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index fec5fd6731..5fd8da430b 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -50,7 +50,7 @@ static char fs_event_filename[1024]; #endif /* defined(PATH_MAX) */ static int timer_cb_touch_called; -static void fs_event_unlink_files(uv_timer_t* handle, int status); +static void fs_event_unlink_files(uv_timer_t* handle); static void create_dir(uv_loop_t* loop, const char* name) { int r; @@ -147,7 +147,7 @@ static const char* fs_event_get_filename(int i) { return fs_event_filename; } -static void fs_event_create_files(uv_timer_t* handle, int status) { +static void fs_event_create_files(uv_timer_t* handle) { int i; /* Already created all files */ @@ -164,7 +164,7 @@ static void fs_event_create_files(uv_timer_t* handle, int status) { ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 50, 0)); } -void fs_event_unlink_files(uv_timer_t* handle, int status) { +void fs_event_unlink_files(uv_timer_t* handle) { int r; int i; @@ -193,11 +193,10 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename, uv_close((uv_handle_t*)handle, close_cb); } -static void timer_cb_close_handle(uv_timer_t* timer, int status) { +static void timer_cb_close_handle(uv_timer_t* timer) { uv_handle_t* handle; ASSERT(timer != NULL); - ASSERT(status == 0); handle = timer->data; uv_close((uv_handle_t*)timer, NULL); @@ -223,7 +222,7 @@ static void fs_event_cb_file_current_dir(uv_fs_event_t* handle, } } -static void timer_cb_file(uv_timer_t* handle, int status) { +static void timer_cb_file(uv_timer_t* handle) { ++timer_cb_called; if (timer_cb_called == 1) { @@ -234,14 +233,13 @@ static void timer_cb_file(uv_timer_t* handle, int status) { } } -static void timer_cb_touch(uv_timer_t* timer, int status) { - ASSERT(status == 0); +static void timer_cb_touch(uv_timer_t* timer) { uv_close((uv_handle_t*)timer, NULL); touch_file(timer->loop, "watch_file"); timer_cb_touch_called++; } -static void timer_cb_watch_twice(uv_timer_t* handle, int status) { +static void timer_cb_watch_twice(uv_timer_t* handle) { uv_fs_event_t* handles = handle->data; uv_close((uv_handle_t*) (handles + 0), NULL); uv_close((uv_handle_t*) (handles + 1), NULL); @@ -253,7 +251,7 @@ TEST_IMPL(fs_event_watch_dir) { int r; /* Setup */ - fs_event_unlink_files(NULL, 0); + fs_event_unlink_files(NULL); remove("watch_dir/file2"); remove("watch_dir/file1"); remove("watch_dir/"); @@ -275,7 +273,7 @@ TEST_IMPL(fs_event_watch_dir) { ASSERT(close_cb_called == 2); /* Cleanup */ - fs_event_unlink_files(NULL, 0); + fs_event_unlink_files(NULL); remove("watch_dir/file2"); remove("watch_dir/file1"); remove("watch_dir/"); @@ -458,11 +456,9 @@ static void fs_event_fail(uv_fs_event_t* handle, const char* filename, } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { int r; - ASSERT(status == 0); - r = uv_fs_event_init(handle->loop, &fs_event); ASSERT(r == 0); r = uv_fs_event_start(&fs_event, fs_event_fail, ".", 0); @@ -672,7 +668,7 @@ static void fs_event_error_report_cb(uv_fs_event_t* handle, fs_event_error_reported = status; } -static void timer_cb_nop(uv_timer_t* handle, int status) { +static void timer_cb_nop(uv_timer_t* handle) { ++timer_cb_called; uv_close((uv_handle_t*) handle, close_cb); } diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c index 27c6c3c3db..f4eb08408f 100644 --- a/deps/uv/test/test-fs-poll.c +++ b/deps/uv/test/test-fs-poll.c @@ -26,7 +26,7 @@ #define FIXTURE "testfile" -static void timer_cb(uv_timer_t* handle, int status); +static void timer_cb(uv_timer_t* handle); static void close_cb(uv_handle_t* handle); static void poll_cb(uv_fs_poll_t* handle, int status, @@ -71,7 +71,7 @@ static void close_cb(uv_handle_t* handle) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { touch_file(FIXTURE); timer_cb_called++; } diff --git a/deps/uv/test/test-idle.c b/deps/uv/test/test-idle.c index 7eea1b83b1..0e991c368c 100644 --- a/deps/uv/test/test-idle.c +++ b/deps/uv/test/test-idle.c @@ -38,9 +38,8 @@ static void close_cb(uv_handle_t* handle) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer_handle); - ASSERT(status == 0); uv_close((uv_handle_t*) &idle_handle, close_cb); uv_close((uv_handle_t*) &check_handle, close_cb); @@ -51,18 +50,16 @@ static void timer_cb(uv_timer_t* handle, int status) { } -static void idle_cb(uv_idle_t* handle, int status) { +static void idle_cb(uv_idle_t* handle) { ASSERT(handle == &idle_handle); - ASSERT(status == 0); idle_cb_called++; LOGF("idle_cb %d\n", idle_cb_called); } -static void check_cb(uv_check_t* handle, int status) { +static void check_cb(uv_check_t* handle) { ASSERT(handle == &check_handle); - ASSERT(status == 0); check_cb_called++; LOGF("check_cb %d\n", check_cb_called); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 345df51144..f44d9f96e9 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -79,10 +79,14 @@ TEST_DECLARE (tcp_bind6_error_addrnotavail) TEST_DECLARE (tcp_bind6_error_fault) TEST_DECLARE (tcp_bind6_error_inval) TEST_DECLARE (tcp_bind6_localhost_ok) +TEST_DECLARE (udp_bind) +TEST_DECLARE (udp_bind_reuseaddr) TEST_DECLARE (udp_send_and_recv) TEST_DECLARE (udp_multicast_join) +TEST_DECLARE (udp_multicast_join6) TEST_DECLARE (udp_multicast_ttl) TEST_DECLARE (udp_multicast_interface) +TEST_DECLARE (udp_multicast_interface6) TEST_DECLARE (udp_dgram_too_big) TEST_DECLARE (udp_dual_stack) TEST_DECLARE (udp_ipv6_only) @@ -176,6 +180,7 @@ TEST_DECLARE (spawn_setgid_fails) TEST_DECLARE (spawn_stdout_to_file) TEST_DECLARE (spawn_stdout_and_stderr_to_file) TEST_DECLARE (spawn_auto_unref) +TEST_DECLARE (spawn_closed_process_io) TEST_DECLARE (fs_poll) TEST_DECLARE (fs_poll_getpath) TEST_DECLARE (kill) @@ -346,12 +351,17 @@ TASK_LIST_START TEST_ENTRY (tcp_bind6_error_inval) TEST_ENTRY (tcp_bind6_localhost_ok) + TEST_ENTRY (udp_bind) + TEST_ENTRY (udp_bind_reuseaddr) TEST_ENTRY (udp_send_and_recv) TEST_ENTRY (udp_dgram_too_big) TEST_ENTRY (udp_dual_stack) TEST_ENTRY (udp_ipv6_only) TEST_ENTRY (udp_options) + TEST_ENTRY (udp_multicast_interface) + TEST_ENTRY (udp_multicast_interface6) TEST_ENTRY (udp_multicast_join) + TEST_ENTRY (udp_multicast_join6) TEST_ENTRY (udp_multicast_ttl) TEST_ENTRY (udp_open) @@ -478,6 +488,7 @@ TASK_LIST_START TEST_ENTRY (spawn_stdout_to_file) TEST_ENTRY (spawn_stdout_and_stderr_to_file) TEST_ENTRY (spawn_auto_unref) + TEST_ENTRY (spawn_closed_process_io) TEST_ENTRY (fs_poll) TEST_ENTRY (fs_poll_getpath) TEST_ENTRY (kill) diff --git a/deps/uv/test/test-loop-alive.c b/deps/uv/test/test-loop-alive.c index 89243357c3..cf4d301930 100644 --- a/deps/uv/test/test-loop-alive.c +++ b/deps/uv/test/test-loop-alive.c @@ -24,9 +24,8 @@ static uv_timer_t timer_handle; -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle); - ASSERT(status == 0); } diff --git a/deps/uv/test/test-loop-close.c b/deps/uv/test/test-loop-close.c index fa053469b8..5aec234ed0 100644 --- a/deps/uv/test/test-loop-close.c +++ b/deps/uv/test/test-loop-close.c @@ -24,9 +24,8 @@ static uv_timer_t timer_handle; -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle); - ASSERT(status == 0); uv_stop(handle->loop); } diff --git a/deps/uv/test/test-loop-handles.c b/deps/uv/test/test-loop-handles.c index fdf9281478..0986de5298 100644 --- a/deps/uv/test/test-loop-handles.c +++ b/deps/uv/test/test-loop-handles.c @@ -107,9 +107,8 @@ static int idle_2_cb_started = 0; static int idle_2_is_active = 0; -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer_handle); - ASSERT(status == 0); } @@ -125,11 +124,10 @@ static void idle_2_close_cb(uv_handle_t* handle) { } -static void idle_2_cb(uv_idle_t* handle, int status) { +static void idle_2_cb(uv_idle_t* handle) { LOG("IDLE_2_CB\n"); ASSERT(handle == &idle_2_handle); - ASSERT(status == 0); idle_2_cb_called++; @@ -137,14 +135,12 @@ static void idle_2_cb(uv_idle_t* handle, int status) { } -static void idle_1_cb(uv_idle_t* handle, int status) { +static void idle_1_cb(uv_idle_t* handle) { int r; LOG("IDLE_1_CB\n"); ASSERT(handle != NULL); - ASSERT(status == 0); - ASSERT(idles_1_active > 0); /* Init idle_2 and make it active */ @@ -200,13 +196,12 @@ static void prepare_2_close_cb(uv_handle_t* handle) { } -static void check_cb(uv_check_t* handle, int status) { +static void check_cb(uv_check_t* handle) { int i, r; LOG("CHECK_CB\n"); ASSERT(handle == &check_handle); - ASSERT(status == 0); if (loop_iteration < ITERATIONS) { /* Make some idle watchers active */ @@ -237,13 +232,12 @@ static void check_cb(uv_check_t* handle, int status) { } -static void prepare_2_cb(uv_prepare_t* handle, int status) { +static void prepare_2_cb(uv_prepare_t* handle) { int r; LOG("PREPARE_2_CB\n"); ASSERT(handle == &prepare_2_handle); - ASSERT(status == 0); /* prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), */ /* and it stops itself immediately. A started watcher is not queued */ @@ -258,13 +252,12 @@ static void prepare_2_cb(uv_prepare_t* handle, int status) { } -static void prepare_1_cb(uv_prepare_t* handle, int status) { +static void prepare_1_cb(uv_prepare_t* handle) { int r; LOG("PREPARE_1_CB\n"); ASSERT(handle == &prepare_1_handle); - ASSERT(status == 0); if (loop_iteration % 2 == 0) { r = uv_prepare_start(&prepare_2_handle, prepare_2_cb); diff --git a/deps/uv/test/test-loop-stop.c b/deps/uv/test/test-loop-stop.c index c519644ed2..14b8c11186 100644 --- a/deps/uv/test/test-loop-stop.c +++ b/deps/uv/test/test-loop-stop.c @@ -29,18 +29,16 @@ static int timer_called = 0; static int num_ticks = 10; -static void prepare_cb(uv_prepare_t* handle, int status) { +static void prepare_cb(uv_prepare_t* handle) { ASSERT(handle == &prepare_handle); - ASSERT(status == 0); prepare_called++; if (prepare_called == num_ticks) uv_prepare_stop(handle); } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer_handle); - ASSERT(status == 0); timer_called++; if (timer_called == 1) uv_stop(uv_default_loop()); diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index 0736b9b0bf..4658762379 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -61,7 +61,7 @@ typedef struct server_context_s { } server_context_t; -static void delay_timer_cb(uv_timer_t* timer, int status); +static void delay_timer_cb(uv_timer_t* timer); static test_mode_t test_mode = DUPLEX; @@ -413,7 +413,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { } -static void delay_timer_cb(uv_timer_t* timer, int status) { +static void delay_timer_cb(uv_timer_t* timer) { connection_context_t* context = (connection_context_t*) timer->data; int r; diff --git a/deps/uv/test/test-ref.c b/deps/uv/test/test-ref.c index 7ff2e84e38..ddaa173808 100644 --- a/deps/uv/test/test-ref.c +++ b/deps/uv/test/test-ref.c @@ -153,9 +153,8 @@ TEST_IMPL(check_ref) { } -static void prepare_cb(uv_prepare_t* h, int status) { +static void prepare_cb(uv_prepare_t* h) { ASSERT(h != NULL); - ASSERT(status == 0); uv_unref((uv_handle_t*)h); } diff --git a/deps/uv/test/test-run-nowait.c b/deps/uv/test/test-run-nowait.c index ee4b36ff3b..43524f636d 100644 --- a/deps/uv/test/test-run-nowait.c +++ b/deps/uv/test/test-run-nowait.c @@ -26,9 +26,8 @@ static uv_timer_t timer_handle; static int timer_called = 0; -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer_handle); - ASSERT(status == 0); timer_called = 1; } diff --git a/deps/uv/test/test-run-once.c b/deps/uv/test/test-run-once.c index e243de0ade..10cbf95e4a 100644 --- a/deps/uv/test/test-run-once.c +++ b/deps/uv/test/test-run-once.c @@ -28,9 +28,8 @@ static uv_idle_t idle_handle; static int idle_counter; -static void idle_cb(uv_idle_t* handle, int status) { +static void idle_cb(uv_idle_t* handle) { ASSERT(handle == &idle_handle); - ASSERT(status == 0); if (++idle_counter == NUM_TICKS) uv_idle_stop(handle); diff --git a/deps/uv/test/test-shutdown-eof.c b/deps/uv/test/test-shutdown-eof.c index 58346361c7..9f95e7561f 100644 --- a/deps/uv/test/test-shutdown-eof.c +++ b/deps/uv/test/test-shutdown-eof.c @@ -123,7 +123,7 @@ static void timer_close_cb(uv_handle_t* handle) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer); uv_close((uv_handle_t*) handle, timer_close_cb); diff --git a/deps/uv/test/test-signal.c b/deps/uv/test/test-signal.c index 9fb1c7f916..fcdd8e4d2d 100644 --- a/deps/uv/test/test-signal.c +++ b/deps/uv/test/test-signal.c @@ -65,7 +65,7 @@ static void signal_cb(uv_signal_t* handle, int signum) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { struct timer_ctx* ctx = container_of(handle, struct timer_ctx, handle); raise(ctx->signum); diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 84dd200175..a3856d1c8e 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -26,8 +26,13 @@ #include <stdlib.h> #include <string.h> -#ifndef _WIN32 -#include <unistd.h> +#ifdef _WIN32 +# if defined(__MINGW32__) +# include <basetyps.h> +# endif +# include <shellapi.h> +#else +# include <unistd.h> #endif @@ -146,13 +151,13 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { uv_process_kill(&process, /* SIGTERM */ 15); uv_close((uv_handle_t*)handle, close_cb); } -static void timer_counter_cb(uv_timer_t* handle, int status) { +static void timer_counter_cb(uv_timer_t* handle) { ++timer_counter; } @@ -680,6 +685,38 @@ TEST_IMPL(spawn_same_stdout_stderr) { } +TEST_IMPL(spawn_closed_process_io) { + uv_pipe_t in; + uv_write_t write_req; + uv_buf_t buf; + uv_stdio_container_t stdio[2]; + static char buffer[] = "hello-from-spawn_stdin"; + + init_process_options("spawn_helper1", exit_cb); + + uv_pipe_init(uv_default_loop(), &in, 0); + options.stdio = stdio; + options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; + options.stdio[0].data.stream = (uv_stream_t*) ∈ + options.stdio_count = 1; + + close(0); /* Close process stdin. */ + + ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); + + buf = uv_buf_init(buffer, sizeof(buffer)); + ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb)); + + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 2); /* process, child stdin */ + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(kill) { int r; diff --git a/deps/uv/test/test-tcp-close-while-connecting.c b/deps/uv/test/test-tcp-close-while-connecting.c index b9f7f9661c..0a69a0ddee 100644 --- a/deps/uv/test/test-tcp-close-while-connecting.c +++ b/deps/uv/test/test-tcp-close-while-connecting.c @@ -43,14 +43,14 @@ static void connect_cb(uv_connect_t* req, int status) { } -static void timer1_cb(uv_timer_t* handle, int status) { +static void timer1_cb(uv_timer_t* handle) { uv_close((uv_handle_t*)handle, close_cb); uv_close((uv_handle_t*)&tcp_handle, close_cb); timer1_cb_called++; } -static void timer2_cb(uv_timer_t* handle, int status) { +static void timer2_cb(uv_timer_t* handle) { ASSERT(0 && "should not be called"); } diff --git a/deps/uv/test/test-tcp-connect-timeout.c b/deps/uv/test/test-tcp-connect-timeout.c index cc583cafb2..a22c773c6d 100644 --- a/deps/uv/test/test-tcp-connect-timeout.c +++ b/deps/uv/test/test-tcp-connect-timeout.c @@ -33,7 +33,7 @@ static uv_timer_t timer; static uv_tcp_t conn; static void connect_cb(uv_connect_t* req, int status); -static void timer_cb(uv_timer_t* handle, int status); +static void timer_cb(uv_timer_t* handle); static void close_cb(uv_handle_t* handle); @@ -44,7 +44,7 @@ static void connect_cb(uv_connect_t* req, int status) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer); uv_close((uv_handle_t*)&conn, close_cb); uv_close((uv_handle_t*)&timer, close_cb); diff --git a/deps/uv/test/test-tcp-read-stop.c b/deps/uv/test/test-tcp-read-stop.c index c8d9c0407e..488e8fb49a 100644 --- a/deps/uv/test/test-tcp-read-stop.c +++ b/deps/uv/test/test-tcp-read-stop.c @@ -38,7 +38,7 @@ static void write_cb(uv_write_t* req, int status) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { uv_buf_t buf = uv_buf_init("PING", 4); ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &tcp_handle, diff --git a/deps/uv/test/test-tcp-shutdown-after-write.c b/deps/uv/test/test-tcp-shutdown-after-write.c index c59acc4020..463b4b0d79 100644 --- a/deps/uv/test/test-tcp-shutdown-after-write.c +++ b/deps/uv/test/test-tcp-shutdown-after-write.c @@ -58,7 +58,7 @@ static void alloc_cb(uv_handle_t* handle, } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { uv_buf_t buf; int r; diff --git a/deps/uv/test/test-tcp-unexpected-read.c b/deps/uv/test/test-tcp-unexpected-read.c index 11fee8ba8e..c7b981456b 100644 --- a/deps/uv/test/test-tcp-unexpected-read.c +++ b/deps/uv/test/test-tcp-unexpected-read.c @@ -33,12 +33,12 @@ static uv_connect_t connect_req; static unsigned long ticks; /* event loop ticks */ -static void check_cb(uv_check_t* handle, int status) { +static void check_cb(uv_check_t* handle) { ticks++; } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { uv_close((uv_handle_t*) &check_handle, NULL); uv_close((uv_handle_t*) &timer_handle, NULL); uv_close((uv_handle_t*) &server_handle, NULL); diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index c3186ea5df..3f5164378f 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -138,7 +138,7 @@ static void done2_cb(uv_work_t* req, int status) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { struct cancel_info* ci; uv_req_t* req; unsigned i; diff --git a/deps/uv/test/test-timer-again.c b/deps/uv/test/test-timer-again.c index 1638da2dfc..095cd9e707 100644 --- a/deps/uv/test/test-timer-again.c +++ b/deps/uv/test/test-timer-again.c @@ -41,12 +41,10 @@ static void close_cb(uv_handle_t* handle) { } -static void repeat_1_cb(uv_timer_t* handle, int status) { +static void repeat_1_cb(uv_timer_t* handle) { int r; ASSERT(handle == &repeat_1); - ASSERT(status == 0); - ASSERT(uv_timer_get_repeat((uv_timer_t*)handle) == 50); LOGF("repeat_1_cb called after %ld ms\n", @@ -67,9 +65,8 @@ static void repeat_1_cb(uv_timer_t* handle, int status) { } -static void repeat_2_cb(uv_timer_t* handle, int status) { +static void repeat_2_cb(uv_timer_t* handle) { ASSERT(handle == &repeat_2); - ASSERT(status == 0); ASSERT(repeat_2_cb_allowed); LOGF("repeat_2_cb called after %ld ms\n", diff --git a/deps/uv/test/test-timer-from-check.c b/deps/uv/test/test-timer-from-check.c index 2aa3fe4119..a18c7e1fb9 100644 --- a/deps/uv/test/test-timer-from-check.c +++ b/deps/uv/test/test-timer-from-check.c @@ -31,7 +31,7 @@ static int check_cb_called; static int timer_cb_called; -static void prepare_cb(uv_prepare_t* handle, int status) { +static void prepare_cb(uv_prepare_t* handle) { ASSERT(0 == uv_prepare_stop(&prepare_handle)); ASSERT(0 == prepare_cb_called); ASSERT(1 == check_cb_called); @@ -40,7 +40,7 @@ static void prepare_cb(uv_prepare_t* handle, int status) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(0 == uv_timer_stop(&timer_handle)); ASSERT(1 == prepare_cb_called); ASSERT(1 == check_cb_called); @@ -49,7 +49,7 @@ static void timer_cb(uv_timer_t* handle, int status) { } -static void check_cb(uv_check_t* handle, int status) { +static void check_cb(uv_check_t* handle) { ASSERT(0 == uv_check_stop(&check_handle)); ASSERT(0 == uv_timer_stop(&timer_handle)); /* Runs before timer_cb. */ ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0)); diff --git a/deps/uv/test/test-timer.c b/deps/uv/test/test-timer.c index bbe69f68be..f26dae577f 100644 --- a/deps/uv/test/test-timer.c +++ b/deps/uv/test/test-timer.c @@ -44,11 +44,10 @@ static void once_close_cb(uv_handle_t* handle) { } -static void once_cb(uv_timer_t* handle, int status) { +static void once_cb(uv_timer_t* handle) { printf("ONCE_CB %d\n", once_cb_called); ASSERT(handle != NULL); - ASSERT(status == 0); ASSERT(0 == uv_is_active((uv_handle_t*) handle)); once_cb_called++; @@ -69,11 +68,10 @@ static void repeat_close_cb(uv_handle_t* handle) { } -static void repeat_cb(uv_timer_t* handle, int status) { +static void repeat_cb(uv_timer_t* handle) { printf("REPEAT_CB\n"); ASSERT(handle != NULL); - ASSERT(status == 0); ASSERT(1 == uv_is_active((uv_handle_t*) handle)); repeat_cb_called++; @@ -84,7 +82,7 @@ static void repeat_cb(uv_timer_t* handle, int status) { } -static void never_cb(uv_timer_t* handle, int status) { +static void never_cb(uv_timer_t* handle) { FATAL("never_cb should never be called"); } @@ -170,12 +168,12 @@ TEST_IMPL(timer_init) { } -static void order_cb_a(uv_timer_t *handle, int status) { +static void order_cb_a(uv_timer_t *handle) { ASSERT(order_cb_called++ == *(int*)handle->data); } -static void order_cb_b(uv_timer_t *handle, int status) { +static void order_cb_b(uv_timer_t *handle) { ASSERT(order_cb_called++ == *(int*)handle->data); } @@ -219,7 +217,7 @@ TEST_IMPL(timer_order) { } -static void tiny_timer_cb(uv_timer_t* handle, int status) { +static void tiny_timer_cb(uv_timer_t* handle) { ASSERT(handle == &tiny_timer); uv_close((uv_handle_t*) &tiny_timer, NULL); uv_close((uv_handle_t*) &huge_timer1, NULL); @@ -240,7 +238,7 @@ TEST_IMPL(timer_huge_timeout) { } -static void huge_repeat_cb(uv_timer_t* handle, int status) { +static void huge_repeat_cb(uv_timer_t* handle) { static int ncalls; if (ncalls == 0) @@ -269,7 +267,7 @@ TEST_IMPL(timer_huge_repeat) { static unsigned int timer_run_once_timer_cb_called; -static void timer_run_once_timer_cb(uv_timer_t* handle, int status) { +static void timer_run_once_timer_cb(uv_timer_t* handle) { timer_run_once_timer_cb_called++; } diff --git a/deps/uv/test/test-udp-bind.c b/deps/uv/test/test-udp-bind.c new file mode 100644 index 0000000000..a1e080ee70 --- /dev/null +++ b/deps/uv/test/test-udp-bind.c @@ -0,0 +1,93 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + + +TEST_IMPL(udp_bind) { + struct sockaddr_in addr; + uv_loop_t* loop; + uv_udp_t h1, h2; + int r; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + + loop = uv_default_loop(); + + r = uv_udp_init(loop, &h1); + ASSERT(r == 0); + + r = uv_udp_init(loop, &h2); + ASSERT(r == 0); + + r = uv_udp_bind(&h1, (const struct sockaddr*) &addr, 0); + ASSERT(r == 0); + + r = uv_udp_bind(&h2, (const struct sockaddr*) &addr, 0); + ASSERT(r == UV_EADDRINUSE); + + uv_close((uv_handle_t*) &h1, NULL); + uv_close((uv_handle_t*) &h2, NULL); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(udp_bind_reuseaddr) { + struct sockaddr_in addr; + uv_loop_t* loop; + uv_udp_t h1, h2; + int r; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + + loop = uv_default_loop(); + + r = uv_udp_init(loop, &h1); + ASSERT(r == 0); + + r = uv_udp_init(loop, &h2); + ASSERT(r == 0); + + r = uv_udp_bind(&h1, (const struct sockaddr*) &addr, UV_UDP_REUSEADDR); + ASSERT(r == 0); + + r = uv_udp_bind(&h2, (const struct sockaddr*) &addr, UV_UDP_REUSEADDR); + ASSERT(r == 0); + + uv_close((uv_handle_t*) &h1, NULL); + uv_close((uv_handle_t*) &h2, NULL); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-udp-ipv6.c b/deps/uv/test/test-udp-ipv6.c index 32cabf097c..0e2fe2dcf2 100644 --- a/deps/uv/test/test-udp-ipv6.c +++ b/deps/uv/test/test-udp-ipv6.c @@ -90,7 +90,7 @@ static void ipv6_recv_ok(uv_udp_t* handle, } -static void timeout_cb(uv_timer_t* timer, int status) { +static void timeout_cb(uv_timer_t* timer) { uv_close((uv_handle_t*)&server, close_cb); uv_close((uv_handle_t*)&client, close_cb); uv_close((uv_handle_t*)&timeout, close_cb); diff --git a/deps/uv/test/test-udp-multicast-interface6.c b/deps/uv/test/test-udp-multicast-interface6.c new file mode 100644 index 0000000000..e58d771197 --- /dev/null +++ b/deps/uv/test/test-udp-multicast-interface6.c @@ -0,0 +1,100 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define CHECK_HANDLE(handle) \ + ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) + +static uv_udp_t server; +static uv_udp_t client; + +static int sv_send_cb_called; +static int close_cb_called; + + +static void close_cb(uv_handle_t* handle) { + CHECK_HANDLE(handle); + close_cb_called++; +} + + +static void sv_send_cb(uv_udp_send_t* req, int status) { + ASSERT(req != NULL); + ASSERT(status == 0); + CHECK_HANDLE(req->handle); + + sv_send_cb_called++; + + uv_close((uv_handle_t*) req->handle, close_cb); +} + + +TEST_IMPL(udp_multicast_interface6) { + int r; + uv_udp_send_t req; + uv_buf_t buf; + struct sockaddr_in6 addr; + struct sockaddr_in6 baddr; + + ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); + + r = uv_udp_init(uv_default_loop(), &server); + ASSERT(r == 0); + + ASSERT(0 == uv_ip6_addr("::", 0, &baddr)); + r = uv_udp_bind(&server, (const struct sockaddr*)&baddr, 0); + ASSERT(r == 0); + +#if defined(__APPLE__) + r = uv_udp_set_multicast_interface(&server, "::1%lo0"); +#else + r = uv_udp_set_multicast_interface(&server, NULL); +#endif + ASSERT(r == 0); + + /* server sends "PING" */ + buf = uv_buf_init("PING", 4); + r = uv_udp_send(&req, + &server, + &buf, + 1, + (const struct sockaddr*)&addr, + sv_send_cb); + ASSERT(r == 0); + + ASSERT(close_cb_called == 0); + ASSERT(sv_send_cb_called == 0); + + /* run the loop till all events are processed */ + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT(sv_send_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c new file mode 100644 index 0000000000..babf61e2bf --- /dev/null +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -0,0 +1,153 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#define CHECK_HANDLE(handle) \ + ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) + +static uv_udp_t server; +static uv_udp_t client; + +static int cl_recv_cb_called; + +static int sv_send_cb_called; + +static int close_cb_called; + +static void alloc_cb(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + static char slab[65536]; + CHECK_HANDLE(handle); + ASSERT(suggested_size <= sizeof(slab)); + buf->base = slab; + buf->len = sizeof(slab); +} + + +static void close_cb(uv_handle_t* handle) { + CHECK_HANDLE(handle); + close_cb_called++; +} + + +static void sv_send_cb(uv_udp_send_t* req, int status) { + ASSERT(req != NULL); + ASSERT(status == 0); + CHECK_HANDLE(req->handle); + + sv_send_cb_called++; + + uv_close((uv_handle_t*) req->handle, close_cb); +} + + +static void cl_recv_cb(uv_udp_t* handle, + ssize_t nread, + const uv_buf_t* buf, + const struct sockaddr* addr, + unsigned flags) { + CHECK_HANDLE(handle); + ASSERT(flags == 0); + + cl_recv_cb_called++; + + if (nread < 0) { + ASSERT(0 && "unexpected error"); + } + + if (nread == 0) { + /* Returning unused buffer */ + /* Don't count towards cl_recv_cb_called */ + ASSERT(addr == NULL); + return; + } + + ASSERT(addr != NULL); + ASSERT(nread == 4); + ASSERT(!memcmp("PING", buf->base, nread)); + + /* we are done with the client handle, we can close it */ + uv_close((uv_handle_t*) &client, close_cb); +} + + +TEST_IMPL(udp_multicast_join6) { + int r; + uv_udp_send_t req; + uv_buf_t buf; + struct sockaddr_in6 addr; + + ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); + + r = uv_udp_init(uv_default_loop(), &server); + ASSERT(r == 0); + + r = uv_udp_init(uv_default_loop(), &client); + ASSERT(r == 0); + + /* bind to the desired port */ + r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); + ASSERT(r == 0); + + /* join the multicast channel */ +#if defined(__APPLE__) + r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); +#else + r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); +#endif + ASSERT(r == 0); + + r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb); + ASSERT(r == 0); + + buf = uv_buf_init("PING", 4); + + /* server sends "PING" */ + r = uv_udp_send(&req, + &server, + &buf, + 1, + (const struct sockaddr*) &addr, + sv_send_cb); + ASSERT(r == 0); + + ASSERT(close_cb_called == 0); + ASSERT(cl_recv_cb_called == 0); + ASSERT(sv_send_cb_called == 0); + + /* run the loop till all events are processed */ + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT(cl_recv_cb_called == 1); + ASSERT(sv_send_cb_called == 1); + ASSERT(close_cb_called == 2); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-walk-handles.c b/deps/uv/test/test-walk-handles.c index f2ae41564f..4b0ca6ebc5 100644 --- a/deps/uv/test/test-walk-handles.c +++ b/deps/uv/test/test-walk-handles.c @@ -41,9 +41,8 @@ static void walk_cb(uv_handle_t* handle, void* arg) { } -static void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle) { ASSERT(handle == &timer); - ASSERT(status == 0); uv_walk(handle->loop, walk_cb, magic_cookie); uv_close((uv_handle_t*)handle, NULL); diff --git a/deps/uv/test/test-watcher-cross-stop.c b/deps/uv/test/test-watcher-cross-stop.c index c701dd2f91..9284a1291f 100644 --- a/deps/uv/test/test-watcher-cross-stop.c +++ b/deps/uv/test/test-watcher-cross-stop.c @@ -73,7 +73,9 @@ TEST_IMPL(watcher_cross_stop) { for (i = 0; i < ARRAY_SIZE(sockets); i++) { ASSERT(0 == uv_udp_init(loop, &sockets[i])); - ASSERT(0 == uv_udp_bind(&sockets[i], (const struct sockaddr*) &addr, 0)); + ASSERT(0 == uv_udp_bind(&sockets[i], + (const struct sockaddr*) &addr, + UV_UDP_REUSEADDR)); ASSERT(0 == uv_udp_recv_start(&sockets[i], alloc_cb, recv_cb)); ASSERT(0 == uv_udp_send(&reqs[i], &sockets[i], diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index ddf303e44c..5425dd63a4 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -217,6 +217,7 @@ 'src/unix/linux-syscalls.c', 'src/unix/linux-syscalls.h', 'src/unix/pthread-fixes.c', + 'src/unix/android-ifaddrs.c' ], 'link_settings': { 'libraries': [ '-ldl' ], @@ -238,7 +239,6 @@ }, }], [ 'OS=="aix"', { - 'include_dirs': [ 'src/ares/config_aix' ], 'sources': [ 'src/unix/aix.c' ], 'defines': [ '_ALL_SOURCE', @@ -383,17 +383,20 @@ 'test/test-timer-from-check.c', 'test/test-timer.c', 'test/test-tty.c', + 'test/test-udp-bind.c', 'test/test-udp-dgram-too-big.c', 'test/test-udp-ipv6.c', 'test/test-udp-open.c', 'test/test-udp-options.c', 'test/test-udp-send-and-recv.c', 'test/test-udp-multicast-join.c', + 'test/test-udp-multicast-join6.c', 'test/test-dlerror.c', 'test/test-udp-multicast-ttl.c', 'test/test-ip4-addr.c', 'test/test-ip6-addr.c', 'test/test-udp-multicast-interface.c', + 'test/test-udp-multicast-interface6.c', ], 'conditions': [ [ 'OS=="win"', { |