summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-09-09 13:08:37 -0400
committerRich Trott <rtrott@gmail.com>2019-09-12 00:49:02 -0700
commitdf0e2e3625d1f72e8b04e05ffa13997a51e9f0d7 (patch)
tree5ef978de762b47bcfc6323c48e7e22b862d6d657 /deps/uv/src/unix
parent62e8cc5e61a36ebe1bd913983a452961aa1c9946 (diff)
downloadandroid-node-v8-df0e2e3625d1f72e8b04e05ffa13997a51e9f0d7.tar.gz
android-node-v8-df0e2e3625d1f72e8b04e05ffa13997a51e9f0d7.tar.bz2
android-node-v8-df0e2e3625d1f72e8b04e05ffa13997a51e9f0d7.zip
deps: upgrade to libuv 1.32.0
Notable changes: - `uv_tcp_close_reset()` has been added. - `uv_udp_set_source_membership()` has been added. - A double free in `uv_free_cpu_info()` on OpenBSD has been fixed. - Defined, but empty environment variables can now be read on Windows. - Several improvements to the cmake build process. - The `EILSEQ` error code is now mapped by libuv. PR-URL: https://github.com/nodejs/node/pull/29508 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Beth Griggs <Bethany.Griggs@uk.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps/uv/src/unix')
-rw-r--r--deps/uv/src/unix/aix-common.c10
-rw-r--r--deps/uv/src/unix/atomic-ops.h4
-rw-r--r--deps/uv/src/unix/core.c45
-rw-r--r--deps/uv/src/unix/cygwin.c5
-rw-r--r--deps/uv/src/unix/darwin.c11
-rw-r--r--deps/uv/src/unix/freebsd.c11
-rw-r--r--deps/uv/src/unix/fs.c17
-rw-r--r--deps/uv/src/unix/haiku.c9
-rw-r--r--deps/uv/src/unix/linux-core.c10
-rw-r--r--deps/uv/src/unix/netbsd.c11
-rw-r--r--deps/uv/src/unix/openbsd.c29
-rw-r--r--deps/uv/src/unix/os390.c7
-rw-r--r--deps/uv/src/unix/signal.c11
-rw-r--r--deps/uv/src/unix/stream.c8
-rw-r--r--deps/uv/src/unix/sunos.c10
-rw-r--r--deps/uv/src/unix/tcp.c17
-rw-r--r--deps/uv/src/unix/udp.c137
17 files changed, 203 insertions, 149 deletions
diff --git a/deps/uv/src/unix/aix-common.c b/deps/uv/src/unix/aix-common.c
index 63ac16a034..b9d313c0c5 100644
--- a/deps/uv/src/unix/aix-common.c
+++ b/deps/uv/src/unix/aix-common.c
@@ -155,16 +155,6 @@ int uv_exepath(char* buffer, size_t* size) {
}
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; ++i) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h
index 541a6c8648..bc37c0d45d 100644
--- a/deps/uv/src/unix/atomic-ops.h
+++ b/deps/uv/src/unix/atomic-ops.h
@@ -36,10 +36,6 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
: "r" (newval), "0" (oldval)
: "memory");
return out;
-#elif defined(_AIX) && defined(__xlC__)
- const int out = (*(volatile int*) ptr);
- __compare_and_swap(ptr, &oldval, newval);
- return out;
#elif defined(__MVS__)
unsigned int op4;
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index f4b94e30cc..366c43c2ab 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -30,7 +30,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <fcntl.h> /* O_CLOEXEC */
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -49,17 +49,19 @@
# include <sys/wait.h>
#endif
-#ifdef __APPLE__
+#if defined(__APPLE__)
+# include <sys/filio.h>
+# endif /* defined(__APPLE__) */
+
+
+#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <crt_externs.h>
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
-# include <sys/filio.h>
-# if defined(O_CLOEXEC)
-# define UV__O_CLOEXEC O_CLOEXEC
-# endif
# define environ (*_NSGetEnviron())
-#else
+#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */
extern char** environ;
-#endif
+#endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */
+
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
@@ -68,7 +70,6 @@ extern char** environ;
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
-# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
# endif
@@ -1000,24 +1001,17 @@ int uv_getrusage(uv_rusage_t* rusage) {
int uv__open_cloexec(const char* path, int flags) {
- int err;
+#if defined(O_CLOEXEC)
int fd;
-#if defined(UV__O_CLOEXEC)
- static int no_cloexec;
-
- if (!no_cloexec) {
- fd = open(path, flags | UV__O_CLOEXEC);
- if (fd != -1)
- return fd;
-
- if (errno != EINVAL)
- return UV__ERR(errno);
+ fd = open(path, flags | O_CLOEXEC);
+ if (fd == -1)
+ return UV__ERR(errno);
- /* O_CLOEXEC not supported. */
- no_cloexec = 1;
- }
-#endif
+ return fd;
+#else /* O_CLOEXEC */
+ int err;
+ int fd;
fd = open(path, flags);
if (fd == -1)
@@ -1030,6 +1024,7 @@ int uv__open_cloexec(const char* path, int flags) {
}
return fd;
+#endif /* O_CLOEXEC */
}
@@ -1051,7 +1046,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
static int no_dup3;
if (!no_dup3) {
do
- r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
+ r = uv__dup3(oldfd, newfd, O_CLOEXEC);
while (r == -1 && errno == EBUSY);
if (r != -1)
return r;
diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c
index 6b5cfb7ba5..169958d55f 100644
--- a/deps/uv/src/unix/cygwin.c
+++ b/deps/uv/src/unix/cygwin.c
@@ -48,11 +48,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return UV_ENOSYS;
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- (void)cpu_infos;
- (void)count;
-}
-
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c
index e4cd8ff7e0..5cf03aea0b 100644
--- a/deps/uv/src/unix/darwin.c
+++ b/deps/uv/src/unix/darwin.c
@@ -223,14 +223,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c
index 7de88d6a52..d0b7d8e9d1 100644
--- a/deps/uv/src/unix/freebsd.c
+++ b/deps/uv/src/unix/freebsd.c
@@ -288,14 +288,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv__free(cp_times);
return 0;
}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index fc80d00d5c..fd3dd4c287 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -255,20 +255,10 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
static ssize_t uv__fs_open(uv_fs_t* req) {
- static int no_cloexec_support;
- int r;
-
- /* Try O_CLOEXEC before entering locks */
- if (no_cloexec_support == 0) {
#ifdef O_CLOEXEC
- r = open(req->path, req->flags | O_CLOEXEC, req->mode);
- if (r >= 0)
- return r;
- if (errno != EINVAL)
- return r;
- no_cloexec_support = 1;
-#endif /* O_CLOEXEC */
- }
+ return open(req->path, req->flags | O_CLOEXEC, req->mode);
+#else /* O_CLOEXEC */
+ int r;
if (req->cb != NULL)
uv_rwlock_rdlock(&req->loop->cloexec_lock);
@@ -289,6 +279,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
return r;
+#endif /* O_CLOEXEC */
}
diff --git a/deps/uv/src/unix/haiku.c b/deps/uv/src/unix/haiku.c
index 7708851c2a..cf17d836b4 100644
--- a/deps/uv/src/unix/haiku.c
+++ b/deps/uv/src/unix/haiku.c
@@ -165,12 +165,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++)
- uv__free(cpu_infos[i].model);
-
- uv__free(cpu_infos);
-}
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index b539beb86a..433e201fe1 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -812,16 +812,6 @@ static uint64_t read_cpufreq(unsigned int cpunum) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c
index c649bb375f..cfe2c6a49d 100644
--- a/deps/uv/src/unix/netbsd.c
+++ b/deps/uv/src/unix/netbsd.c
@@ -234,14 +234,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv__free(cp_times);
return 0;
}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index b5cdc80c3e..1f5228dc13 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -202,14 +202,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
if (!(*cpu_infos))
return UV_ENOMEM;
+ i = 0;
*count = numcpus;
which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
- if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
- uv__free(*cpu_infos);
- return UV__ERR(errno);
- }
+ if (sysctl(which, 2, &cpuspeed, &size, NULL, 0))
+ goto error;
size = sizeof(info);
which[0] = CTL_KERN;
@@ -217,10 +216,8 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
for (i = 0; i < numcpus; i++) {
which[2] = i;
size = sizeof(info);
- if (sysctl(which, 3, &info, &size, NULL, 0)) {
- uv__free(*cpu_infos);
- return UV__ERR(errno);
- }
+ if (sysctl(which, 3, &info, &size, NULL, 0))
+ goto error;
cpu_info = &(*cpu_infos)[i];
@@ -235,15 +232,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
return 0;
-}
+error:
+ *count = 0;
+ for (j = 0; j < i; j++)
+ uv__free((*cpu_infos)[j].model);
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
+ uv__free(*cpu_infos);
+ *cpu_infos = NULL;
+ return UV__ERR(errno);
}
diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c
index 273ded7ca5..a7305006c1 100644
--- a/deps/uv/src/unix/os390.c
+++ b/deps/uv/src/unix/os390.c
@@ -433,13 +433,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- for (int i = 0; i < count; ++i)
- uv__free(cpu_infos[i].model);
- uv__free(cpu_infos);
-}
-
-
static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
int* count) {
uv_interface_address_t* address;
diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c
index 5e89ded2d8..3a257f04b5 100644
--- a/deps/uv/src/unix/signal.c
+++ b/deps/uv/src/unix/signal.c
@@ -477,9 +477,11 @@ static void uv__signal_event(uv_loop_t* loop,
* yet dispatched, the uv__finish_close was deferred. Make close pending
* now if this has happened.
*/
- if ((handle->flags & UV_HANDLE_CLOSING) &&
- (handle->caught_signals == handle->dispatched_signals)) {
- uv__make_close_pending((uv_handle_t*) handle);
+ if (handle->caught_signals == handle->dispatched_signals) {
+ if (handle->signum == 0)
+ uv__handle_stop(handle);
+ if (handle->flags & UV_HANDLE_CLOSING)
+ uv__make_close_pending((uv_handle_t*) handle);
}
}
@@ -569,5 +571,6 @@ static void uv__signal_stop(uv_signal_t* handle) {
uv__signal_unlock_and_unblock(&saved_sigmask);
handle->signum = 0;
- uv__handle_stop(handle);
+ if (handle->caught_signals == handle->dispatched_signals)
+ uv__handle_stop(handle);
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 9de01e3c78..78ce8e8487 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -1180,6 +1180,10 @@ static void uv__read(uv_stream_t* stream) {
} else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) {
uv__stream_eof(stream, &buf);
return;
+#elif defined(_AIX)
+ } else if (errno == ECONNRESET && (stream->flags & UV_DISCONNECT)) {
+ uv__stream_eof(stream, &buf);
+ return;
#endif
} else {
/* Error. User should call uv_close(). */
@@ -1403,7 +1407,7 @@ int uv_write2(uv_write_t* req,
return UV_EBADF;
if (!(stream->flags & UV_HANDLE_WRITABLE))
- return -EPIPE;
+ return UV_EPIPE;
if (send_handle) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
@@ -1557,7 +1561,7 @@ int uv_read_start(uv_stream_t* stream,
return UV_EINVAL;
if (!(stream->flags & UV_HANDLE_READABLE))
- return -ENOTCONN;
+ return UV_ENOTCONN;
/* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index f323d1defd..180cc84651 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -696,16 +696,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
#ifdef SUNOS_NO_IFADDRS
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
*count = 0;
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 8cedcd6027..fa660f1381 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -308,6 +308,23 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
}
+int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
+ int fd;
+ struct linger l = { 1, 0 };
+
+ /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
+ if (handle->flags & UV_HANDLE_SHUTTING)
+ return UV_EINVAL;
+
+ fd = uv__stream_fd(handle);
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
+ return UV__ERR(errno);
+
+ uv_close((uv_handle_t*) handle, close_cb);
+ return 0;
+}
+
+
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
static int single_accept = -1;
unsigned long flags;
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index b578e7bc10..dba8eff838 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -659,6 +659,98 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
}
+static int uv__udp_set_source_membership4(uv_udp_t* handle,
+ const struct sockaddr_in* multicast_addr,
+ const char* interface_addr,
+ const struct sockaddr_in* source_addr,
+ uv_membership membership) {
+ struct ip_mreq_source mreq;
+ int optname;
+ int err;
+
+ err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
+ if (err)
+ return err;
+
+ memset(&mreq, 0, sizeof(mreq));
+
+ if (interface_addr != NULL) {
+ 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);
+ }
+
+ mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
+ mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
+
+ if (membership == UV_JOIN_GROUP)
+ optname = IP_ADD_SOURCE_MEMBERSHIP;
+ else if (membership == UV_LEAVE_GROUP)
+ optname = IP_DROP_SOURCE_MEMBERSHIP;
+ else
+ return UV_EINVAL;
+
+ if (setsockopt(handle->io_watcher.fd,
+ IPPROTO_IP,
+ optname,
+ &mreq,
+ sizeof(mreq))) {
+ return UV__ERR(errno);
+ }
+
+ return 0;
+}
+
+
+static int uv__udp_set_source_membership6(uv_udp_t* handle,
+ const struct sockaddr_in6* multicast_addr,
+ const char* interface_addr,
+ const struct sockaddr_in6* source_addr,
+ uv_membership membership) {
+ struct group_source_req mreq;
+ struct sockaddr_in6 addr6;
+ int optname;
+ int err;
+
+ err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
+ if (err)
+ return err;
+
+ memset(&mreq, 0, sizeof(mreq));
+
+ if (interface_addr != NULL) {
+ err = uv_ip6_addr(interface_addr, 0, &addr6);
+ if (err)
+ return err;
+ mreq.gsr_interface = addr6.sin6_scope_id;
+ } else {
+ mreq.gsr_interface = 0;
+ }
+
+ memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group));
+ memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source));
+
+ if (membership == UV_JOIN_GROUP)
+ optname = MCAST_JOIN_SOURCE_GROUP;
+ else if (membership == UV_LEAVE_GROUP)
+ optname = MCAST_LEAVE_SOURCE_GROUP;
+ else
+ return UV_EINVAL;
+
+ if (setsockopt(handle->io_watcher.fd,
+ IPPROTO_IPV6,
+ optname,
+ &mreq,
+ sizeof(mreq))) {
+ return UV__ERR(errno);
+ }
+
+ return 0;
+}
+
+
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
int domain;
int err;
@@ -748,6 +840,51 @@ int uv_udp_set_membership(uv_udp_t* handle,
}
}
+
+int uv_udp_set_source_membership(uv_udp_t* handle,
+ const char* multicast_addr,
+ const char* interface_addr,
+ const char* source_addr,
+ uv_membership membership) {
+ int err;
+ struct sockaddr_storage mcast_addr;
+ struct sockaddr_in* mcast_addr4;
+ struct sockaddr_in6* mcast_addr6;
+ struct sockaddr_storage src_addr;
+ struct sockaddr_in* src_addr4;
+ struct sockaddr_in6* src_addr6;
+
+ mcast_addr4 = (struct sockaddr_in*)&mcast_addr;
+ mcast_addr6 = (struct sockaddr_in6*)&mcast_addr;
+ src_addr4 = (struct sockaddr_in*)&src_addr;
+ src_addr6 = (struct sockaddr_in6*)&src_addr;
+
+ err = uv_ip4_addr(multicast_addr, 0, mcast_addr4);
+ if (err) {
+ err = uv_ip6_addr(multicast_addr, 0, mcast_addr6);
+ if (err)
+ return err;
+ err = uv_ip6_addr(source_addr, 0, src_addr6);
+ if (err)
+ return err;
+ return uv__udp_set_source_membership6(handle,
+ mcast_addr6,
+ interface_addr,
+ src_addr6,
+ membership);
+ }
+
+ err = uv_ip4_addr(source_addr, 0, src_addr4);
+ if (err)
+ return err;
+ return uv__udp_set_source_membership4(handle,
+ mcast_addr4,
+ interface_addr,
+ src_addr4,
+ membership);
+}
+
+
static int uv__setsockopt(uv_udp_t* handle,
int option4,
int option6,