Blame src/win/winsock.c

Packit Service 7c31a4
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service 7c31a4
 * of this software and associated documentation files (the "Software"), to
Packit Service 7c31a4
 * deal in the Software without restriction, including without limitation the
Packit Service 7c31a4
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service 7c31a4
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service 7c31a4
 * furnished to do so, subject to the following conditions:
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The above copyright notice and this permission notice shall be included in
Packit Service 7c31a4
 * all copies or substantial portions of the Software.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 7c31a4
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 7c31a4
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service 7c31a4
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service 7c31a4
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service 7c31a4
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service 7c31a4
 * IN THE SOFTWARE.
Packit Service 7c31a4
 */
Packit Service 7c31a4
Packit Service 7c31a4
#include <assert.h>
Packit Service 7c31a4
#include <stdlib.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include "uv.h"
Packit Service 7c31a4
#include "internal.h"
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/* Whether there are any non-IFS LSPs stacked on TCP */
Packit Service 7c31a4
int uv_tcp_non_ifs_lsp_ipv4;
Packit Service 7c31a4
int uv_tcp_non_ifs_lsp_ipv6;
Packit Service 7c31a4
Packit Service 7c31a4
/* Ip address used to bind to any port at any interface */
Packit Service 7c31a4
struct sockaddr_in uv_addr_ip4_any_;
Packit Service 7c31a4
struct sockaddr_in6 uv_addr_ip6_any_;
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Retrieves the pointer to a winsock extension function.
Packit Service 7c31a4
 */
