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:
parent
0f7b2963ad
commit
525dbb5e31
10
include/uv.h
10
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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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[],
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user