|
160
|
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
|
2 *
|
|
|
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
4 * of this software and associated documentation files (the "Software"), to
|
|
|
5 * deal in the Software without restriction, including without limitation the
|
|
|
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
7 * sell copies of the Software, and to permit persons to whom the Software is
|
|
|
8 * furnished to do so, subject to the following conditions:
|
|
|
9 *
|
|
|
10 * The above copyright notice and this permission notice shall be included in
|
|
|
11 * all copies or substantial portions of the Software.
|
|
|
12 *
|
|
|
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
19 * IN THE SOFTWARE.
|
|
|
20 */
|
|
|
21
|
|
|
22 #include <assert.h>
|
|
|
23 #include <io.h>
|
|
|
24
|
|
|
25 #include "uv.h"
|
|
|
26 #include "internal.h"
|
|
|
27 #include "handle-inl.h"
|
|
|
28 #include "req-inl.h"
|
|
|
29
|
|
|
30
|
|
|
31 static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {
|
|
|
32 {0xe70f1aa0, 0xab8b, 0x11cf,
|
|
|
33 {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
|
|
|
34 {0xf9eab0c0, 0x26d4, 0x11d0,
|
|
|
35 {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
|
|
|
36 {0x9fc48064, 0x7298, 0x43e4,
|
|
|
37 {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}},
|
|
|
38 {0xa00943d9, 0x9c2e, 0x4633,
|
|
|
39 {0x9b, 0x59, 0x00, 0x57, 0xa3, 0x16, 0x09, 0x94}}
|
|
|
40 };
|
|
|
41
|
|
|
42 typedef struct uv_single_fd_set_s {
|
|
|
43 unsigned int fd_count;
|
|
|
44 SOCKET fd_array[1];
|
|
|
45 } uv_single_fd_set_t;
|
|
|
46
|
|
|
47
|
|
|
48 static OVERLAPPED overlapped_dummy_;
|
|
|
49 static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT;
|
|
|
50
|
|
|
51 static AFD_POLL_INFO afd_poll_info_dummy_;
|
|
|
52
|
|
|
53
|
|
|
54 static void uv__init_overlapped_dummy(void) {
|
|
|
55 HANDLE event;
|
|
|
56
|
|
|
57 event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
|
|
58 if (event == NULL)
|
|
|
59 uv_fatal_error(GetLastError(), "CreateEvent");
|
|
|
60
|
|
|
61 memset(&overlapped_dummy_, 0, sizeof overlapped_dummy_);
|
|
|
62 overlapped_dummy_.hEvent = (HANDLE) ((uintptr_t) event | 1);
|
|
|
63 }
|
|
|
64
|
|
|
65
|
|
|
66 static OVERLAPPED* uv__get_overlapped_dummy(void) {
|
|
|
67 uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy);
|
|
|
68 return &overlapped_dummy_;
|
|
|
69 }
|
|
|
70
|
|
|
71
|
|
|
72 static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
|
|
|
73 return &afd_poll_info_dummy_;
|
|
|
74 }
|
|
|
75
|
|
|
76
|
|
|
77 static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
|
|
78 uv_req_t* req;
|
|
|
79 AFD_POLL_INFO* afd_poll_info;
|
|
|
80 int result;
|
|
|
81
|
|
|
82 /* Find a yet unsubmitted req to submit. */
|
|
|
83 if (handle->submitted_events_1 == 0) {
|
|
|
84 req = &handle->poll_req_1;
|
|
|
85 afd_poll_info = &handle->afd_poll_info_1;
|
|
|
86 handle->submitted_events_1 = handle->events;
|
|
|
87 handle->mask_events_1 = 0;
|
|
|
88 handle->mask_events_2 = handle->events;
|
|
|
89 } else if (handle->submitted_events_2 == 0) {
|
|
|
90 req = &handle->poll_req_2;
|
|
|
91 afd_poll_info = &handle->afd_poll_info_2;
|
|
|
92 handle->submitted_events_2 = handle->events;
|
|
|
93 handle->mask_events_1 = handle->events;
|
|
|
94 handle->mask_events_2 = 0;
|
|
|
95 } else {
|
|
|
96 /* Just wait until there's an unsubmitted req. This will happen almost
|
|
|
97 * immediately as one of the 2 outstanding requests is about to return.
|
|
|
98 * When this happens, uv__fast_poll_process_poll_req will be called, and
|
|
|
99 * the pending events, if needed, will be processed in a subsequent
|
|
|
100 * request. */
|
|
|
101 return;
|
|
|
102 }
|
|
|
103
|
|
|
104 /* Setting Exclusive to TRUE makes the other poll request return if there is
|
|
|
105 * any. */
|
|
|
106 afd_poll_info->Exclusive = TRUE;
|
|
|
107 afd_poll_info->NumberOfHandles = 1;
|
|
|
108 afd_poll_info->Timeout.QuadPart = INT64_MAX;
|
|
|
109 afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;
|
|
|
110 afd_poll_info->Handles[0].Status = 0;
|
|
|
111 afd_poll_info->Handles[0].Events = 0;
|
|
|
112
|
|
|
113 if (handle->events & UV_READABLE) {
|
|
|
114 afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE |
|
|
|
115 AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT;
|
|
|
116 } else {
|
|
|
117 if (handle->events & UV_DISCONNECT) {
|
|
|
118 afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT;
|
|
|
119 }
|
|
|
120 }
|
|
|
121 if (handle->events & UV_WRITABLE) {
|
|
|
122 afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL;
|
|
|
123 }
|
|
|
124
|
|
|
125 memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped);
|
|
|
126
|
|
|
127 result = uv__msafd_poll((SOCKET) handle->peer_socket,
|
|
|
128 afd_poll_info,
|
|
|
129 afd_poll_info,
|
|
|
130 &req->u.io.overlapped);
|
|
|
131 if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
|
|
|
132 /* Queue this req, reporting an error. */
|
|
|
133 SET_REQ_ERROR(req, WSAGetLastError());
|
|
|
134 uv__insert_pending_req(loop, req);
|
|
|
135 }
|
|
|
136 }
|
|
|
137
|
|
|
138
|
|
|
139 static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|
|
140 uv_req_t* req) {
|
|
|
141 unsigned char mask_events;
|
|
|
142 AFD_POLL_INFO* afd_poll_info;
|
|
|
143
|
|
|
144 if (req == &handle->poll_req_1) {
|
|
|
145 afd_poll_info = &handle->afd_poll_info_1;
|
|
|
146 handle->submitted_events_1 = 0;
|
|
|
147 mask_events = handle->mask_events_1;
|
|
|
148 } else if (req == &handle->poll_req_2) {
|
|
|
149 afd_poll_info = &handle->afd_poll_info_2;
|
|
|
150 handle->submitted_events_2 = 0;
|
|
|
151 mask_events = handle->mask_events_2;
|
|
|
152 } else {
|
|
|
153 assert(0);
|
|
|
154 return;
|
|
|
155 }
|
|
|
156
|
|
|
157 /* Report an error unless the select was just interrupted. */
|
|
|
158 if (!REQ_SUCCESS(req)) {
|
|
|
159 DWORD error = GET_REQ_SOCK_ERROR(req);
|
|
|
160 if (error != WSAEINTR && handle->events != 0) {
|
|
|
161 handle->events = 0; /* Stop the watcher */
|
|
|
162 handle->poll_cb(handle, uv_translate_sys_error(error), 0);
|
|
|
163 }
|
|
|
164
|
|
|
165 } else if (afd_poll_info->NumberOfHandles >= 1) {
|
|
|
166 unsigned char events = 0;
|
|
|
167
|
|
|
168 if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE |
|
|
|
169 AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) {
|
|
|
170 events |= UV_READABLE;
|
|
|
171 if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) {
|
|
|
172 events |= UV_DISCONNECT;
|
|
|
173 }
|
|
|
174 }
|
|
|
175 if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND |
|
|
|
176 AFD_POLL_CONNECT_FAIL)) != 0) {
|
|
|
177 events |= UV_WRITABLE;
|
|
|
178 }
|
|
|
179
|
|
|
180 events &= handle->events & ~mask_events;
|
|
|
181
|
|
|
182 if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {
|
|
|
183 /* Stop polling. */
|
|
|
184 handle->events = 0;
|
|
|
185 if (uv__is_active(handle))
|
|
|
186 uv__handle_stop(handle);
|
|
|
187 }
|
|
|
188
|
|
|
189 if (events != 0) {
|
|
|
190 handle->poll_cb(handle, 0, events);
|
|
|
191 }
|
|
|
192 }
|
|
|
193
|
|
|
194 if ((handle->events & ~(handle->submitted_events_1 |
|
|
|
195 handle->submitted_events_2)) != 0) {
|
|
|
196 uv__fast_poll_submit_poll_req(loop, handle);
|
|
|
197 } else if ((handle->flags & UV_HANDLE_CLOSING) &&
|
|
|
198 handle->submitted_events_1 == 0 &&
|
|
|
199 handle->submitted_events_2 == 0) {
|
|
|
200 uv__want_endgame(loop, (uv_handle_t*) handle);
|
|
|
201 }
|
|
|
202 }
|
|
|
203
|
|
|
204
|
|
|
205 static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp,
|
|
|
206 WSAPROTOCOL_INFOW* protocol_info) {
|
|
|
207 SOCKET sock = 0;
|
|
|
208
|
|
|
209 sock = WSASocketW(protocol_info->iAddressFamily,
|
|
|
210 protocol_info->iSocketType,
|
|
|
211 protocol_info->iProtocol,
|
|
|
212 protocol_info,
|
|
|
213 0,
|
|
|
214 WSA_FLAG_OVERLAPPED);
|
|
|
215 if (sock == INVALID_SOCKET) {
|
|
|
216 return INVALID_SOCKET;
|
|
|
217 }
|
|
|
218
|
|
|
219 if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
|
|
|
220 goto error;
|
|
|
221 };
|
|
|
222
|
|
|
223 if (CreateIoCompletionPort((HANDLE) sock,
|
|
|
224 iocp,
|
|
|
225 (ULONG_PTR) sock,
|
|
|
226 0) == NULL) {
|
|
|
227 goto error;
|
|
|
228 }
|
|
|
229
|
|
|
230 return sock;
|
|
|
231
|
|
|
232 error:
|
|
|
233 closesocket(sock);
|
|
|
234 return INVALID_SOCKET;
|
|
|
235 }
|
|
|
236
|
|
|
237
|
|
|
238 static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
|
|
|
239 WSAPROTOCOL_INFOW* protocol_info) {
|
|
|
240 int index, i;
|
|
|
241 SOCKET peer_socket;
|
|
|
242
|
|
|
243 index = -1;
|
|
|
244 for (i = 0; (size_t) i < ARRAY_SIZE(uv_msafd_provider_ids); i++) {
|
|
|
245 if (memcmp((void*) &protocol_info->ProviderId,
|
|
|
246 (void*) &uv_msafd_provider_ids[i],
|
|
|
247 sizeof protocol_info->ProviderId) == 0) {
|
|
|
248 index = i;
|
|
|
249 }
|
|
|
250 }
|
|
|
251
|
|
|
252 /* Check if the protocol uses an msafd socket. */
|
|
|
253 if (index < 0) {
|
|
|
254 return INVALID_SOCKET;
|
|
|
255 }
|
|
|
256
|
|
|
257 /* If we didn't (try) to create a peer socket yet, try to make one. Don't try
|
|
|
258 * again if the peer socket creation failed earlier for the same protocol. */
|
|
|
259 peer_socket = loop->poll_peer_sockets[index];
|
|
|
260 if (peer_socket == 0) {
|
|
|
261 peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
|
|
|
262 loop->poll_peer_sockets[index] = peer_socket;
|
|
|
263 }
|
|
|
264
|
|
|
265 return peer_socket;
|
|
|
266 }
|
|
|
267
|
|
|
268
|
|
|
269 static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
|
|
|
270 uv_req_t* req = (uv_req_t*) arg;
|
|
|
271 uv_poll_t* handle = (uv_poll_t*) req->data;
|
|
|
272 unsigned char reported_events;
|
|
|
273 int r;
|
|
|
274 uv_single_fd_set_t rfds, wfds, efds;
|
|
|
275 struct timeval timeout;
|
|
|
276
|
|
|
277 assert(handle->type == UV_POLL);
|
|
|
278 assert(req->type == UV_POLL_REQ);
|
|
|
279
|
|
|
280 if (handle->events & UV_READABLE) {
|
|
|
281 rfds.fd_count = 1;
|
|
|
282 rfds.fd_array[0] = handle->socket;
|
|
|
283 } else {
|
|
|
284 rfds.fd_count = 0;
|
|
|
285 }
|
|
|
286
|
|
|
287 if (handle->events & UV_WRITABLE) {
|
|
|
288 wfds.fd_count = 1;
|
|
|
289 wfds.fd_array[0] = handle->socket;
|
|
|
290 efds.fd_count = 1;
|
|
|
291 efds.fd_array[0] = handle->socket;
|
|
|
292 } else {
|
|
|
293 wfds.fd_count = 0;
|
|
|
294 efds.fd_count = 0;
|
|
|
295 }
|
|
|
296
|
|
|
297 /* Make the select() time out after 3 minutes. If select() hangs because the
|
|
|
298 * user closed the socket, we will at least not hang indefinitely. */
|
|
|
299 timeout.tv_sec = 3 * 60;
|
|
|
300 timeout.tv_usec = 0;
|
|
|
301
|
|
|
302 r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout);
|
|
|
303 if (r == SOCKET_ERROR) {
|
|
|
304 /* Queue this req, reporting an error. */
|
|
|
305 SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError());
|
|
|
306 POST_COMPLETION_FOR_REQ(handle->loop, req);
|
|
|
307 return 0;
|
|
|
308 }
|
|
|
309
|
|
|
310 reported_events = 0;
|
|
|
311
|
|
|
312 if (r > 0) {
|
|
|
313 if (rfds.fd_count > 0) {
|
|
|
314 assert(rfds.fd_count == 1);
|
|
|
315 assert(rfds.fd_array[0] == handle->socket);
|
|
|
316 reported_events |= UV_READABLE;
|
|
|
317 }
|
|
|
318
|
|
|
319 if (wfds.fd_count > 0) {
|
|
|
320 assert(wfds.fd_count == 1);
|
|
|
321 assert(wfds.fd_array[0] == handle->socket);
|
|
|
322 reported_events |= UV_WRITABLE;
|
|
|
323 } else if (efds.fd_count > 0) {
|
|
|
324 assert(efds.fd_count == 1);
|
|
|
325 assert(efds.fd_array[0] == handle->socket);
|
|
|
326 reported_events |= UV_WRITABLE;
|
|
|
327 }
|
|
|
328 }
|
|
|
329
|
|
|
330 SET_REQ_SUCCESS(req);
|
|
|
331 req->u.io.overlapped.InternalHigh = (DWORD) reported_events;
|
|
|
332 POST_COMPLETION_FOR_REQ(handle->loop, req);
|
|
|
333
|
|
|
334 return 0;
|
|
|
335 }
|
|
|
336
|
|
|
337
|
|
|
338 static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
|
|
339 uv_req_t* req;
|
|
|
340
|
|
|
341 /* Find a yet unsubmitted req to submit. */
|
|
|
342 if (handle->submitted_events_1 == 0) {
|
|
|
343 req = &handle->poll_req_1;
|
|
|
344 handle->submitted_events_1 = handle->events;
|
|
|
345 handle->mask_events_1 = 0;
|
|
|
346 handle->mask_events_2 = handle->events;
|
|
|
347 } else if (handle->submitted_events_2 == 0) {
|
|
|
348 req = &handle->poll_req_2;
|
|
|
349 handle->submitted_events_2 = handle->events;
|
|
|
350 handle->mask_events_1 = handle->events;
|
|
|
351 handle->mask_events_2 = 0;
|
|
|
352 } else {
|
|
|
353 assert(0);
|
|
|
354 return;
|
|
|
355 }
|
|
|
356
|
|
|
357 if (!QueueUserWorkItem(uv__slow_poll_thread_proc,
|
|
|
358 (void*) req,
|
|
|
359 WT_EXECUTELONGFUNCTION)) {
|
|
|
360 /* Make this req pending, reporting an error. */
|
|
|
361 SET_REQ_ERROR(req, GetLastError());
|
|
|
362 uv__insert_pending_req(loop, req);
|
|
|
363 }
|
|
|
364 }
|
|
|
365
|
|
|
366
|
|
|
367
|
|
|
368 static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|
|
369 uv_req_t* req) {
|
|
|
370 unsigned char mask_events;
|
|
|
371 int err;
|
|
|
372
|
|
|
373 if (req == &handle->poll_req_1) {
|
|
|
374 handle->submitted_events_1 = 0;
|
|
|
375 mask_events = handle->mask_events_1;
|
|
|
376 } else if (req == &handle->poll_req_2) {
|
|
|
377 handle->submitted_events_2 = 0;
|
|
|
378 mask_events = handle->mask_events_2;
|
|
|
379 } else {
|
|
|
380 assert(0);
|
|
|
381 return;
|
|
|
382 }
|
|
|
383
|
|
|
384 if (!REQ_SUCCESS(req)) {
|
|
|
385 /* Error. */
|
|
|
386 if (handle->events != 0) {
|
|
|
387 err = GET_REQ_ERROR(req);
|
|
|
388 handle->events = 0; /* Stop the watcher */
|
|
|
389 handle->poll_cb(handle, uv_translate_sys_error(err), 0);
|
|
|
390 }
|
|
|
391 } else {
|
|
|
392 /* Got some events. */
|
|
|
393 int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events;
|
|
|
394 if (events != 0) {
|
|
|
395 handle->poll_cb(handle, 0, events);
|
|
|
396 }
|
|
|
397 }
|
|
|
398
|
|
|
399 if ((handle->events & ~(handle->submitted_events_1 |
|
|
|
400 handle->submitted_events_2)) != 0) {
|
|
|
401 uv__slow_poll_submit_poll_req(loop, handle);
|
|
|
402 } else if ((handle->flags & UV_HANDLE_CLOSING) &&
|
|
|
403 handle->submitted_events_1 == 0 &&
|
|
|
404 handle->submitted_events_2 == 0) {
|
|
|
405 uv__want_endgame(loop, (uv_handle_t*) handle);
|
|
|
406 }
|
|
|
407 }
|
|
|
408
|
|
|
409
|
|
|
410 int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
|
|
|
411 return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd));
|
|
|
412 }
|
|
|
413
|
|
|
414
|
|
|
415 int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
|
|
416 uv_os_sock_t socket) {
|
|
|
417 WSAPROTOCOL_INFOW protocol_info;
|
|
|
418 int len;
|
|
|
419 SOCKET peer_socket, base_socket;
|
|
|
420 DWORD bytes;
|
|
|
421 DWORD yes = 1;
|
|
|
422
|
|
|
423 /* Set the socket to nonblocking mode */
|
|
|
424 if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
|
|
|
425 return uv_translate_sys_error(WSAGetLastError());
|
|
|
426
|
|
|
427 /* Try to obtain a base handle for the socket. This increases this chances that
|
|
|
428 * we find an AFD handle and are able to use the fast poll mechanism.
|
|
|
429 */
|
|
|
430 #ifndef NDEBUG
|
|
|
431 base_socket = INVALID_SOCKET;
|
|
|
432 #endif
|
|
|
433
|
|
|
434 if (WSAIoctl(socket,
|
|
|
435 SIO_BASE_HANDLE,
|
|
|
436 NULL,
|
|
|
437 0,
|
|
|
438 &base_socket,
|
|
|
439 sizeof base_socket,
|
|
|
440 &bytes,
|
|
|
441 NULL,
|
|
|
442 NULL) == 0) {
|
|
|
443 assert(base_socket != 0 && base_socket != INVALID_SOCKET);
|
|
|
444 socket = base_socket;
|
|
|
445 }
|
|
|
446
|
|
|
447 uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
|
|
|
448 handle->socket = socket;
|
|
|
449 handle->events = 0;
|
|
|
450
|
|
|
451 /* Obtain protocol information about the socket. */
|
|
|
452 len = sizeof protocol_info;
|
|
|
453 if (getsockopt(socket,
|
|
|
454 SOL_SOCKET,
|
|
|
455 SO_PROTOCOL_INFOW,
|
|
|
456 (char*) &protocol_info,
|
|
|
457 &len) != 0) {
|
|
|
458 return uv_translate_sys_error(WSAGetLastError());
|
|
|
459 }
|
|
|
460
|
|
|
461 /* Get the peer socket that is needed to enable fast poll. If the returned
|
|
|
462 * value is NULL, the protocol is not implemented by MSAFD and we'll have to
|
|
|
463 * use slow mode. */
|
|
|
464 peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
|
|
|
465
|
|
|
466 if (peer_socket != INVALID_SOCKET) {
|
|
|
467 /* Initialize fast poll specific fields. */
|
|
|
468 handle->peer_socket = peer_socket;
|
|
|
469 } else {
|
|
|
470 /* Initialize slow poll specific fields. */
|
|
|
471 handle->flags |= UV_HANDLE_POLL_SLOW;
|
|
|
472 }
|
|
|
473
|
|
|
474 /* Initialize 2 poll reqs. */
|
|
|
475 handle->submitted_events_1 = 0;
|
|
|
476 UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ);
|
|
|
477 handle->poll_req_1.data = handle;
|
|
|
478
|
|
|
479 handle->submitted_events_2 = 0;
|
|
|
480 UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ);
|
|
|
481 handle->poll_req_2.data = handle;
|
|
|
482
|
|
|
483 return 0;
|
|
|
484 }
|
|
|
485
|
|
|
486
|
|
|
487 static int uv__poll_set(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
|
|
488 int submitted_events;
|
|
|
489
|
|
|
490 assert(handle->type == UV_POLL);
|
|
|
491 assert(!(handle->flags & UV_HANDLE_CLOSING));
|
|
|
492 assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |
|
|
|
493 UV_PRIORITIZED)) == 0);
|
|
|
494
|
|
|
495 handle->events = events;
|
|
|
496 handle->poll_cb = cb;
|
|
|
497
|
|
|
498 if (handle->events == 0) {
|
|
|
499 uv__handle_stop(handle);
|
|
|
500 return 0;
|
|
|
501 }
|
|
|
502
|
|
|
503 uv__handle_start(handle);
|
|
|
504 submitted_events = handle->submitted_events_1 | handle->submitted_events_2;
|
|
|
505
|
|
|
506 if (handle->events & ~submitted_events) {
|
|
|
507 if (handle->flags & UV_HANDLE_POLL_SLOW) {
|
|
|
508 uv__slow_poll_submit_poll_req(handle->loop, handle);
|
|
|
509 } else {
|
|
|
510 uv__fast_poll_submit_poll_req(handle->loop, handle);
|
|
|
511 }
|
|
|
512 }
|
|
|
513
|
|
|
514 return 0;
|
|
|
515 }
|
|
|
516
|
|
|
517
|
|
|
518 int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
|
|
519 return uv__poll_set(handle, events, cb);
|
|
|
520 }
|
|
|
521
|
|
|
522
|
|
|
523 int uv_poll_stop(uv_poll_t* handle) {
|
|
|
524 return uv__poll_set(handle, 0, handle->poll_cb);
|
|
|
525 }
|
|
|
526
|
|
|
527
|
|
|
528 void uv__process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
|
|
|
529 if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
|
|
|
530 uv__fast_poll_process_poll_req(loop, handle, req);
|
|
|
531 } else {
|
|
|
532 uv__slow_poll_process_poll_req(loop, handle, req);
|
|
|
533 }
|
|
|
534 }
|
|
|
535
|
|
|
536
|
|
|
537 int uv__poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
|
|
538 AFD_POLL_INFO afd_poll_info;
|
|
|
539 DWORD error;
|
|
|
540 int result;
|
|
|
541
|
|
|
542 handle->events = 0;
|
|
|
543 uv__handle_closing(handle);
|
|
|
544
|
|
|
545 if (handle->submitted_events_1 == 0 &&
|
|
|
546 handle->submitted_events_2 == 0) {
|
|
|
547 uv__want_endgame(loop, (uv_handle_t*) handle);
|
|
|
548 return 0;
|
|
|
549 }
|
|
|
550
|
|
|
551 if (handle->flags & UV_HANDLE_POLL_SLOW)
|
|
|
552 return 0;
|
|
|
553
|
|
|
554 /* Cancel outstanding poll requests by executing another, unique poll
|
|
|
555 * request that forces the outstanding ones to return. */
|
|
|
556 afd_poll_info.Exclusive = TRUE;
|
|
|
557 afd_poll_info.NumberOfHandles = 1;
|
|
|
558 afd_poll_info.Timeout.QuadPart = INT64_MAX;
|
|
|
559 afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
|
|
|
560 afd_poll_info.Handles[0].Status = 0;
|
|
|
561 afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
|
|
|
562
|
|
|
563 result = uv__msafd_poll(handle->socket,
|
|
|
564 &afd_poll_info,
|
|
|
565 uv__get_afd_poll_info_dummy(),
|
|
|
566 uv__get_overlapped_dummy());
|
|
|
567
|
|
|
568 if (result == SOCKET_ERROR) {
|
|
|
569 error = WSAGetLastError();
|
|
|
570 if (error != WSA_IO_PENDING)
|
|
|
571 return uv_translate_sys_error(error);
|
|
|
572 }
|
|
|
573
|
|
|
574 return 0;
|
|
|
575 }
|
|
|
576
|
|
|
577
|
|
|
578 void uv__poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
|
|
|
579 assert(handle->flags & UV_HANDLE_CLOSING);
|
|
|
580 assert(!(handle->flags & UV_HANDLE_CLOSED));
|
|
|
581
|
|
|
582 assert(handle->submitted_events_1 == 0);
|
|
|
583 assert(handle->submitted_events_2 == 0);
|
|
|
584
|
|
|
585 uv__handle_close(handle);
|
|
|
586 }
|