include: uv_udp_bind{6} now takes sockaddr_in*

Passing or returning structs as values makes life hard for people that
work with libuv through a foreign function interface. Switch to a
pointer-based approach.

Fixes #684.
This commit is contained in:
Ben Noordhuis 2013-08-31 07:10:56 +02:00
parent 0f7b2963ad
commit 525dbb5e31
14 changed files with 95 additions and 100 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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[],

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);