unix,win: implement uv_udp_open_ex
Fixes: https://github.com/libuv/libuv/issues/4551 Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com>
This commit is contained in:
parent
74079a8e47
commit
54063830a6
@ -173,6 +173,22 @@ API
|
||||
.. versionadded:: 1.7.0
|
||||
.. versionchanged:: 1.37.0 added the `UV_UDP_RECVMMSG` flag.
|
||||
|
||||
.. c:function:: int uv_udp_open_ex(uv_udp_t* handle, uv_os_sock_t sock, unsigned int flags)
|
||||
|
||||
Opens an existing file descriptor or Windows SOCKET as a UDP handle.
|
||||
|
||||
:param handle: UDP handle. Should have been initialized with
|
||||
:c:func:`uv_udp_init`.
|
||||
|
||||
:param sock: An existing socket to associate with the handle.
|
||||
|
||||
:param flags: Flags that control socket behavior,
|
||||
``UV_UDP_REUSEADDR``, and ``UV_UDP_REUSEPORT`` are supported.
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
.. versionadded:: 1.52.0
|
||||
|
||||
.. c:function:: int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock)
|
||||
|
||||
Opens an existing file descriptor or Windows SOCKET as a UDP handle.
|
||||
@ -189,6 +205,10 @@ API
|
||||
The passed file descriptor or SOCKET is not checked for its type, but
|
||||
it's required that it represents a valid datagram socket.
|
||||
|
||||
Internally sets the SO_REUSEADDR socket option unconditionally. This
|
||||
means the reuse flag is always enabled, regardless of user intent. For
|
||||
more control use :c:func:`uv_udp_open_ex`.
|
||||
|
||||
.. c:function:: int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags)
|
||||
|
||||
Bind the UDP handle to an IP address and port.
|
||||
|
||||
@ -746,6 +746,9 @@ struct uv_udp_send_s {
|
||||
UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
|
||||
UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags);
|
||||
UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
|
||||
UV_EXTERN int uv_udp_open_ex(uv_udp_t* handle,
|
||||
uv_os_sock_t sock,
|
||||
unsigned int flags);
|
||||
UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
|
||||
const struct sockaddr* addr,
|
||||
unsigned int flags);
|
||||
|
||||
@ -897,9 +897,13 @@ int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
int uv_udp_open_ex(uv_udp_t* handle, uv_os_sock_t sock, unsigned int flags) {
|
||||
int err;
|
||||
|
||||
/* Check for bad flags. */
|
||||
if (flags & ~(UV_UDP_REUSEADDR | UV_UDP_REUSEPORT))
|
||||
return UV_EINVAL;
|
||||
|
||||
/* Check for already active socket. */
|
||||
if (handle->io_watcher.fd != -1)
|
||||
return UV_EBUSY;
|
||||
@ -911,9 +915,17 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = uv__sock_reuseaddr(sock);
|
||||
if (err)
|
||||
return err;
|
||||
if (flags & UV_UDP_REUSEADDR) {
|
||||
err = uv__sock_reuseaddr(sock);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (flags & UV_UDP_REUSEPORT) {
|
||||
err = uv__sock_reuseport(sock);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
handle->io_watcher.fd = sock;
|
||||
if (uv__udp_is_connected(handle))
|
||||
@ -923,6 +935,15 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
/*
|
||||
* Keep backward compatibility, always set REUSEADDR.
|
||||
* Refs: https://github.com/libuv/libuv/issues/4551
|
||||
*/
|
||||
return uv_udp_open_ex(handle, sock, UV_UDP_REUSEADDR);
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_set_membership(uv_udp_t* handle,
|
||||
const char* multicast_addr,
|
||||
const char* interface_addr,
|
||||
|
||||
@ -204,7 +204,7 @@ static int uv__udp_maybe_bind(uv_udp_t* handle,
|
||||
* so we just return an error directly when UV_UDP_REUSEPORT is requested
|
||||
* for binding the socket. */
|
||||
if (flags & UV_UDP_REUSEPORT)
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
return UV_ENOTSUP;
|
||||
|
||||
if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {
|
||||
/* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
|
||||
@ -908,11 +908,15 @@ int uv__udp_is_bound(uv_udp_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
int uv_udp_open_ex(uv_udp_t* handle, uv_os_sock_t sock, unsigned int flags) {
|
||||
WSAPROTOCOL_INFOW protocol_info;
|
||||
int opt_len;
|
||||
int err;
|
||||
|
||||
/* Check for bad flags. */
|
||||
if (flags & ~(UV_UDP_REUSEADDR | UV_UDP_REUSEPORT))
|
||||
return UV_EINVAL;
|
||||
|
||||
/* Detect the address family of the socket. */
|
||||
opt_len = (int) sizeof protocol_info;
|
||||
if (getsockopt(sock,
|
||||
@ -930,6 +934,25 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
|
||||
/* There is no SO_REUSEPORT on Windows, Windows only knows SO_REUSEADDR.
|
||||
* so we just return an error directly when UV_UDP_REUSEPORT is requested
|
||||
* for binding the socket. */
|
||||
if (flags & UV_UDP_REUSEPORT)
|
||||
return UV_ENOTSUP;
|
||||
|
||||
if (flags & UV_UDP_REUSEADDR) {
|
||||
DWORD yes = 1;
|
||||
/* Set SO_REUSEADDR on the socket. */
|
||||
if (setsockopt(handle->socket,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
(char*) &yes,
|
||||
sizeof yes) == SOCKET_ERROR) {
|
||||
err = WSAGetLastError();
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (uv__udp_is_bound(handle))
|
||||
handle->flags |= UV_HANDLE_BOUND;
|
||||
|
||||
@ -940,6 +963,11 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
return uv_udp_open_ex(handle, sock, 0);
|
||||
}
|
||||
|
||||
|
||||
#define SOCKOPT_SETTER(name, option4, option6, validate) \
|
||||
int uv_udp_set_##name(uv_udp_t* handle, int value) { \
|
||||
DWORD optval = (DWORD) value; \
|
||||
|
||||
Loading…
Reference in New Issue
Block a user