Packit Service 7c31a4
static BOOL uv_get_extension_function(SOCKET socket, GUID guid,
Packit Service 7c31a4
    void **target) {
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
  DWORD bytes;
Packit Service 7c31a4
Packit Service 7c31a4
  result = WSAIoctl(socket,
Packit Service 7c31a4
                    SIO_GET_EXTENSION_FUNCTION_POINTER,
Packit Service 7c31a4
                    &guid,
Packit Service 7c31a4
                    sizeof(guid),
Packit Service 7c31a4
                    (void*)target,
Packit Service 7c31a4
                    sizeof(*target),
Packit Service 7c31a4
                    &bytes,
Packit Service 7c31a4
                    NULL,
Packit Service 7c31a4
                    NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (result == SOCKET_ERROR) {
Packit Service 7c31a4
    *target = NULL;
Packit Service 7c31a4
    return FALSE;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    return TRUE;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) {
Packit Service 7c31a4
  const GUID wsaid_acceptex = WSAID_ACCEPTEX;
Packit Service 7c31a4
  return uv_get_extension_function(socket, wsaid_acceptex, (void**)target);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) {
Packit Service 7c31a4
  const GUID wsaid_connectex = WSAID_CONNECTEX;
Packit Service 7c31a4
  return uv_get_extension_function(socket, wsaid_connectex, (void**)target);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_winsock_init(void) {
Packit Service 7c31a4
  WSADATA wsa_data;
Packit Service 7c31a4
  int errorno;
Packit Service 7c31a4
  SOCKET dummy;
Packit Service 7c31a4
  WSAPROTOCOL_INFOW protocol_info;
Packit Service 7c31a4
  int opt_len;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Set implicit binding address used by connectEx */
Packit Service 7c31a4
  if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
Packit Service 7c31a4
    abort();
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv_ip6_addr("::", 0, &uv_addr_ip6_any_)) {
Packit Service 7c31a4
    abort();
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Skip initialization in safe mode without network support */
Packit Service 7c31a4
  if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Initialize winsock */
Packit Service 7c31a4
  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
Packit Service 7c31a4
  if (errorno != 0) {
Packit Service 7c31a4
    uv_fatal_error(errorno, "WSAStartup");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Try to detect non-IFS LSPs */
Packit Service 7c31a4
  uv_tcp_non_ifs_lsp_ipv4 = 1;
Packit Service 7c31a4
  dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
Packit Service 7c31a4
  if (dummy != INVALID_SOCKET) {
Packit Service 7c31a4
    opt_len = (int) sizeof protocol_info;
Packit Service 7c31a4
    if (getsockopt(dummy,
Packit Service 7c31a4
                   SOL_SOCKET,
Packit Service 7c31a4
                   SO_PROTOCOL_INFOW,
Packit Service 7c31a4
                   (char*) &protocol_info,
Packit Service 7c31a4
                   &opt_len) == 0) {
Packit Service 7c31a4
      if (protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)
Packit Service 7c31a4
        uv_tcp_non_ifs_lsp_ipv4 = 0;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    closesocket(dummy);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Try to detect IPV6 support and non-IFS LSPs */
Packit Service 7c31a4
  uv_tcp_non_ifs_lsp_ipv6 = 1;
Packit Service 7c31a4
  dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
Packit Service 7c31a4
  if (dummy != INVALID_SOCKET) {
Packit Service 7c31a4
    opt_len = (int) sizeof protocol_info;
Packit Service 7c31a4
    if (getsockopt(dummy,
Packit Service 7c31a4
                   SOL_SOCKET,
Packit Service 7c31a4
                   SO_PROTOCOL_INFOW,
Packit Service 7c31a4
                   (char*) &protocol_info,
Packit Service 7c31a4
                   &opt_len) == 0) {
Packit Service 7c31a4
      if (protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)
Packit Service 7c31a4
        uv_tcp_non_ifs_lsp_ipv6 = 0;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    closesocket(dummy);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_ntstatus_to_winsock_error(NTSTATUS status) {
Packit Service 7c31a4
  switch (status) {
Packit Service 7c31a4
    case STATUS_SUCCESS:
Packit Service 7c31a4
      return ERROR_SUCCESS;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_PENDING:
Packit Service 7c31a4
      return ERROR_IO_PENDING;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_INVALID_HANDLE:
Packit Service 7c31a4
    case STATUS_OBJECT_TYPE_MISMATCH:
Packit Service 7c31a4
      return WSAENOTSOCK;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_INSUFFICIENT_RESOURCES:
Packit Service 7c31a4
    case STATUS_PAGEFILE_QUOTA:
Packit Service 7c31a4
    case STATUS_COMMITMENT_LIMIT:
Packit Service 7c31a4
    case STATUS_WORKING_SET_QUOTA:
Packit Service 7c31a4
    case STATUS_NO_MEMORY:
Packit Service 7c31a4
    case STATUS_QUOTA_EXCEEDED:
Packit Service 7c31a4
    case STATUS_TOO_MANY_PAGING_FILES:
Packit Service 7c31a4
    case STATUS_REMOTE_RESOURCES:
Packit Service 7c31a4
      return WSAENOBUFS;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_TOO_MANY_ADDRESSES:
Packit Service 7c31a4
    case STATUS_SHARING_VIOLATION:
Packit Service 7c31a4
    case STATUS_ADDRESS_ALREADY_EXISTS:
Packit Service 7c31a4
      return WSAEADDRINUSE;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_LINK_TIMEOUT:
Packit Service 7c31a4
    case STATUS_IO_TIMEOUT:
Packit Service 7c31a4
    case STATUS_TIMEOUT:
Packit Service 7c31a4
      return WSAETIMEDOUT;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_GRACEFUL_DISCONNECT:
Packit Service 7c31a4
      return WSAEDISCON;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_REMOTE_DISCONNECT:
Packit Service 7c31a4
    case STATUS_CONNECTION_RESET:
Packit Service 7c31a4
    case STATUS_LINK_FAILED:
Packit Service 7c31a4
    case STATUS_CONNECTION_DISCONNECTED:
Packit Service 7c31a4
    case STATUS_PORT_UNREACHABLE:
Packit Service 7c31a4
    case STATUS_HOPLIMIT_EXCEEDED:
Packit Service 7c31a4
      return WSAECONNRESET;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_LOCAL_DISCONNECT:
Packit Service 7c31a4
    case STATUS_TRANSACTION_ABORTED:
Packit Service 7c31a4
    case STATUS_CONNECTION_ABORTED:
Packit Service 7c31a4
      return WSAECONNABORTED;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_BAD_NETWORK_PATH:
Packit Service 7c31a4
    case STATUS_NETWORK_UNREACHABLE:
Packit Service 7c31a4
    case STATUS_PROTOCOL_UNREACHABLE:
Packit Service 7c31a4
      return WSAENETUNREACH;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_HOST_UNREACHABLE:
Packit Service 7c31a4
      return WSAEHOSTUNREACH;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_CANCELLED:
Packit Service 7c31a4
    case STATUS_REQUEST_ABORTED:
Packit Service 7c31a4
      return WSAEINTR;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_BUFFER_OVERFLOW:
Packit Service 7c31a4
    case STATUS_INVALID_BUFFER_SIZE:
Packit Service 7c31a4
      return WSAEMSGSIZE;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_BUFFER_TOO_SMALL:
Packit Service 7c31a4
    case STATUS_ACCESS_VIOLATION:
Packit Service 7c31a4
      return WSAEFAULT;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_DEVICE_NOT_READY:
Packit Service 7c31a4
    case STATUS_REQUEST_NOT_ACCEPTED:
Packit Service 7c31a4
      return WSAEWOULDBLOCK;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_INVALID_NETWORK_RESPONSE:
Packit Service 7c31a4
    case STATUS_NETWORK_BUSY:
Packit Service 7c31a4
    case STATUS_NO_SUCH_DEVICE:
Packit Service 7c31a4
    case STATUS_NO_SUCH_FILE:
Packit Service 7c31a4
    case STATUS_OBJECT_PATH_NOT_FOUND:
Packit Service 7c31a4
    case STATUS_OBJECT_NAME_NOT_FOUND:
Packit Service 7c31a4
    case STATUS_UNEXPECTED_NETWORK_ERROR:
Packit Service 7c31a4
      return WSAENETDOWN;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_INVALID_CONNECTION:
Packit Service 7c31a4
      return WSAENOTCONN;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_REMOTE_NOT_LISTENING:
Packit Service 7c31a4
    case STATUS_CONNECTION_REFUSED:
Packit Service 7c31a4
      return WSAECONNREFUSED;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_PIPE_DISCONNECTED:
Packit Service 7c31a4
      return WSAESHUTDOWN;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_CONFLICTING_ADDRESSES:
Packit Service 7c31a4
    case STATUS_INVALID_ADDRESS:
Packit Service 7c31a4
    case STATUS_INVALID_ADDRESS_COMPONENT:
Packit Service 7c31a4
      return WSAEADDRNOTAVAIL;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_NOT_SUPPORTED:
Packit Service 7c31a4
    case STATUS_NOT_IMPLEMENTED:
Packit Service 7c31a4
      return WSAEOPNOTSUPP;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_ACCESS_DENIED:
Packit Service 7c31a4
      return WSAEACCES;
Packit Service 7c31a4
Packit Service 7c31a4
    default:
Packit Service 7c31a4
      if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&
Packit Service 7c31a4
          (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {
Packit Service 7c31a4
        /* It's a windows error that has been previously mapped to an ntstatus
Packit Service 7c31a4
         * code. */
Packit Service 7c31a4
        return (DWORD) (status & 0xffff);
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        /* The default fallback for unmappable ntstatus codes. */
Packit Service 7c31a4
        return WSAEINVAL;
Packit Service 7c31a4
      }
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * This function provides a workaround for a bug in the winsock implementation
Packit Service 7c31a4
 * of WSARecv. The problem is that when SetFileCompletionNotificationModes is
Packit Service 7c31a4
 * used to avoid IOCP notifications of completed reads, WSARecv does not
Packit Service 7c31a4
 * reliably indicate whether we can expect a completion package to be posted
Packit Service 7c31a4
 * when the receive buffer is smaller than the received datagram.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * However it is desirable to use SetFileCompletionNotificationModes because
Packit Service 7c31a4
 * it yields a massive performance increase.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * This function provides a workaround for that bug, but it only works for the
Packit Service 7c31a4
 * specific case that we need it for. E.g. it assumes that the "avoid iocp"
Packit Service 7c31a4
 * bit has been set, and supports only overlapped operation. It also requires
Packit Service 7c31a4
 * the user to use the default msafd driver, doesn't work when other LSPs are
Packit Service 7c31a4
 * stacked on top of it.
Packit Service 7c31a4
 */
Packit Service 7c31a4
int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
Packit Service 7c31a4
    DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,
Packit Service 7c31a4
    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
  void* apc_context;
Packit Service 7c31a4
  IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;
Packit Service 7c31a4
  AFD_RECV_INFO info;
Packit Service 7c31a4
  DWORD error;
Packit Service 7c31a4
Packit Service 7c31a4
  if (overlapped == NULL || completion_routine != NULL) {
Packit Service 7c31a4
    WSASetLastError(WSAEINVAL);
Packit Service 7c31a4
    return SOCKET_ERROR;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  info.BufferArray = buffers;
Packit Service 7c31a4
  info.BufferCount = buffer_count;
Packit Service 7c31a4
  info.AfdFlags = AFD_OVERLAPPED;
Packit Service 7c31a4
  info.TdiFlags = TDI_RECEIVE_NORMAL;
Packit Service 7c31a4
Packit Service 7c31a4
  if (*flags & MSG_PEEK) {
Packit Service 7c31a4
    info.TdiFlags |= TDI_RECEIVE_PEEK;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (*flags & MSG_PARTIAL) {
Packit Service 7c31a4
    info.TdiFlags |= TDI_RECEIVE_PARTIAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!((intptr_t) overlapped->hEvent & 1)) {
Packit Service 7c31a4
    apc_context = (void*) overlapped;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    apc_context = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  iosb->Status = STATUS_PENDING;
Packit Service 7c31a4
  iosb->Pointer = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  status = pNtDeviceIoControlFile((HANDLE) socket,
Packit Service 7c31a4
                                  overlapped->hEvent,
Packit Service 7c31a4
                                  NULL,
Packit Service 7c31a4
                                  apc_context,
Packit Service 7c31a4
                                  iosb,
Packit Service 7c31a4
                                  IOCTL_AFD_RECEIVE,
Packit Service 7c31a4
                                  &info,
Packit Service 7c31a4
                                  sizeof(info),
Packit Service 7c31a4
                                  NULL,
Packit Service 7c31a4
                                  0);
Packit Service 7c31a4
Packit Service 7c31a4
  *flags = 0;
Packit Service 7c31a4
  *bytes = (DWORD) iosb->Information;
Packit Service 7c31a4
Packit Service 7c31a4
  switch (status) {
Packit Service 7c31a4
    case STATUS_SUCCESS:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_PENDING:
Packit Service 7c31a4
      error = WSA_IO_PENDING;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_BUFFER_OVERFLOW:
Packit Service 7c31a4
      error = WSAEMSGSIZE;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_RECEIVE_EXPEDITED:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      *flags = MSG_OOB;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_RECEIVE_PARTIAL_EXPEDITED:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      *flags = MSG_PARTIAL | MSG_OOB;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_RECEIVE_PARTIAL:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      *flags = MSG_PARTIAL;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    default:
Packit Service 7c31a4
      error = uv_ntstatus_to_winsock_error(status);
Packit Service 7c31a4
      break;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  WSASetLastError(error);
Packit Service 7c31a4
Packit Service 7c31a4
  if (error == ERROR_SUCCESS) {
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    return SOCKET_ERROR;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/* See description of uv_wsarecv_workaround. */
Packit Service 7c31a4
int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
Packit Service 7c31a4
    DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,
Packit Service 7c31a4
    int* addr_len, WSAOVERLAPPED *overlapped,
Packit Service 7c31a4
    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
  void* apc_context;
Packit Service 7c31a4
  IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;
Packit Service 7c31a4
  AFD_RECV_DATAGRAM_INFO info;
Packit Service 7c31a4
  DWORD error;
Packit Service 7c31a4
Packit Service 7c31a4
  if (overlapped == NULL || addr == NULL || addr_len == NULL ||
Packit Service 7c31a4
      completion_routine != NULL) {
Packit Service 7c31a4
    WSASetLastError(WSAEINVAL);
Packit Service 7c31a4
    return SOCKET_ERROR;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  info.BufferArray = buffers;
Packit Service 7c31a4
  info.BufferCount = buffer_count;
Packit Service 7c31a4
  info.AfdFlags = AFD_OVERLAPPED;
Packit Service 7c31a4
  info.TdiFlags = TDI_RECEIVE_NORMAL;
Packit Service 7c31a4
  info.Address = addr;
Packit Service 7c31a4
  info.AddressLength = addr_len;
Packit Service 7c31a4
Packit Service 7c31a4
  if (*flags & MSG_PEEK) {
Packit Service 7c31a4
    info.TdiFlags |= TDI_RECEIVE_PEEK;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (*flags & MSG_PARTIAL) {
Packit Service 7c31a4
    info.TdiFlags |= TDI_RECEIVE_PARTIAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!((intptr_t) overlapped->hEvent & 1)) {
Packit Service 7c31a4
    apc_context = (void*) overlapped;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    apc_context = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  iosb->Status = STATUS_PENDING;
Packit Service 7c31a4
  iosb->Pointer = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  status = pNtDeviceIoControlFile((HANDLE) socket,
Packit Service 7c31a4
                                  overlapped->hEvent,
Packit Service 7c31a4
                                  NULL,
Packit Service 7c31a4
                                  apc_context,
Packit Service 7c31a4
                                  iosb,
Packit Service 7c31a4
                                  IOCTL_AFD_RECEIVE_DATAGRAM,
Packit Service 7c31a4
                                  &info,
Packit Service 7c31a4
                                  sizeof(info),
Packit Service 7c31a4
                                  NULL,
Packit Service 7c31a4
                                  0);
Packit Service 7c31a4
Packit Service 7c31a4
  *flags = 0;
Packit Service 7c31a4
  *bytes = (DWORD) iosb->Information;
Packit Service 7c31a4
Packit Service 7c31a4
  switch (status) {
Packit Service 7c31a4
    case STATUS_SUCCESS:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_PENDING:
Packit Service 7c31a4
      error = WSA_IO_PENDING;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_BUFFER_OVERFLOW:
Packit Service 7c31a4
      error = WSAEMSGSIZE;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_RECEIVE_EXPEDITED:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      *flags = MSG_OOB;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_RECEIVE_PARTIAL_EXPEDITED:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      *flags = MSG_PARTIAL | MSG_OOB;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_RECEIVE_PARTIAL:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      *flags = MSG_PARTIAL;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    default:
Packit Service 7c31a4
      error = uv_ntstatus_to_winsock_error(status);
Packit Service 7c31a4
      break;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  WSASetLastError(error);
Packit Service 7c31a4
Packit Service 7c31a4
  if (error == ERROR_SUCCESS) {
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    return SOCKET_ERROR;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
Packit Service 7c31a4
    AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) {
Packit Service 7c31a4
  IO_STATUS_BLOCK iosb;
Packit Service 7c31a4
  IO_STATUS_BLOCK* iosb_ptr;
Packit Service 7c31a4
  HANDLE event = NULL;
Packit Service 7c31a4
  void* apc_context;
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
  DWORD error;
Packit Service 7c31a4
Packit Service 7c31a4
  if (overlapped != NULL) {
Packit Service 7c31a4
    /* Overlapped operation. */
Packit Service 7c31a4
    iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal;
Packit Service 7c31a4
    event = overlapped->hEvent;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Do not report iocp completion if hEvent is tagged. */
Packit Service 7c31a4
    if ((uintptr_t) event & 1) {
Packit Service 7c31a4
      event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);
Packit Service 7c31a4
      apc_context = NULL;
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      apc_context = overlapped;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* Blocking operation. */
Packit Service 7c31a4
    iosb_ptr = &ios;;
Packit Service 7c31a4
    event = CreateEvent(NULL, FALSE, FALSE, NULL);
Packit Service 7c31a4
    if (event == NULL) {
Packit Service 7c31a4
      return SOCKET_ERROR;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    apc_context = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  iosb_ptr->Status = STATUS_PENDING;
Packit Service 7c31a4
  status = pNtDeviceIoControlFile((HANDLE) socket,
Packit Service 7c31a4
                                  event,
Packit Service 7c31a4
                                  NULL,
Packit Service 7c31a4
                                  apc_context,
Packit Service 7c31a4
                                  iosb_ptr,
Packit Service 7c31a4
                                  IOCTL_AFD_POLL,
Packit Service 7c31a4
                                  info_in,
Packit Service 7c31a4
                                  sizeof *info_in,
Packit Service 7c31a4
                                  info_out,
Packit Service 7c31a4
                                  sizeof *info_out);
Packit Service 7c31a4
Packit Service 7c31a4
  if (overlapped == NULL) {
Packit Service 7c31a4
    /* If this is a blocking operation, wait for the event to become signaled,
Packit Service 7c31a4
     * and then grab the real status from the io status block. */
Packit Service 7c31a4
    if (status == STATUS_PENDING) {
Packit Service 7c31a4
      DWORD r = WaitForSingleObject(event, INFINITE);
Packit Service 7c31a4
Packit Service 7c31a4
      if (r == WAIT_FAILED) {
Packit Service 7c31a4
        DWORD saved_error = GetLastError();
Packit Service 7c31a4
        CloseHandle(event);
Packit Service 7c31a4
        WSASetLastError(saved_error);
Packit Service 7c31a4
        return SOCKET_ERROR;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      status = iosb.Status;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    CloseHandle(event);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  switch (status) {
Packit Service 7c31a4
    case STATUS_SUCCESS:
Packit Service 7c31a4
      error = ERROR_SUCCESS;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    case STATUS_PENDING:
Packit Service 7c31a4
      error = WSA_IO_PENDING;
Packit Service 7c31a4
      break;
Packit Service 7c31a4
Packit Service 7c31a4
    default:
Packit Service 7c31a4
      error = uv_ntstatus_to_winsock_error(status);
Packit Service 7c31a4
      break;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  WSASetLastError(error);
Packit Service 7c31a4
Packit Service 7c31a4
  if (error == ERROR_SUCCESS) {
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    return SOCKET_ERROR;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
Packit Service 7c31a4
                                            struct sockaddr_storage* storage) {
Packit Service 7c31a4
  struct sockaddr_in* dest4;
Packit Service 7c31a4
  struct sockaddr_in6* dest6;
Packit Service 7c31a4
Packit Service 7c31a4
  if (addr == NULL)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  switch (addr->sa_family) {
Packit Service 7c31a4
  case AF_INET:
Packit Service 7c31a4
    dest4 = (struct sockaddr_in*) storage;
Packit Service 7c31a4
    memcpy(dest4, addr, sizeof(*dest4));
Packit Service 7c31a4
    if (dest4->sin_addr.s_addr == 0)
Packit Service 7c31a4
      dest4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  case AF_INET6:
Packit Service 7c31a4
    dest6 = (struct sockaddr_in6*) storage;
Packit Service 7c31a4
    memcpy(dest6, addr, sizeof(*dest6));
Packit Service 7c31a4
    if (memcmp(&dest6->sin6_addr,
Packit Service 7c31a4
               &uv_addr_ip6_any_.sin6_addr,
Packit Service 7c31a4
               sizeof(uv_addr_ip6_any_.sin6_addr)) == 0) {
Packit Service 7c31a4
      struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT;
Packit Service 7c31a4
      dest6->sin6_addr = init_sin6_addr;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  default:
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}