summaryrefslogtreecommitdiff
path: root/deps/uv/src/win/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src/win/udp.c')
-rw-r--r--deps/uv/src/win/udp.c103
1 files changed, 88 insertions, 15 deletions
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 37df849f8f..8aeeab3b46 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -36,22 +36,27 @@ const unsigned int uv_active_udp_streams_threshold = 0;
/* A zero-size buffer for use by uv_udp_read */
static char uv_zero_[] = "";
-
-int uv_udp_getsockname(const uv_udp_t* handle,
+int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen,
+ 0);
+}
- result = getsockname(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+int uv_udp_getsockname(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen) {
+
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen,
+ 0);
}
@@ -784,6 +789,18 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
}
+int uv__udp_is_bound(uv_udp_t* handle) {
+ struct sockaddr_storage addr;
+ int addrlen;
+
+ addrlen = sizeof(addr);
+ if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+ return 0;
+
+ return addrlen > 0;
+}
+
+
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
@@ -803,7 +820,16 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
handle,
sock,
protocol_info.iAddressFamily);
- return uv_translate_sys_error(err);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ if (uv__udp_is_bound(handle))
+ handle->flags |= UV_HANDLE_BOUND;
+
+ if (uv__udp_is_connected(handle))
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
}
@@ -880,6 +906,50 @@ int uv__udp_bind(uv_udp_t* handle,
}
+int uv__udp_connect(uv_udp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen) {
+ const struct sockaddr* bind_addr;
+ int err;
+
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ if (addrlen == sizeof(uv_addr_ip4_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
+ else if (addrlen == sizeof(uv_addr_ip6_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
+ else
+ return UV_EINVAL;
+
+ err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ if (err)
+ return uv_translate_sys_error(err);
+ }
+
+ err = connect(handle->socket, addr, addrlen);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+ int err;
+ struct sockaddr addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ err = connect(handle->socket, &addr, sizeof(addr));
+ if (err)
+ return uv_translate_sys_error(err);
+
+ handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+ return 0;
+}
+
+
/* This function is an egress point, i.e. it returns libuv errors rather than
* system errors.
*/
@@ -900,6 +970,7 @@ int uv__udp_send(uv_udp_send_t* req,
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
else
return UV_EINVAL;
+
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
@@ -925,9 +996,11 @@ int uv__udp_try_send(uv_udp_t* handle,
assert(nbufs > 0);
- err = uv__convert_to_localhost_if_unspecified(addr, &converted);
- if (err)
- return err;
+ if (addr != NULL) {
+ err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+ if (err)
+ return err;
+ }
/* Already sending a message.*/
if (handle->send_queue_count != 0)