diff --git a/include/uv.h b/include/uv.h index 4bf4d6fe6..4f96ad97e 100644 --- a/include/uv.h +++ b/include/uv.h @@ -890,8 +890,9 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); * 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, struct sockaddr_in addr, - unsigned flags); +UV_EXTERN int uv_udp_bind(uv_udp_t* handle, + const struct sockaddr_in* addr, + unsigned flags); /* * Bind to a IPv6 address and port. @@ -904,8 +905,9 @@ UV_EXTERN int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, * Returns: * 0 on success, or an error code < 0 on failure. */ -UV_EXTERN int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, - unsigned flags); +UV_EXTERN int uv_udp_bind6(uv_udp_t* handle, + const struct sockaddr_in6* addr, + unsigned flags); UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen); diff --git a/src/unix/udp.c b/src/unix/udp.c index c96afc0ce..6c7482882 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -305,11 +305,10 @@ static int uv__set_reuse(int fd) { } -static int uv__bind(uv_udp_t* handle, - int domain, - struct sockaddr* addr, - socklen_t len, - unsigned flags) { +int uv__udp_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags) { int err; int yes; int fd; @@ -322,12 +321,12 @@ static int uv__bind(uv_udp_t* handle, return -EINVAL; /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) + if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) return -EINVAL; fd = handle->io_watcher.fd; if (fd == -1) { - fd = uv__socket(domain, SOCK_DGRAM, 0); + fd = uv__socket(addr->sa_family, SOCK_DGRAM, 0); if (fd == -1) return -errno; handle->io_watcher.fd = fd; @@ -350,7 +349,7 @@ static int uv__bind(uv_udp_t* handle, #endif } - if (bind(fd, addr, len) == -1) { + if (bind(fd, addr, addrlen)) { err = -errno; goto out; } @@ -397,7 +396,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain) { abort(); } - return uv__bind(handle, domain, (struct sockaddr*)&taddr, addrlen, 0); + return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, 0); } @@ -452,24 +451,6 @@ int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { } -int uv__udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags) { - return uv__bind(handle, - AF_INET, - (struct sockaddr*)&addr, - sizeof addr, - flags); -} - - -int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags) { - return uv__bind(handle, - AF_INET6, - (struct sockaddr*)&addr, - sizeof addr, - flags); -} - - int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { int err; diff --git a/src/uv-common.c b/src/uv-common.c index 944ca64df..83ee12dc8 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -201,22 +201,28 @@ int uv_tcp_bind6(uv_tcp_t* handle, const struct sockaddr_in6* addr) { int uv_udp_bind(uv_udp_t* handle, - struct sockaddr_in addr, + const struct sockaddr_in* addr, unsigned int flags) { - if (handle->type != UV_UDP || addr.sin_family != AF_INET) - return UV_EINVAL; - else - return uv__udp_bind(handle, addr, flags); + if (handle->type == UV_UDP && addr->sin_family == AF_INET) { + return uv__udp_bind(handle, + (const struct sockaddr*) addr, + sizeof(*addr), + flags); + } + return UV_EINVAL; } int uv_udp_bind6(uv_udp_t* handle, - struct sockaddr_in6 addr, + const struct sockaddr_in6* addr, unsigned int flags) { - if (handle->type != UV_UDP || addr.sin6_family != AF_INET6) - return UV_EINVAL; - else - return uv__udp_bind6(handle, addr, flags); + if (handle->type == UV_UDP && addr->sin6_family == AF_INET6) { + return uv__udp_bind(handle, + (const struct sockaddr*) addr, + sizeof(*addr), + flags); + } + return UV_EINVAL; } diff --git a/src/uv-common.h b/src/uv-common.h index f1e88602c..b933b98a0 100644 --- a/src/uv-common.h +++ b/src/uv-common.h @@ -63,15 +63,17 @@ int uv__tcp_bind(uv_tcp_t* tcp, const struct sockaddr* addr, unsigned int addrlen); -int uv__udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags); -int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags); - int uv__tcp_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, unsigned int addrlen, uv_connect_cb cb); +int uv__udp_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags); + int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], diff --git a/src/win/udp.c b/src/win/udp.c index 0a5d0600d..c7c011591 100644 --- a/src/win/udp.c +++ b/src/win/udp.c @@ -167,37 +167,36 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { } -static int uv__bind(uv_udp_t* handle, - int family, - struct sockaddr* addr, - int addrsize, - unsigned int flags) { +static int uv_udp_try_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags) { int r; int err; DWORD no = 0; - if ((flags & UV_UDP_IPV6ONLY) && family != AF_INET6) { + if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) { /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ return ERROR_INVALID_PARAMETER; } if (handle->socket == INVALID_SOCKET) { - SOCKET sock = socket(family, SOCK_DGRAM, 0); + SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { return WSAGetLastError(); } - err = uv_udp_set_socket(handle->loop, handle, sock, family); + err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family); if (err) { closesocket(sock); return err; } - if (family == AF_INET6) + if (addr->sa_family == AF_INET6) handle->flags |= UV_HANDLE_IPV6; } - if (family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { + if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { /* On windows IPV6ONLY is on by default. */ /* If the user doesn't specify it libuv turns it off. */ @@ -211,7 +210,7 @@ static int uv__bind(uv_udp_t* handle, sizeof no); } - r = bind(handle->socket, addr, addrsize); + r = bind(handle->socket, addr, addrlen); if (r == SOCKET_ERROR) { return WSAGetLastError(); } @@ -222,36 +221,6 @@ static int uv__bind(uv_udp_t* handle, } -int uv__udp_bind(uv_udp_t* handle, - struct sockaddr_in addr, - unsigned int flags) { - int err; - - err = uv__bind(handle, - AF_INET, - (struct sockaddr*) &addr, - sizeof(addr), - flags); - - return uv_translate_sys_error(err); -} - - -int uv__udp_bind6(uv_udp_t* handle, - struct sockaddr_in6 addr, - unsigned int flags) { - int err; - - err = uv__bind(handle, - AF_INET6, - (struct sockaddr*) &addr, - sizeof(addr), - flags); - - return uv_translate_sys_error(err); -} - - static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { uv_req_t* req; uv_buf_t buf; @@ -355,7 +324,10 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, } if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_bind(handle, uv_addr_ip4_any_, 0); + err = uv_udp_try_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + 0); if (err) return err; } @@ -433,7 +405,10 @@ int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], int err; if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_bind(handle, uv_addr_ip4_any_, 0); + err = uv_udp_try_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + 0); if (err) return err; } @@ -453,7 +428,10 @@ int uv__udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], int err; if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_udp_bind6(handle, uv_addr_ip6_any_, 0); + err = uv_udp_try_bind(handle, + (const struct sockaddr*) &uv_addr_ip6_any_, + sizeof(uv_addr_ip6_any_), + 0); if (err) return err; } @@ -602,7 +580,10 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, /* If the socket is unbound, bind to inaddr_any. */ if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv__udp_bind(handle, uv_addr_ip4_any_, 0); + 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); } @@ -650,7 +631,10 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) { /* If the socket is unbound, bind to inaddr_any. */ if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv__udp_bind(handle, uv_addr_ip4_any_, 0); + 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); } @@ -701,7 +685,10 @@ 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_bind(handle, uv_addr_ip4_any_, 0); \ + 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); \ } \ @@ -749,3 +736,20 @@ SOCKOPT_SETTER(multicast_loop, #undef VALIDATE_TTL #undef VALIDATE_MULTICAST_TTL #undef VALIDATE_MULTICAST_LOOP + + +/* This function is an egress point, i.e. it returns libuv errors rather than + * system errors. + */ +int uv__udp_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags) { + int err; + + err = uv_udp_try_bind(handle, addr, addrlen, flags); + if (err) + return uv_translate_sys_error(err); + + return 0; +} diff --git a/test/benchmark-udp-pummel.c b/test/benchmark-udp-pummel.c index 80d2bfc77..ce66600f6 100644 --- a/test/benchmark-udp-pummel.c +++ b/test/benchmark-udp-pummel.c @@ -174,7 +174,7 @@ static int pummel(unsigned int n_senders, struct sockaddr_in addr; ASSERT(0 == uv_ip4_addr("0.0.0.0", BASE_PORT + i, &addr)); ASSERT(0 == uv_udp_init(loop, &s->udp_handle)); - ASSERT(0 == uv_udp_bind(&s->udp_handle, addr, 0)); + ASSERT(0 == uv_udp_bind(&s->udp_handle, &addr, 0)); ASSERT(0 == uv_udp_recv_start(&s->udp_handle, alloc_cb, recv_cb)); uv_unref((uv_handle_t*)&s->udp_handle); } diff --git a/test/test-getsockname.c b/test/test-getsockname.c index c530122c5..57d276f27 100644 --- a/test/test-getsockname.c +++ b/test/test-getsockname.c @@ -279,7 +279,7 @@ static int udp_listener(void) { return 1; } - r = uv_udp_bind(&udpServer, addr, 0); + r = uv_udp_bind(&udpServer, &addr, 0); if (r) { fprintf(stderr, "Bind error\n"); return 1; diff --git a/test/test-ref.c b/test/test-ref.c index a77a731f1..aea1244e7 100644 --- a/test/test-ref.c +++ b/test/test-ref.c @@ -302,7 +302,7 @@ TEST_IMPL(udp_ref2) { uv_udp_t h; ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); uv_udp_init(uv_default_loop(), &h); - uv_udp_bind(&h, addr, 0); + uv_udp_bind(&h, &addr, 0); uv_udp_recv_start(&h, (uv_alloc_cb)fail_cb, (uv_udp_recv_cb)fail_cb); uv_unref((uv_handle_t*)&h); uv_run(uv_default_loop(), UV_RUN_DEFAULT); diff --git a/test/test-udp-ipv6.c b/test/test-udp-ipv6.c index aaf54a8d1..1f501a239 100644 --- a/test/test-udp-ipv6.c +++ b/test/test-udp-ipv6.c @@ -108,7 +108,7 @@ static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) { r = uv_udp_init(uv_default_loop(), &server); ASSERT(r == 0); - r = uv_udp_bind6(&server, addr6, bind_flags); + r = uv_udp_bind6(&server, &addr6, bind_flags); ASSERT(r == 0); r = uv_udp_recv_start(&server, alloc_cb, recv_cb); diff --git a/test/test-udp-multicast-join.c b/test/test-udp-multicast-join.c index 5545c3f49..3b162e247 100644 --- a/test/test-udp-multicast-join.c +++ b/test/test-udp-multicast-join.c @@ -111,7 +111,7 @@ TEST_IMPL(udp_multicast_join) { ASSERT(r == 0); /* bind to the desired port */ - r = uv_udp_bind(&client, addr, 0); + r = uv_udp_bind(&client, &addr, 0); ASSERT(r == 0); /* join the multicast channel */ diff --git a/test/test-udp-multicast-ttl.c b/test/test-udp-multicast-ttl.c index 6d868ff85..194ff90f5 100644 --- a/test/test-udp-multicast-ttl.c +++ b/test/test-udp-multicast-ttl.c @@ -63,7 +63,7 @@ TEST_IMPL(udp_multicast_ttl) { ASSERT(r == 0); ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &addr)); - r = uv_udp_bind(&server, addr, 0); + r = uv_udp_bind(&server, &addr, 0); ASSERT(r == 0); r = uv_udp_set_multicast_ttl(&server, 32); diff --git a/test/test-udp-open.c b/test/test-udp-open.c index c23d53c4f..3c554e478 100644 --- a/test/test-udp-open.c +++ b/test/test-udp-open.c @@ -140,7 +140,7 @@ TEST_IMPL(udp_open) { r = uv_udp_open(&client, sock); ASSERT(r == 0); - r = uv_udp_bind(&client, addr, 0); + r = uv_udp_bind(&client, &addr, 0); ASSERT(r == 0); r = uv_udp_recv_start(&client, alloc_cb, recv_cb); diff --git a/test/test-udp-options.c b/test/test-udp-options.c index 7923fa342..af90a5751 100644 --- a/test/test-udp-options.c +++ b/test/test-udp-options.c @@ -43,7 +43,7 @@ TEST_IMPL(udp_options) { uv_unref((uv_handle_t*)&h); /* don't keep the loop alive */ - r = uv_udp_bind(&h, addr, 0); + r = uv_udp_bind(&h, &addr, 0); ASSERT(r == 0); r = uv_udp_set_broadcast(&h, 1); diff --git a/test/test-udp-send-and-recv.c b/test/test-udp-send-and-recv.c index f90a182f1..db31937e1 100644 --- a/test/test-udp-send-and-recv.c +++ b/test/test-udp-send-and-recv.c @@ -175,7 +175,7 @@ TEST_IMPL(udp_send_and_recv) { r = uv_udp_init(uv_default_loop(), &server); ASSERT(r == 0); - r = uv_udp_bind(&server, addr, 0); + r = uv_udp_bind(&server, &addr, 0); ASSERT(r == 0); r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);