Permalink
Browse files

Merge remote-tracking branch 'ry/v0.6'

  • Loading branch information...
2 parents 812e410 + 4cfda74 commit 243cfcd078fea62662201d92d58f4923334ebc5a @isaacs isaacs committed Feb 1, 2012
Showing with 272 additions and 39 deletions.
  1. +2 −1 include/uv.h
  2. +1 −0 src/unix/error.c
  3. +0 −1 src/unix/pipe.c
  4. +42 −3 src/unix/udp.c
  5. +1 −1 src/win/fs.c
  6. +108 −31 src/win/udp.c
  7. +16 −0 test/test-fs.c
  8. +2 −0 test/test-list.h
  9. +1 −1 test/test-udp-multicast-join.c
  10. +85 −0 test/test-udp-options.c
  11. +1 −0 uv.gyp
  12. +13 −1 vcbuild.bat
View
@@ -116,7 +116,8 @@ typedef intptr_t ssize_t;
XX( 46, ESHUTDOWN, "") \
XX( 47, EEXIST, "file already exists") \
XX( 48, ESRCH, "no such process") \
- XX( 49, ENAMETOOLONG, "name too long")
+ XX( 49, ENAMETOOLONG, "name too long") \
+ XX( 50, EPERM, "operation not permitted")
#define UV_ERRNO_GEN(val, name, s) UV_##name = val,
View
@@ -59,6 +59,7 @@ void uv_fatal_error(const int errorno, const char* syscall) {
uv_err_code uv_translate_sys_error(int sys_errno) {
switch (sys_errno) {
case 0: return UV_OK;
+ case EPERM: return UV_EPERM;
case ENOSYS: return UV_ENOSYS;
case ENOTSOCK: return UV_ENOTSOCK;
case ENOENT: return UV_ENOENT;
View
@@ -251,7 +251,6 @@ void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) {
pipe = watcher->data;
assert(pipe->type == UV_NAMED_PIPE);
- assert(pipe->pipe_fname != NULL);
sockfd = uv__accept(pipe->fd, (struct sockaddr *)&saddr, sizeof saddr);
if (sockfd == -1) {
View
@@ -344,7 +344,15 @@ static int uv__bind(uv_udp_t* handle,
goto out;
}
-#ifdef SO_REUSEPORT /* Apple's version of SO_REUSEADDR... */
+ /* On the BSDs, SO_REUSEADDR lets you reuse an address that's in the TIME_WAIT
+ * state (i.e. was until recently tied to a socket) while SO_REUSEPORT lets
+ * multiple processes bind to the same address. Yes, it's something of a
+ * misnomer but then again, SO_REUSEADDR was already taken.
+ *
+ * None of the above applies to Linux: SO_REUSEADDR implies SO_REUSEPORT on
+ * Linux and hence it does not have SO_REUSEPORT at all.
+ */
+#ifdef SO_REUSEPORT
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof yes) == -1) {
uv__set_sys_error(handle->loop, errno);
@@ -531,14 +539,45 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
return 0; \
}
-X(multicast_loop, IPPROTO_IP, IP_MULTICAST_LOOP)
-X(multicast_ttl, IPPROTO_IP, IP_MULTICAST_TTL)
X(broadcast, SOL_SOCKET, SO_BROADCAST)
X(ttl, IPPROTO_IP, IP_TTL)
#undef X
+static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) {
+#if __sun
+ char arg = val;
+#else
+ int arg = val;
+#endif
+
+#if __sun
+ if (val < 0 || val > 255) {
+ uv__set_sys_error(handle->loop, EINVAL);
+ return -1;
+ }
+#endif
+
+ if (setsockopt(handle->fd, IPPROTO_IP, option, &arg, sizeof(arg))) {
+ uv__set_sys_error(handle->loop, errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
+ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, ttl);
+}
+
+
+int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
+ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, on);
+}
+
+
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) {
socklen_t socklen;
int saved_errno;
View
@@ -541,7 +541,7 @@ static int uv__is_root(const wchar_t* path) {
size_t len = wcslen(path);
/* Test for \ */
- if (len == 0 && IS_SLASH(path[0])) {
+ if (len == 1 && IS_SLASH(path[0])) {
return 1;
}
View
@@ -162,9 +162,9 @@ static int uv__bind(uv_udp_t* handle,
struct sockaddr* addr,
int addrsize,
unsigned int flags) {
- DWORD err;
int r;
SOCKET sock;
+ DWORD no = 0, yes = 1;
if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) {
/* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
@@ -186,7 +186,6 @@ static int uv__bind(uv_udp_t* handle,
}
if (domain == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
- DWORD off = 0;
/* On windows IPV6ONLY is on by default. */
/* If the user doesn't specify it libuv turns it off. */
@@ -196,14 +195,22 @@ static int uv__bind(uv_udp_t* handle,
setsockopt(sock,
IPPROTO_IPV6,
IPV6_V6ONLY,
- (const char*) &off,
- sizeof off);
+ (char*) &no,
+ sizeof no);
}
- r = bind(handle->socket, addr, addrsize);
+ r = setsockopt(sock,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (char*) &yes,
+ sizeof yes);
+ if (r == SOCKET_ERROR) {
+ uv__set_sys_error(handle->loop, WSAGetLastError());
+ return -1;
+ }
+ r = bind(handle->socket, addr, addrsize);
if (r == SOCKET_ERROR) {
- err = WSAGetLastError();
uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
}
@@ -240,15 +247,6 @@ int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr,
}
-int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
- const char* interface_addr, uv_membership membership) {
-
- /* not implemented yet */
- uv__set_artificial_error(handle->loop, UV_ENOSYS);
- return -1;
-}
-
-
static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
uv_req_t* req;
uv_buf_t buf;
@@ -575,35 +573,114 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
}
-int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
- uv__set_artificial_error(handle->loop, UV_ENOSYS);
- return -1;
-}
+int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
+ const char* interface_addr, uv_membership membership) {
+ int optname;
+ struct ip_mreq mreq;
+ /* If the socket is unbound, bind to inaddr_any. */
+ if (!(handle->flags & UV_HANDLE_BOUND) &&
+ uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) {
+ return -1;
+ }
-int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
- if (setsockopt(handle->socket, IPPROTO_IP, IP_MULTICAST_TTL,
- (const char*)&ttl, sizeof ttl) == -1) {
- uv__set_sys_error(handle->loop, WSAGetLastError());
+ if (handle->flags & UV_HANDLE_IPV6) {
+ uv__set_artificial_error(handle->loop, UV_ENOSYS);
+ return -1;
+ }
+
+ memset(&mreq, 0, sizeof mreq);
+
+ if (interface_addr) {
+ mreq.imr_interface.s_addr = inet_addr(interface_addr);
+ } else {
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ }
+
+ mreq.imr_multiaddr.s_addr = inet_addr(multicast_addr);
+
+ switch (membership) {
+ case UV_JOIN_GROUP:
+ optname = IP_ADD_MEMBERSHIP;
+ break;
+ case UV_LEAVE_GROUP:
+ optname = IP_DROP_MEMBERSHIP;
+ break;
+ default:
+ uv__set_artificial_error(handle->loop, UV_EFAULT);
+ return -1;
+ }
+
+ if (setsockopt(handle->socket,
+ IPPROTO_IP,
+ optname,
+ (char*) &mreq,
+ sizeof mreq) == SOCKET_ERROR) {
+ uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
}
return 0;
}
-int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
- if (setsockopt(handle->socket, SOL_SOCKET, SO_BROADCAST, (const char*)&on,
- sizeof on) == -1) {
- uv__set_sys_error(handle->loop, WSAGetLastError());
+int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
+ BOOL optval = (BOOL) value;
+
+ /* If the socket is unbound, bind to inaddr_any. */
+ if (!(handle->flags & UV_HANDLE_BOUND) &&
+ uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) {
return -1;
}
+ if (setsockopt(handle->socket,
+ SOL_SOCKET,
+ SO_BROADCAST,
+ (char*) &optval,
+ sizeof optval)) {
+ uv__set_sys_error(handle->loop, WSAGetLastError());
+ return -1;
+ }
return 0;
}
-int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
- uv__set_artificial_error(handle->loop, UV_ENOSYS);
- return -1;
-}
+#define SOCKOPT_SETTER(name, option4, option6) \
+ int uv_udp_set_##name(uv_udp_t* handle, int value) { \
+ DWORD optval = (DWORD) value; \
+ \
+ /* If the socket is unbound, bind to inaddr_any. */ \
+ if (!(handle->flags & UV_HANDLE_BOUND) && \
+ uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) { \
+ return -1; \
+ } \
+ \
+ if (!(handle->flags & UV_HANDLE_IPV6)) { \
+ /* Set IPv4 socket option */ \
+ if (setsockopt(handle->socket, \
+ IPPROTO_IP, \
+ option4, \
+ (char*) &optval, \
+ sizeof optval)) { \
+ uv__set_sys_error(handle->loop, WSAGetLastError()); \
+ return -1; \
+ } \
+ } else { \
+ /* Set IPv6 socket option */ \
+ if (setsockopt(handle->socket, \
+ IPPROTO_IPV6, \
+ option6, \
+ (char*) &optval, \
+ sizeof optval)) { \
+ uv__set_sys_error(handle->loop, WSAGetLastError()); \
+ return -1; \
+ } \
+ } \
+ return 0; \
+ }
+
+SOCKOPT_SETTER(multicast_loop, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP)
+SOCKOPT_SETTER(multicast_ttl, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS)
+SOCKOPT_SETTER(ttl, IP_TTL, IPV6_HOPLIMIT)
+
+#undef SOCKOPT_SETTER
View
@@ -184,6 +184,13 @@ static void chown_cb(uv_fs_t* req) {
uv_fs_req_cleanup(req);
}
+static void chown_root_cb(uv_fs_t* req) {
+ ASSERT(req->fs_type == UV_FS_CHOWN);
+ ASSERT(req->result == -1);
+ ASSERT(req->errorno == UV_EPERM);
+ chown_cb_count++;
+ uv_fs_req_cleanup(req);
+}
static void unlink_cb(uv_fs_t* req) {
ASSERT(req == &unlink_req);
@@ -1018,6 +1025,12 @@ TEST_IMPL(fs_chown) {
uv_run(loop);
ASSERT(chown_cb_count == 1);
+ /* chown to root (fail) */
+ chown_cb_count = 0;
+ r = uv_fs_chown(loop, &req, "test_file", 0, 0, chown_root_cb);
+ uv_run(loop);
+ ASSERT(chown_cb_count == 1);
+
/* async fchown */
r = uv_fs_fchown(loop, &req, file, -1, -1, fchown_cb);
ASSERT(r == 0);
@@ -1293,6 +1306,9 @@ TEST_IMPL(fs_stat_root) {
int r;
uv_loop_t* loop = uv_default_loop();
+ r = uv_fs_stat(loop, &stat_req, "\\", NULL);
+ ASSERT(r == 0);
+
r = uv_fs_stat(loop, &stat_req, "c:\\", NULL);
ASSERT(r == 0);
View
@@ -53,6 +53,7 @@ TEST_DECLARE (udp_multicast_join)
TEST_DECLARE (udp_dgram_too_big)
TEST_DECLARE (udp_dual_stack)
TEST_DECLARE (udp_ipv6_only)
+TEST_DECLARE (udp_options)
TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail)
TEST_DECLARE (pipe_bind_error_inval)
@@ -203,6 +204,7 @@ TASK_LIST_START
TEST_ENTRY (udp_dgram_too_big)
TEST_ENTRY (udp_dual_stack)
TEST_ENTRY (udp_ipv6_only)
+ TEST_ENTRY (udp_options)
TEST_ENTRY (udp_multicast_join)
TEST_ENTRY (pipe_bind_error_addrinuse)
@@ -99,7 +99,7 @@ TEST_IMPL(udp_multicast_join) {
int r;
uv_udp_send_t req;
uv_buf_t buf;
- struct sockaddr_in addr = uv_ip4_addr("239.255.0.1", TEST_PORT);
+ struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
r = uv_udp_init(uv_default_loop(), &server);
ASSERT(r == 0);
Oops, something went wrong.

0 comments on commit 243cfcd

Please sign in to comment.