|
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 <io.h>
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
#include "uv.h"
|
|
Packit Service |
7c31a4 |
#include "internal.h"
|
|
Packit Service |
7c31a4 |
#include "handle-inl.h"
|
|
Packit Service |
7c31a4 |
#include "req-inl.h"
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {
|
|
Packit Service |
7c31a4 |
{0xe70f1aa0, 0xab8b, 0x11cf,
|
|
Packit Service |
7c31a4 |
{0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
|
|
Packit Service |
7c31a4 |
{0xf9eab0c0, 0x26d4, 0x11d0,
|
|
Packit Service |
7c31a4 |
{0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
|
|
Packit Service |
7c31a4 |
{0x9fc48064, 0x7298, 0x43e4,
|
|
Packit Service |
7c31a4 |
{0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}
|
|
Packit Service |
7c31a4 |
};
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
typedef struct uv_single_fd_set_s {
|
|
Packit Service |
7c31a4 |
unsigned int fd_count;
|
|
Packit Service |
7c31a4 |
SOCKET fd_array[1];
|
|
Packit Service |
7c31a4 |
} uv_single_fd_set_t;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static OVERLAPPED overlapped_dummy_;
|
|
Packit Service |
7c31a4 |
static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static AFD_POLL_INFO afd_poll_info_dummy_;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static void uv__init_overlapped_dummy(void) {
|
|
Packit Service |
7c31a4 |
HANDLE event;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
|
Packit Service |
7c31a4 |
if (event == NULL)
|
|
Packit Service |
7c31a4 |
uv_fatal_error(GetLastError(), "CreateEvent");
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
memset(&overlapped_dummy_, 0, sizeof overlapped_dummy_);
|
|
Packit Service |
7c31a4 |
overlapped_dummy_.hEvent = (HANDLE) ((uintptr_t) event | 1);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static OVERLAPPED* uv__get_overlapped_dummy(void) {
|
|
Packit Service |
7c31a4 |
uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy);
|
|
Packit Service |
7c31a4 |
return &overlapped_dummy_;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
|
|
Packit Service |
7c31a4 |
return &afd_poll_info_dummy_;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
|
Packit Service |
7c31a4 |
uv_req_t* req;
|
|
Packit Service |
7c31a4 |
AFD_POLL_INFO* afd_poll_info;
|
|
Packit Service |
7c31a4 |
int result;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Find a yet unsubmitted req to submit. */
|
|
Packit Service |
7c31a4 |
if (handle->submitted_events_1 == 0) {
|
|
Packit Service |
7c31a4 |
req = &handle->poll_req_1;
|
|
Packit Service |
7c31a4 |
afd_poll_info = &handle->afd_poll_info_1;
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 = handle->events;
|
|
Packit Service |
7c31a4 |
handle->mask_events_1 = 0;
|
|
Packit Service |
7c31a4 |
handle->mask_events_2 = handle->events;
|
|
Packit Service |
7c31a4 |
} else if (handle->submitted_events_2 == 0) {
|
|
Packit Service |
7c31a4 |
req = &handle->poll_req_2;
|
|
Packit Service |
7c31a4 |
afd_poll_info = &handle->afd_poll_info_2;
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 = handle->events;
|
|
Packit Service |
7c31a4 |
handle->mask_events_1 = handle->events;
|
|
Packit Service |
7c31a4 |
handle->mask_events_2 = 0;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
/* Just wait until there's an unsubmitted req. This will happen almost
|
|
Packit Service |
7c31a4 |
* immediately as one of the 2 outstanding requests is about to return.
|
|
Packit Service |
7c31a4 |
* When this happens, uv__fast_poll_process_poll_req will be called, and
|
|
Packit Service |
7c31a4 |
* the pending events, if needed, will be processed in a subsequent
|
|
Packit Service |
7c31a4 |
* request. */
|
|
Packit Service |
7c31a4 |
return;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Setting Exclusive to TRUE makes the other poll request return if there is
|
|
Packit Service |
7c31a4 |
* any. */
|
|
Packit Service |
7c31a4 |
afd_poll_info->Exclusive = TRUE;
|
|
Packit Service |
7c31a4 |
afd_poll_info->NumberOfHandles = 1;
|
|
Packit Service |
7c31a4 |
afd_poll_info->Timeout.QuadPart = INT64_MAX;
|
|
Packit Service |
7c31a4 |
afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;
|
|
Packit Service |
7c31a4 |
afd_poll_info->Handles[0].Status = 0;
|
|
Packit Service |
7c31a4 |
afd_poll_info->Handles[0].Events = 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->events & UV_READABLE) {
|
|
Packit Service |
7c31a4 |
afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE |
|
|
Packit Service |
7c31a4 |
AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
if (handle->events & UV_DISCONNECT) {
|
|
Packit Service |
7c31a4 |
afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
if (handle->events & UV_WRITABLE) {
|
|
Packit Service |
7c31a4 |
afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
result = uv_msafd_poll((SOCKET) handle->peer_socket,
|
|
Packit Service |
7c31a4 |
afd_poll_info,
|
|
Packit Service |
7c31a4 |
afd_poll_info,
|
|
Packit Service |
7c31a4 |
&req->u.io.overlapped);
|
|
Packit Service |
7c31a4 |
if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
|
|
Packit Service |
7c31a4 |
/* Queue this req, reporting an error. */
|
|
Packit Service |
7c31a4 |
SET_REQ_ERROR(req, WSAGetLastError());
|
|
Packit Service |
7c31a4 |
uv_insert_pending_req(loop, req);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|
Packit Service |
7c31a4 |
uv_req_t* req) {
|
|
Packit Service |
7c31a4 |
unsigned char mask_events;
|
|
Packit Service |
7c31a4 |
AFD_POLL_INFO* afd_poll_info;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (req == &handle->poll_req_1) {
|
|
Packit Service |
7c31a4 |
afd_poll_info = &handle->afd_poll_info_1;
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 = 0;
|
|
Packit Service |
7c31a4 |
mask_events = handle->mask_events_1;
|
|
Packit Service |
7c31a4 |
} else if (req == &handle->poll_req_2) {
|
|
Packit Service |
7c31a4 |
afd_poll_info = &handle->afd_poll_info_2;
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 = 0;
|
|
Packit Service |
7c31a4 |
mask_events = handle->mask_events_2;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
assert(0);
|
|
Packit Service |
7c31a4 |
return;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Report an error unless the select was just interrupted. */
|
|
Packit Service |
7c31a4 |
if (!REQ_SUCCESS(req)) {
|
|
Packit Service |
7c31a4 |
DWORD error = GET_REQ_SOCK_ERROR(req);
|
|
Packit Service |
7c31a4 |
if (error != WSAEINTR && handle->events != 0) {
|
|
Packit Service |
7c31a4 |
handle->events = 0; /* Stop the watcher */
|
|
Packit Service |
7c31a4 |
handle->poll_cb(handle, uv_translate_sys_error(error), 0);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
} else if (afd_poll_info->NumberOfHandles >= 1) {
|
|
Packit Service |
7c31a4 |
unsigned char events = 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE |
|
|
Packit Service |
7c31a4 |
AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) {
|
|
Packit Service |
7c31a4 |
events |= UV_READABLE;
|
|
Packit Service |
7c31a4 |
if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) {
|
|
Packit Service |
7c31a4 |
events |= UV_DISCONNECT;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND |
|
|
Packit Service |
7c31a4 |
AFD_POLL_CONNECT_FAIL)) != 0) {
|
|
Packit Service |
7c31a4 |
events |= UV_WRITABLE;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
events &= handle->events & ~mask_events;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {
|
|
Packit Service |
7c31a4 |
/* Stop polling. */
|
|
Packit Service |
7c31a4 |
handle->events = 0;
|
|
Packit Service |
7c31a4 |
if (uv__is_active(handle))
|
|
Packit Service |
7c31a4 |
uv__handle_stop(handle);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (events != 0) {
|
|
Packit Service |
7c31a4 |
handle->poll_cb(handle, 0, events);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if ((handle->events & ~(handle->submitted_events_1 |
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2)) != 0) {
|
|
Packit Service |
7c31a4 |
uv__fast_poll_submit_poll_req(loop, handle);
|
|
Packit Service |
7c31a4 |
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 == 0 &&
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 == 0) {
|
|
Packit Service |
7c31a4 |
uv_want_endgame(loop, (uv_handle_t*) handle);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp,
|
|
Packit Service |
7c31a4 |
WSAPROTOCOL_INFOW* protocol_info) {
|
|
Packit Service |
7c31a4 |
SOCKET sock = 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
sock = WSASocketW(protocol_info->iAddressFamily,
|
|
Packit Service |
7c31a4 |
protocol_info->iSocketType,
|
|
Packit Service |
7c31a4 |
protocol_info->iProtocol,
|
|
Packit Service |
7c31a4 |
protocol_info,
|
|
Packit Service |
7c31a4 |
0,
|
|
Packit Service |
7c31a4 |
WSA_FLAG_OVERLAPPED);
|
|
Packit Service |
7c31a4 |
if (sock == INVALID_SOCKET) {
|
|
Packit Service |
7c31a4 |
return INVALID_SOCKET;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
|
|
Packit Service |
7c31a4 |
goto error;
|
|
Packit Service |
7c31a4 |
};
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (CreateIoCompletionPort((HANDLE) sock,
|
|
Packit Service |
7c31a4 |
iocp,
|
|
Packit Service |
7c31a4 |
(ULONG_PTR) sock,
|
|
Packit Service |
7c31a4 |
0) == NULL) {
|
|
Packit Service |
7c31a4 |
goto error;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
return sock;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
error:
|
|
Packit Service |
7c31a4 |
closesocket(sock);
|
|
Packit Service |
7c31a4 |
return INVALID_SOCKET;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
|
|
Packit Service |
7c31a4 |
WSAPROTOCOL_INFOW* protocol_info) {
|
|
Packit Service |
7c31a4 |
int index, i;
|
|
Packit Service |
7c31a4 |
SOCKET peer_socket;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
index = -1;
|
|
Packit Service |
7c31a4 |
for (i = 0; (size_t) i < ARRAY_SIZE(uv_msafd_provider_ids); i++) {
|
|
Packit Service |
7c31a4 |
if (memcmp((void*) &protocol_info->ProviderId,
|
|
Packit Service |
7c31a4 |
(void*) &uv_msafd_provider_ids[i],
|
|
Packit Service |
7c31a4 |
sizeof protocol_info->ProviderId) == 0) {
|
|
Packit Service |
7c31a4 |
index = i;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Check if the protocol uses an msafd socket. */
|
|
Packit Service |
7c31a4 |
if (index < 0) {
|
|
Packit Service |
7c31a4 |
return INVALID_SOCKET;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* If we didn't (try) to create a peer socket yet, try to make one. Don't try
|
|
Packit Service |
7c31a4 |
* again if the peer socket creation failed earlier for the same protocol. */
|
|
Packit Service |
7c31a4 |
peer_socket = loop->poll_peer_sockets[index];
|
|
Packit Service |
7c31a4 |
if (peer_socket == 0) {
|
|
Packit Service |
7c31a4 |
peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
|
|
Packit Service |
7c31a4 |
loop->poll_peer_sockets[index] = peer_socket;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
return peer_socket;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
|
|
Packit Service |
7c31a4 |
uv_req_t* req = (uv_req_t*) arg;
|
|
Packit Service |
7c31a4 |
uv_poll_t* handle = (uv_poll_t*) req->data;
|
|
Packit Service |
7c31a4 |
unsigned char reported_events;
|
|
Packit Service |
7c31a4 |
int r;
|
|
Packit Service |
7c31a4 |
uv_single_fd_set_t rfds, wfds, efds;
|
|
Packit Service |
7c31a4 |
struct timeval timeout;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
assert(handle->type == UV_POLL);
|
|
Packit Service |
7c31a4 |
assert(req->type == UV_POLL_REQ);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->events & UV_READABLE) {
|
|
Packit Service |
7c31a4 |
rfds.fd_count = 1;
|
|
Packit Service |
7c31a4 |
rfds.fd_array[0] = handle->socket;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
rfds.fd_count = 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->events & UV_WRITABLE) {
|
|
Packit Service |
7c31a4 |
wfds.fd_count = 1;
|
|
Packit Service |
7c31a4 |
wfds.fd_array[0] = handle->socket;
|
|
Packit Service |
7c31a4 |
efds.fd_count = 1;
|
|
Packit Service |
7c31a4 |
efds.fd_array[0] = handle->socket;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
wfds.fd_count = 0;
|
|
Packit Service |
7c31a4 |
efds.fd_count = 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Make the select() time out after 3 minutes. If select() hangs because the
|
|
Packit Service |
7c31a4 |
* user closed the socket, we will at least not hang indefinitely. */
|
|
Packit Service |
7c31a4 |
timeout.tv_sec = 3 * 60;
|
|
Packit Service |
7c31a4 |
timeout.tv_usec = 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout);
|
|
Packit Service |
7c31a4 |
if (r == SOCKET_ERROR) {
|
|
Packit Service |
7c31a4 |
/* Queue this req, reporting an error. */
|
|
Packit Service |
7c31a4 |
SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError());
|
|
Packit Service |
7c31a4 |
POST_COMPLETION_FOR_REQ(handle->loop, req);
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
reported_events = 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (r > 0) {
|
|
Packit Service |
7c31a4 |
if (rfds.fd_count > 0) {
|
|
Packit Service |
7c31a4 |
assert(rfds.fd_count == 1);
|
|
Packit Service |
7c31a4 |
assert(rfds.fd_array[0] == handle->socket);
|
|
Packit Service |
7c31a4 |
reported_events |= UV_READABLE;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (wfds.fd_count > 0) {
|
|
Packit Service |
7c31a4 |
assert(wfds.fd_count == 1);
|
|
Packit Service |
7c31a4 |
assert(wfds.fd_array[0] == handle->socket);
|
|
Packit Service |
7c31a4 |
reported_events |= UV_WRITABLE;
|
|
Packit Service |
7c31a4 |
} else if (efds.fd_count > 0) {
|
|
Packit Service |
7c31a4 |
assert(efds.fd_count == 1);
|
|
Packit Service |
7c31a4 |
assert(efds.fd_array[0] == handle->socket);
|
|
Packit Service |
7c31a4 |
reported_events |= UV_WRITABLE;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
SET_REQ_SUCCESS(req);
|
|
Packit Service |
7c31a4 |
req->u.io.overlapped.InternalHigh = (DWORD) reported_events;
|
|
Packit Service |
7c31a4 |
POST_COMPLETION_FOR_REQ(handle->loop, req);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
|
Packit Service |
7c31a4 |
uv_req_t* req;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Find a yet unsubmitted req to submit. */
|
|
Packit Service |
7c31a4 |
if (handle->submitted_events_1 == 0) {
|
|
Packit Service |
7c31a4 |
req = &handle->poll_req_1;
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 = handle->events;
|
|
Packit Service |
7c31a4 |
handle->mask_events_1 = 0;
|
|
Packit Service |
7c31a4 |
handle->mask_events_2 = handle->events;
|
|
Packit Service |
7c31a4 |
} else if (handle->submitted_events_2 == 0) {
|
|
Packit Service |
7c31a4 |
req = &handle->poll_req_2;
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 = handle->events;
|
|
Packit Service |
7c31a4 |
handle->mask_events_1 = handle->events;
|
|
Packit Service |
7c31a4 |
handle->mask_events_2 = 0;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
assert(0);
|
|
Packit Service |
7c31a4 |
return;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (!QueueUserWorkItem(uv__slow_poll_thread_proc,
|
|
Packit Service |
7c31a4 |
(void*) req,
|
|
Packit Service |
7c31a4 |
WT_EXECUTELONGFUNCTION)) {
|
|
Packit Service |
7c31a4 |
/* Make this req pending, reporting an error. */
|
|
Packit Service |
7c31a4 |
SET_REQ_ERROR(req, GetLastError());
|
|
Packit Service |
7c31a4 |
uv_insert_pending_req(loop, req);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|
Packit Service |
7c31a4 |
uv_req_t* req) {
|
|
Packit Service |
7c31a4 |
unsigned char mask_events;
|
|
Packit Service |
7c31a4 |
int err;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (req == &handle->poll_req_1) {
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 = 0;
|
|
Packit Service |
7c31a4 |
mask_events = handle->mask_events_1;
|
|
Packit Service |
7c31a4 |
} else if (req == &handle->poll_req_2) {
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 = 0;
|
|
Packit Service |
7c31a4 |
mask_events = handle->mask_events_2;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
assert(0);
|
|
Packit Service |
7c31a4 |
return;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (!REQ_SUCCESS(req)) {
|
|
Packit Service |
7c31a4 |
/* Error. */
|
|
Packit Service |
7c31a4 |
if (handle->events != 0) {
|
|
Packit Service |
7c31a4 |
err = GET_REQ_ERROR(req);
|
|
Packit Service |
7c31a4 |
handle->events = 0; /* Stop the watcher */
|
|
Packit Service |
7c31a4 |
handle->poll_cb(handle, uv_translate_sys_error(err), 0);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
/* Got some events. */
|
|
Packit Service |
7c31a4 |
int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events;
|
|
Packit Service |
7c31a4 |
if (events != 0) {
|
|
Packit Service |
7c31a4 |
handle->poll_cb(handle, 0, events);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if ((handle->events & ~(handle->submitted_events_1 |
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2)) != 0) {
|
|
Packit Service |
7c31a4 |
uv__slow_poll_submit_poll_req(loop, handle);
|
|
Packit Service |
7c31a4 |
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 == 0 &&
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 == 0) {
|
|
Packit Service |
7c31a4 |
uv_want_endgame(loop, (uv_handle_t*) handle);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
|
|
Packit Service |
7c31a4 |
return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd));
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
|
Packit Service |
7c31a4 |
uv_os_sock_t socket) {
|
|
Packit Service |
7c31a4 |
WSAPROTOCOL_INFOW protocol_info;
|
|
Packit Service |
7c31a4 |
int len;
|
|
Packit Service |
7c31a4 |
SOCKET peer_socket, base_socket;
|
|
Packit Service |
7c31a4 |
DWORD bytes;
|
|
Packit Service |
7c31a4 |
DWORD yes = 1;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Set the socket to nonblocking mode */
|
|
Packit Service |
7c31a4 |
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
|
|
Packit Service |
7c31a4 |
return uv_translate_sys_error(WSAGetLastError());
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Try to obtain a base handle for the socket. This increases this chances that
|
|
Packit Service |
7c31a4 |
* we find an AFD handle and are able to use the fast poll mechanism. This will
|
|
Packit Service |
7c31a4 |
* always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE
|
|
Packit Service |
7c31a4 |
* ioctl. */
|
|
Packit Service |
7c31a4 |
#ifndef NDEBUG
|
|
Packit Service |
7c31a4 |
base_socket = INVALID_SOCKET;
|
|
Packit Service |
7c31a4 |
#endif
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (WSAIoctl(socket,
|
|
Packit Service |
7c31a4 |
SIO_BASE_HANDLE,
|
|
Packit Service |
7c31a4 |
NULL,
|
|
Packit Service |
7c31a4 |
0,
|
|
Packit Service |
7c31a4 |
&base_socket,
|
|
Packit Service |
7c31a4 |
sizeof base_socket,
|
|
Packit Service |
7c31a4 |
&bytes,
|
|
Packit Service |
7c31a4 |
NULL,
|
|
Packit Service |
7c31a4 |
NULL) == 0) {
|
|
Packit Service |
7c31a4 |
assert(base_socket != 0 && base_socket != INVALID_SOCKET);
|
|
Packit Service |
7c31a4 |
socket = base_socket;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
|
|
Packit Service |
7c31a4 |
handle->socket = socket;
|
|
Packit Service |
7c31a4 |
handle->events = 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Obtain protocol information about the socket. */
|
|
Packit Service |
7c31a4 |
len = sizeof protocol_info;
|
|
Packit Service |
7c31a4 |
if (getsockopt(socket,
|
|
Packit Service |
7c31a4 |
SOL_SOCKET,
|
|
Packit Service |
7c31a4 |
SO_PROTOCOL_INFOW,
|
|
Packit Service |
7c31a4 |
(char*) &protocol_info,
|
|
Packit Service |
7c31a4 |
&len) != 0) {
|
|
Packit Service |
7c31a4 |
return uv_translate_sys_error(WSAGetLastError());
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Get the peer socket that is needed to enable fast poll. If the returned
|
|
Packit Service |
7c31a4 |
* value is NULL, the protocol is not implemented by MSAFD and we'll have to
|
|
Packit Service |
7c31a4 |
* use slow mode. */
|
|
Packit Service |
7c31a4 |
peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (peer_socket != INVALID_SOCKET) {
|
|
Packit Service |
7c31a4 |
/* Initialize fast poll specific fields. */
|
|
Packit Service |
7c31a4 |
handle->peer_socket = peer_socket;
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
/* Initialize slow poll specific fields. */
|
|
Packit Service |
7c31a4 |
handle->flags |= UV_HANDLE_POLL_SLOW;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Initialize 2 poll reqs. */
|
|
Packit Service |
7c31a4 |
handle->submitted_events_1 = 0;
|
|
Packit Service |
7c31a4 |
UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ);
|
|
Packit Service |
7c31a4 |
handle->poll_req_1.data = handle;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 = 0;
|
|
Packit Service |
7c31a4 |
UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ);
|
|
Packit Service |
7c31a4 |
handle->poll_req_2.data = handle;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
static int uv__poll_set(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
|
Packit Service |
7c31a4 |
int submitted_events;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
assert(handle->type == UV_POLL);
|
|
Packit Service |
7c31a4 |
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
|
Packit Service |
7c31a4 |
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
handle->events = events;
|
|
Packit Service |
7c31a4 |
handle->poll_cb = cb;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->events == 0) {
|
|
Packit Service |
7c31a4 |
uv__handle_stop(handle);
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
uv__handle_start(handle);
|
|
Packit Service |
7c31a4 |
submitted_events = handle->submitted_events_1 | handle->submitted_events_2;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->events & ~submitted_events) {
|
|
Packit Service |
7c31a4 |
if (handle->flags & UV_HANDLE_POLL_SLOW) {
|
|
Packit Service |
7c31a4 |
uv__slow_poll_submit_poll_req(handle->loop, handle);
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
uv__fast_poll_submit_poll_req(handle->loop, handle);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
|
Packit Service |
7c31a4 |
return uv__poll_set(handle, events, cb);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
int uv_poll_stop(uv_poll_t* handle) {
|
|
Packit Service |
7c31a4 |
return uv__poll_set(handle, 0, handle->poll_cb);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
|
|
Packit Service |
7c31a4 |
if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
|
|
Packit Service |
7c31a4 |
uv__fast_poll_process_poll_req(loop, handle, req);
|
|
Packit Service |
7c31a4 |
} else {
|
|
Packit Service |
7c31a4 |
uv__slow_poll_process_poll_req(loop, handle, req);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
|
Packit Service |
7c31a4 |
AFD_POLL_INFO afd_poll_info;
|
|
Packit Service |
7c31a4 |
DWORD error;
|
|
Packit Service |
7c31a4 |
int result;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
handle->events = 0;
|
|
Packit Service |
7c31a4 |
uv__handle_closing(handle);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->submitted_events_1 == 0 &&
|
|
Packit Service |
7c31a4 |
handle->submitted_events_2 == 0) {
|
|
Packit Service |
7c31a4 |
uv_want_endgame(loop, (uv_handle_t*) handle);
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (handle->flags & UV_HANDLE_POLL_SLOW)
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
/* Cancel outstanding poll requests by executing another, unique poll
|
|
Packit Service |
7c31a4 |
* request that forces the outstanding ones to return. */
|
|
Packit Service |
7c31a4 |
afd_poll_info.Exclusive = TRUE;
|
|
Packit Service |
7c31a4 |
afd_poll_info.NumberOfHandles = 1;
|
|
Packit Service |
7c31a4 |
afd_poll_info.Timeout.QuadPart = INT64_MAX;
|
|
Packit Service |
7c31a4 |
afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
|
|
Packit Service |
7c31a4 |
afd_poll_info.Handles[0].Status = 0;
|
|
Packit Service |
7c31a4 |
afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
result = uv_msafd_poll(handle->socket,
|
|
Packit Service |
7c31a4 |
&afd_poll_info,
|
|
Packit Service |
7c31a4 |
uv__get_afd_poll_info_dummy(),
|
|
Packit Service |
7c31a4 |
uv__get_overlapped_dummy());
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
if (result == SOCKET_ERROR) {
|
|
Packit Service |
7c31a4 |
error = WSAGetLastError();
|
|
Packit Service |
7c31a4 |
if (error != WSA_IO_PENDING)
|
|
Packit Service |
7c31a4 |
return uv_translate_sys_error(error);
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
return 0;
|
|
Packit Service |
7c31a4 |
}
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
|
|
Packit Service |
7c31a4 |
assert(handle->flags & UV_HANDLE_CLOSING);
|
|
Packit Service |
7c31a4 |
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
assert(handle->submitted_events_1 == 0);
|
|
Packit Service |
7c31a4 |
assert(handle->submitted_events_2 == 0);
|
|
Packit Service |
7c31a4 |
|
|
Packit Service |
7c31a4 |
uv__handle_close(handle);
|
|
Packit Service |
7c31a4 |
}
|