static int uv__bind(uv_udp_t* handle, int domain, struct sockaddr* addr, int addrsize, unsigned int flags) { DWORD err; int r; SOCKET sock; if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) { /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ uv__set_artificial_error(handle->loop, UV_EINVAL); return -1; } if (handle->socket == INVALID_SOCKET) { sock = socket(domain, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } if (uv_udp_set_socket(handle->loop, handle, sock) == -1) { closesocket(sock); return -1; } } if (domain == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { DWORD off = 0; /* On windows IPV6ONLY is on by default. */ /* If the user doesn't specify it libuv turns it off. */ /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ /* available, or when run on XP/2003 which have no support for dualstack */ /* sockets. For now we're silently ignoring the error. */ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &off, sizeof off); } r = bind(handle->socket, addr, addrsize); if (r == SOCKET_ERROR) { err = WSAGetLastError(); uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } handle->flags |= UV_HANDLE_BOUND; return 0; }
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) && 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(addr->sa_family, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { return WSAGetLastError(); } err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family); if (err) { closesocket(sock); return err; } if (addr->sa_family == AF_INET6) handle->flags |= UV_HANDLE_IPV6; } 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. */ /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ /* available, or when run on XP/2003 which have no support for dualstack */ /* sockets. For now we're silently ignoring the error. */ setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &no, sizeof no); } r = bind(handle->socket, addr, addrlen); if (r == SOCKET_ERROR) { return WSAGetLastError(); } handle->flags |= UV_HANDLE_BOUND; return 0; }
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { int domain; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return UV_EINVAL; if (flags & ~0xFF) return UV_EINVAL; uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP); handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; handle->activecnt = 0; handle->func_wsarecv = WSARecv; handle->func_wsarecvfrom = WSARecvFrom; handle->send_queue_size = 0; handle->send_queue_count = 0; uv_req_init(loop, (uv_req_t*) &(handle->recv_req)); handle->recv_req.type = UV_UDP_RECV; handle->recv_req.data = handle; /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init. */ if (domain != AF_UNSPEC) { SOCKET sock; DWORD err; sock = socket(domain, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { err = WSAGetLastError(); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } err = uv_udp_set_socket(handle->loop, handle, sock, domain); if (err) { closesocket(sock); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } } return 0; }
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { WSAPROTOCOL_INFOW protocol_info; int opt_len; int err; /* Detect the address family of the socket. */ opt_len = (int) sizeof protocol_info; if (getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, &opt_len) == SOCKET_ERROR) { return uv_translate_sys_error(GetLastError()); } err = uv_udp_set_socket(handle->loop, handle, sock, protocol_info.iAddressFamily); return uv_translate_sys_error(err); }