unix, windows: be consistent when binding implictly in UDP

Only these functions will trigger an implicit binding of a UDP handle:
- uv_udp_send
- uv_udp_recv_start
- uv_udp_set_membership

All other functions will return UV_EBADF in case the socket was not
bound.

Note: currently the socket is created and bound at the same time. This
may change in the future.
This commit is contained in:
Saúl Ibarra Corretgé 2014-05-07 11:12:19 +02:00
parent fa0e1e5071
commit 386d2141e4
4 changed files with 31 additions and 36 deletions

View File

@ -629,7 +629,6 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
}
int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
int err;
struct sockaddr_storage addr_st;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
@ -655,9 +654,6 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
}
if (addr_st.ss_family == AF_INET) {
err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
if (err)
return err;
if (setsockopt(handle->io_watcher.fd,
IPPROTO_IP,
IP_MULTICAST_IF,
@ -666,9 +662,6 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return -errno;
}
} else if (addr_st.ss_family == AF_INET6) {
err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
if (err)
return err;
if (setsockopt(handle->io_watcher.fd,
IPPROTO_IPV6,
IPV6_MULTICAST_IF,

View File

@ -662,7 +662,6 @@ int uv_udp_set_membership(uv_udp_t* handle,
int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
int err;
struct sockaddr_storage addr_st;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
@ -687,13 +686,10 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return UV_EINVAL;
}
if (!(handle->flags & UV_HANDLE_BOUND))
return UV_EBADF;
if (addr_st.ss_family == AF_INET) {
err = uv_udp_maybe_bind(handle,
(const struct sockaddr*) &uv_addr_ip4_any_,
sizeof(uv_addr_ip4_any_),
UV_UDP_REUSEADDR);
if (err)
return uv_translate_sys_error(err);
if (setsockopt(handle->socket,
IPPROTO_IP,
IP_MULTICAST_IF,
@ -702,12 +698,6 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return uv_translate_sys_error(WSAGetLastError());
}
} else if (addr_st.ss_family == AF_INET6) {
err = uv_udp_maybe_bind(handle,
(const struct sockaddr*) &uv_addr_ip6_any_,
sizeof(uv_addr_ip6_any_),
UV_UDP_REUSEADDR);
if (err)
return uv_translate_sys_error(err);
if (setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_MULTICAST_IF,
@ -726,15 +716,9 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
BOOL optval = (BOOL) value;
int err;
/* If the socket is unbound, bind to inaddr_any. */
err = uv_udp_maybe_bind(handle,
(const struct sockaddr*) &uv_addr_ip4_any_,
sizeof(uv_addr_ip4_any_),
0);
if (err)
return uv_translate_sys_error(err);
if (!(handle->flags & UV_HANDLE_BOUND))
return UV_EBADF;
if (setsockopt(handle->socket,
SOL_SOCKET,
@ -774,19 +758,13 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
#define SOCKOPT_SETTER(name, option4, option6, validate) \
int uv_udp_set_##name(uv_udp_t* handle, int value) { \
DWORD optval = (DWORD) value; \
int err; \
\
if (!(validate(value))) { \
return UV_EINVAL; \
} \
\
/* If the socket is unbound, bind to inaddr_any. */ \
err = uv_udp_maybe_bind(handle, \
(const struct sockaddr*) &uv_addr_ip4_any_, \
sizeof(uv_addr_ip4_any_), \
0); \
if (err) \
return uv_translate_sys_error(err); \
if (!(handle->flags & UV_HANDLE_BOUND)) \
return UV_EBADF; \
\
if (!(handle->flags & UV_HANDLE_IPV6)) { \
/* Set IPv4 socket option */ \

View File

@ -93,6 +93,7 @@ TEST_DECLARE (udp_dgram_too_big)
TEST_DECLARE (udp_dual_stack)
TEST_DECLARE (udp_ipv6_only)
TEST_DECLARE (udp_options)
TEST_DECLARE (udp_no_autobind)
TEST_DECLARE (udp_open)
TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail)
@ -363,6 +364,7 @@ TASK_LIST_START
TEST_ENTRY (udp_dual_stack)
TEST_ENTRY (udp_ipv6_only)
TEST_ENTRY (udp_options)
TEST_ENTRY (udp_no_autobind)
TEST_ENTRY (udp_multicast_interface)
TEST_ENTRY (udp_multicast_interface6)
TEST_ENTRY (udp_multicast_join)

View File

@ -86,3 +86,25 @@ TEST_IMPL(udp_options) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(udp_no_autobind) {
uv_loop_t* loop;
uv_udp_t h;
loop = uv_default_loop();
ASSERT(0 == uv_udp_init(loop, &h));
ASSERT(UV_EBADF == uv_udp_set_multicast_ttl(&h, 32));
ASSERT(UV_EBADF == uv_udp_set_broadcast(&h, 1));
ASSERT(UV_EBADF == uv_udp_set_ttl(&h, 1));
ASSERT(UV_EBADF == uv_udp_set_multicast_loop(&h, 1));
ASSERT(UV_EBADF == uv_udp_set_multicast_interface(&h, "0.0.0.0"));
uv_close((uv_handle_t*) &h, NULL);
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
MAKE_VALGRIND_HAPPY();
return 0;
}