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 <stdlib.h>
24
25 #include "uv.h"
26 #include "internal.h"
27 #include "handle-inl.h"
28 #include "stream-inl.h"
29 #include "req-inl.h"
30
31
32 /*
33 * Number of simultaneous pending AcceptEx calls.
34 */
35 const unsigned int uv_simultaneous_server_accepts = 32;
36
37 /* A zero-size buffer for use by uv_tcp_read */
38 static char uv_zero_[] = "";
39
uv__tcp_nodelay(uv_tcp_t * handle,SOCKET socket,int enable)40 static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
41 if (setsockopt(socket,
42 IPPROTO_TCP,
43 TCP_NODELAY,
44 (const char*)&enable,
45 sizeof enable) == -1) {
46 return WSAGetLastError();
47 }
48 return 0;
49 }
50
51
uv__tcp_keepalive(uv_tcp_t * handle,SOCKET socket,int enable,unsigned int delay)52 static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
53 if (setsockopt(socket,
54 SOL_SOCKET,
55 SO_KEEPALIVE,
56 (const char*)&enable,
57 sizeof enable) == -1) {
58 return WSAGetLastError();
59 }
60
61 if (enable && setsockopt(socket,
62 IPPROTO_TCP,
63 TCP_KEEPALIVE,
64 (const char*)&delay,
65 sizeof delay) == -1) {
66 return WSAGetLastError();
67 }
68
69 return 0;
70 }
71
72
uv__tcp_set_socket(uv_loop_t * loop,uv_tcp_t * handle,SOCKET socket,int family,int imported)73 static int uv__tcp_set_socket(uv_loop_t* loop,
74 uv_tcp_t* handle,
75 SOCKET socket,
76 int family,
77 int imported) {
78 DWORD yes = 1;
79 int non_ifs_lsp;
80 int err;
81
82 if (handle->socket != INVALID_SOCKET)
83 return UV_EBUSY;
84
85 /* Set the socket to nonblocking mode */
86 if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
87 return WSAGetLastError();
88 }
89
90 /* Make the socket non-inheritable */
91 if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
92 return GetLastError();
93
94 /* Associate it with the I/O completion port. Use uv_handle_t pointer as
95 * completion key. */
96 if (CreateIoCompletionPort((HANDLE)socket,
97 loop->iocp,
98 (ULONG_PTR)socket,
99 0) == NULL) {
100 if (imported) {
101 handle->flags |= UV_HANDLE_EMULATE_IOCP;
102 } else {
103 return GetLastError();
104 }
105 }
106
107 if (family == AF_INET6) {
108 non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6;
109 } else {
110 non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
111 }
112
113 if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
114 UCHAR sfcnm_flags =
115 FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
116 if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags))
117 return GetLastError();
118 handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
119 }
120
121 if (handle->flags & UV_HANDLE_TCP_NODELAY) {
122 err = uv__tcp_nodelay(handle, socket, 1);
123 if (err)
124 return err;
125 }
126
127 /* TODO: Use stored delay. */
128 if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) {
129 err = uv__tcp_keepalive(handle, socket, 1, 60);
130 if (err)
131 return err;
132 }
133
134 handle->socket = socket;
135
136 if (family == AF_INET6) {
137 handle->flags |= UV_HANDLE_IPV6;
138 } else {
139 assert(!(handle->flags & UV_HANDLE_IPV6));
140 }
141
142 return 0;
143 }
144
145
uv_tcp_init_ex(uv_loop_t * loop,uv_tcp_t * handle,unsigned int flags)146 int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {
147 int domain;
148
149 /* Use the lower 8 bits for the domain */
150 domain = flags & 0xFF;
151 if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
152 return UV_EINVAL;
153
154 if (flags & ~0xFF)
155 return UV_EINVAL;
156
157 uv__stream_init(loop, (uv_stream_t*) handle, UV_TCP);
158 handle->tcp.serv.accept_reqs = NULL;
159 handle->tcp.serv.pending_accepts = NULL;
160 handle->socket = INVALID_SOCKET;
161 handle->reqs_pending = 0;
162 handle->tcp.serv.func_acceptex = NULL;
163 handle->tcp.conn.func_connectex = NULL;
164 handle->tcp.serv.processed_accepts = 0;
165 handle->delayed_error = 0;
166
167 /* If anything fails beyond this point we need to remove the handle from
168 * the handle queue, since it was added by uv__handle_init in uv__stream_init.
169 */
170
171 if (domain != AF_UNSPEC) {
172 SOCKET sock;
173 DWORD err;
174
175 sock = socket(domain, SOCK_STREAM, 0);
176 if (sock == INVALID_SOCKET) {
177 err = WSAGetLastError();
178 uv__queue_remove(&handle->handle_queue);
179 return uv_translate_sys_error(err);
180 }
181
182 err = uv__tcp_set_socket(handle->loop, handle, sock, domain, 0);
183 if (err) {
184 closesocket(sock);
185 uv__queue_remove(&handle->handle_queue);
186 return uv_translate_sys_error(err);
187 }
188
189 }
190
191 return 0;
192 }
193
194
uv_tcp_init(uv_loop_t * loop,uv_tcp_t * handle)195 int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
196 return uv_tcp_init_ex(loop, handle, AF_UNSPEC);
197 }
198
199
uv__process_tcp_shutdown_req(uv_loop_t * loop,uv_tcp_t * stream,uv_shutdown_t * req)200 void uv__process_tcp_shutdown_req(uv_loop_t* loop, uv_tcp_t* stream, uv_shutdown_t *req) {
201 int err;
202
203 assert(req);
204 assert(stream->stream.conn.write_reqs_pending == 0);
205 assert(!(stream->flags & UV_HANDLE_SHUT));
206 assert(stream->flags & UV_HANDLE_CONNECTION);
207
208 stream->stream.conn.shutdown_req = NULL;
209 UNREGISTER_HANDLE_REQ(loop, stream, req);
210
211 err = 0;
212 if (stream->flags & UV_HANDLE_CLOSING)
213 /* The user destroyed the stream before we got to do the shutdown. */
214 err = UV_ECANCELED;
215 else if (shutdown(stream->socket, SD_SEND) == SOCKET_ERROR)
216 err = uv_translate_sys_error(WSAGetLastError());
217 else /* Success. */
218 stream->flags |= UV_HANDLE_SHUT;
219
220 if (req->cb)
221 req->cb(req, err);
222
223 DECREASE_PENDING_REQ_COUNT(stream);
224 }
225
226
uv__tcp_endgame(uv_loop_t * loop,uv_tcp_t * handle)227 void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
228 unsigned int i;
229 uv_tcp_accept_t* req;
230
231 assert(handle->flags & UV_HANDLE_CLOSING);
232 assert(handle->reqs_pending == 0);
233 assert(!(handle->flags & UV_HANDLE_CLOSED));
234 assert(handle->socket == INVALID_SOCKET);
235
236 if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
237 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
238 for (i = 0; i < uv_simultaneous_server_accepts; i++) {
239 req = &handle->tcp.serv.accept_reqs[i];
240 if (req->wait_handle != INVALID_HANDLE_VALUE) {
241 UnregisterWait(req->wait_handle);
242 req->wait_handle = INVALID_HANDLE_VALUE;
243 }
244 if (req->event_handle != NULL) {
245 CloseHandle(req->event_handle);
246 req->event_handle = NULL;
247 }
248 }
249 }
250
251 uv__free(handle->tcp.serv.accept_reqs);
252 handle->tcp.serv.accept_reqs = NULL;
253 }
254
255 if (handle->flags & UV_HANDLE_CONNECTION &&
256 handle->flags & UV_HANDLE_EMULATE_IOCP) {
257 if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
258 UnregisterWait(handle->read_req.wait_handle);
259 handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
260 }
261 if (handle->read_req.event_handle != NULL) {
262 CloseHandle(handle->read_req.event_handle);
263 handle->read_req.event_handle = NULL;
264 }
265 }
266
267 uv__handle_close(handle);
268 }
269
270
271 /* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just
272 * allow binding to addresses that are in use by sockets in TIME_WAIT, it
273 * effectively allows 'stealing' a port which is in use by another application.
274 *
275 * SO_EXCLUSIVEADDRUSE is also not good here because it does check all sockets,
276 * regardless of state, so we'd get an error even if the port is in use by a
277 * socket in TIME_WAIT state.
278 *
279 * See issue #1360.
280 *
281 */
uv__tcp_try_bind(uv_tcp_t * handle,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)282 static int uv__tcp_try_bind(uv_tcp_t* handle,
283 const struct sockaddr* addr,
284 unsigned int addrlen,
285 unsigned int flags) {
286 DWORD err;
287 int r;
288
289 if (handle->socket == INVALID_SOCKET) {
290 SOCKET sock;
291
292 /* Cannot set IPv6-only mode on non-IPv6 socket. */
293 if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
294 return ERROR_INVALID_PARAMETER;
295
296 sock = socket(addr->sa_family, SOCK_STREAM, 0);
297 if (sock == INVALID_SOCKET) {
298 return WSAGetLastError();
299 }
300
301 err = uv__tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);
302 if (err) {
303 closesocket(sock);
304 return err;
305 }
306 }
307
308 #ifdef IPV6_V6ONLY
309 if (addr->sa_family == AF_INET6) {
310 int on;
311
312 on = (flags & UV_TCP_IPV6ONLY) != 0;
313
314 /* TODO: how to handle errors? This may fail if there is no ipv4 stack
315 * available, or when run on XP/2003 which have no support for dualstack
316 * sockets. For now we're silently ignoring the error. */
317 setsockopt(handle->socket,
318 IPPROTO_IPV6,
319 IPV6_V6ONLY,
320 (const char*)&on,
321 sizeof on);
322 }
323 #endif
324
325 r = bind(handle->socket, addr, addrlen);
326
327 if (r == SOCKET_ERROR) {
328 err = WSAGetLastError();
329 if (err == WSAEADDRINUSE) {
330 /* Some errors are not to be reported until connect() or listen() */
331 handle->delayed_error = err;
332 } else {
333 return err;
334 }
335 }
336
337 handle->flags |= UV_HANDLE_BOUND;
338
339 return 0;
340 }
341
342
post_completion(void * context,BOOLEAN timed_out)343 static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {
344 uv_req_t* req;
345 uv_tcp_t* handle;
346
347 req = (uv_req_t*) context;
348 assert(req != NULL);
349 handle = (uv_tcp_t*)req->data;
350 assert(handle != NULL);
351 assert(!timed_out);
352
353 if (!PostQueuedCompletionStatus(handle->loop->iocp,
354 req->u.io.overlapped.InternalHigh,
355 0,
356 &req->u.io.overlapped)) {
357 uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
358 }
359 }
360
361
post_write_completion(void * context,BOOLEAN timed_out)362 static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) {
363 uv_write_t* req;
364 uv_tcp_t* handle;
365
366 req = (uv_write_t*) context;
367 assert(req != NULL);
368 handle = (uv_tcp_t*)req->handle;
369 assert(handle != NULL);
370 assert(!timed_out);
371
372 if (!PostQueuedCompletionStatus(handle->loop->iocp,
373 req->u.io.overlapped.InternalHigh,
374 0,
375 &req->u.io.overlapped)) {
376 uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
377 }
378 }
379
380
uv__tcp_queue_accept(uv_tcp_t * handle,uv_tcp_accept_t * req)381 static void uv__tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
382 uv_loop_t* loop = handle->loop;
383 BOOL success;
384 DWORD bytes;
385 SOCKET accept_socket;
386 short family;
387
388 assert(handle->flags & UV_HANDLE_LISTENING);
389 assert(req->accept_socket == INVALID_SOCKET);
390
391 /* choose family and extension function */
392 if (handle->flags & UV_HANDLE_IPV6) {
393 family = AF_INET6;
394 } else {
395 family = AF_INET;
396 }
397
398 /* Open a socket for the accepted connection. */
399 accept_socket = socket(family, SOCK_STREAM, 0);
400 if (accept_socket == INVALID_SOCKET) {
401 SET_REQ_ERROR(req, WSAGetLastError());
402 uv__insert_pending_req(loop, (uv_req_t*)req);
403 handle->reqs_pending++;
404 return;
405 }
406
407 /* Make the socket non-inheritable */
408 if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {
409 SET_REQ_ERROR(req, GetLastError());
410 uv__insert_pending_req(loop, (uv_req_t*)req);
411 handle->reqs_pending++;
412 closesocket(accept_socket);
413 return;
414 }
415
416 /* Prepare the overlapped structure. */
417 memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
418 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
419 assert(req->event_handle != NULL);
420 req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
421 }
422
423 success = handle->tcp.serv.func_acceptex(handle->socket,
424 accept_socket,
425 (void*)req->accept_buffer,
426 0,
427 sizeof(struct sockaddr_storage),
428 sizeof(struct sockaddr_storage),
429 &bytes,
430 &req->u.io.overlapped);
431
432 if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
433 /* Process the req without IOCP. */
434 req->accept_socket = accept_socket;
435 handle->reqs_pending++;
436 uv__insert_pending_req(loop, (uv_req_t*)req);
437 } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
438 /* The req will be processed with IOCP. */
439 req->accept_socket = accept_socket;
440 handle->reqs_pending++;
441 if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
442 req->wait_handle == INVALID_HANDLE_VALUE &&
443 !RegisterWaitForSingleObject(&req->wait_handle,
444 req->event_handle, post_completion, (void*) req,
445 INFINITE, WT_EXECUTEINWAITTHREAD)) {
446 SET_REQ_ERROR(req, GetLastError());
447 uv__insert_pending_req(loop, (uv_req_t*)req);
448 }
449 } else {
450 /* Make this req pending reporting an error. */
451 SET_REQ_ERROR(req, WSAGetLastError());
452 uv__insert_pending_req(loop, (uv_req_t*)req);
453 handle->reqs_pending++;
454 /* Destroy the preallocated client socket. */
455 closesocket(accept_socket);
456 /* Destroy the event handle */
457 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
458 CloseHandle(req->event_handle);
459 req->event_handle = NULL;
460 }
461 }
462 }
463
464
uv__tcp_queue_read(uv_loop_t * loop,uv_tcp_t * handle)465 static void uv__tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
466 uv_read_t* req;
467 uv_buf_t buf;
468 int result;
469 DWORD bytes, flags;
470
471 assert(handle->flags & UV_HANDLE_READING);
472 assert(!(handle->flags & UV_HANDLE_READ_PENDING));
473
474 req = &handle->read_req;
475 memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
476
477 handle->flags |= UV_HANDLE_ZERO_READ;
478 buf.base = (char*) &uv_zero_;
479 buf.len = 0;
480
481 /* Prepare the overlapped structure. */
482 memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
483 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
484 assert(req->event_handle != NULL);
485 req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
486 }
487
488 flags = 0;
489 result = WSARecv(handle->socket,
490 (WSABUF*)&buf,
491 1,
492 &bytes,
493 &flags,
494 &req->u.io.overlapped,
495 NULL);
496
497 handle->flags |= UV_HANDLE_READ_PENDING;
498 handle->reqs_pending++;
499
500 if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
501 /* Process the req without IOCP. */
502 req->u.io.overlapped.InternalHigh = bytes;
503 uv__insert_pending_req(loop, (uv_req_t*)req);
504 } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
505 /* The req will be processed with IOCP. */
506 if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
507 req->wait_handle == INVALID_HANDLE_VALUE &&
508 !RegisterWaitForSingleObject(&req->wait_handle,
509 req->event_handle, post_completion, (void*) req,
510 INFINITE, WT_EXECUTEINWAITTHREAD)) {
511 SET_REQ_ERROR(req, GetLastError());
512 uv__insert_pending_req(loop, (uv_req_t*)req);
513 }
514 } else {
515 /* Make this req pending reporting an error. */
516 SET_REQ_ERROR(req, WSAGetLastError());
517 uv__insert_pending_req(loop, (uv_req_t*)req);
518 }
519 }
520
521
uv_tcp_close_reset(uv_tcp_t * handle,uv_close_cb close_cb)522 int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
523 struct linger l = { 1, 0 };
524
525 /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
526 if (uv__is_stream_shutting(handle))
527 return UV_EINVAL;
528
529 if (0 != setsockopt(handle->socket, SOL_SOCKET, SO_LINGER, (const char*)&l, sizeof(l)))
530 return uv_translate_sys_error(WSAGetLastError());
531
532 uv_close((uv_handle_t*) handle, close_cb);
533 return 0;
534 }
535
536
uv__tcp_listen(uv_tcp_t * handle,int backlog,uv_connection_cb cb)537 int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
538 unsigned int i, simultaneous_accepts;
539 uv_tcp_accept_t* req;
540 int err;
541
542 assert(backlog > 0);
543
544 if (handle->flags & UV_HANDLE_LISTENING) {
545 handle->stream.serv.connection_cb = cb;
546 }
547
548 if (handle->flags & UV_HANDLE_READING) {
549 return WSAEISCONN;
550 }
551
552 if (handle->delayed_error) {
553 return handle->delayed_error;
554 }
555
556 if (!(handle->flags & UV_HANDLE_BOUND)) {
557 err = uv__tcp_try_bind(handle,
558 (const struct sockaddr*) &uv_addr_ip4_any_,
559 sizeof(uv_addr_ip4_any_),
560 0);
561 if (err)
562 return err;
563 if (handle->delayed_error)
564 return handle->delayed_error;
565 }
566
567 if (!handle->tcp.serv.func_acceptex) {
568 if (!uv__get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) {
569 return WSAEAFNOSUPPORT;
570 }
571 }
572
573 /* If this flag is set, we already made this listen call in xfer. */
574 if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
575 listen(handle->socket, backlog) == SOCKET_ERROR) {
576 return WSAGetLastError();
577 }
578
579 handle->flags |= UV_HANDLE_LISTENING;
580 handle->stream.serv.connection_cb = cb;
581 INCREASE_ACTIVE_COUNT(loop, handle);
582
583 simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
584 : uv_simultaneous_server_accepts;
585
586 if (handle->tcp.serv.accept_reqs == NULL) {
587 handle->tcp.serv.accept_reqs =
588 uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
589 if (!handle->tcp.serv.accept_reqs) {
590 uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
591 }
592
593 for (i = 0; i < simultaneous_accepts; i++) {
594 req = &handle->tcp.serv.accept_reqs[i];
595 UV_REQ_INIT(req, UV_ACCEPT);
596 req->accept_socket = INVALID_SOCKET;
597 req->data = handle;
598
599 req->wait_handle = INVALID_HANDLE_VALUE;
600 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
601 req->event_handle = CreateEvent(NULL, 0, 0, NULL);
602 if (req->event_handle == NULL) {
603 uv_fatal_error(GetLastError(), "CreateEvent");
604 }
605 } else {
606 req->event_handle = NULL;
607 }
608
609 uv__tcp_queue_accept(handle, req);
610 }
611
612 /* Initialize other unused requests too, because uv_tcp_endgame doesn't
613 * know how many requests were initialized, so it will try to clean up
614 * {uv_simultaneous_server_accepts} requests. */
615 for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
616 req = &handle->tcp.serv.accept_reqs[i];
617 UV_REQ_INIT(req, UV_ACCEPT);
618 req->accept_socket = INVALID_SOCKET;
619 req->data = handle;
620 req->wait_handle = INVALID_HANDLE_VALUE;
621 req->event_handle = NULL;
622 }
623 }
624
625 return 0;
626 }
627
628
uv__tcp_accept(uv_tcp_t * server,uv_tcp_t * client)629 int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
630 int err = 0;
631 int family;
632
633 uv_tcp_accept_t* req = server->tcp.serv.pending_accepts;
634
635 if (!req) {
636 /* No valid connections found, so we error out. */
637 return WSAEWOULDBLOCK;
638 }
639
640 if (req->accept_socket == INVALID_SOCKET) {
641 return WSAENOTCONN;
642 }
643
644 if (server->flags & UV_HANDLE_IPV6) {
645 family = AF_INET6;
646 } else {
647 family = AF_INET;
648 }
649
650 err = uv__tcp_set_socket(client->loop,
651 client,
652 req->accept_socket,
653 family,
654 0);
655 if (err) {
656 closesocket(req->accept_socket);
657 } else {
658 uv__connection_init((uv_stream_t*) client);
659 /* AcceptEx() implicitly binds the accepted socket. */
660 client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
661 }
662
663 /* Prepare the req to pick up a new connection */
664 server->tcp.serv.pending_accepts = req->next_pending;
665 req->next_pending = NULL;
666 req->accept_socket = INVALID_SOCKET;
667
668 if (!(server->flags & UV_HANDLE_CLOSING)) {
669 /* Check if we're in a middle of changing the number of pending accepts. */
670 if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
671 uv__tcp_queue_accept(server, req);
672 } else {
673 /* We better be switching to a single pending accept. */
674 assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);
675
676 server->tcp.serv.processed_accepts++;
677
678 if (server->tcp.serv.processed_accepts >= uv_simultaneous_server_accepts) {
679 server->tcp.serv.processed_accepts = 0;
680 /*
681 * All previously queued accept requests are now processed.
682 * We now switch to queueing just a single accept.
683 */
684 uv__tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]);
685 server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
686 server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
687 }
688 }
689 }
690
691 return err;
692 }
693
694
uv__tcp_read_start(uv_tcp_t * handle,uv_alloc_cb alloc_cb,uv_read_cb read_cb)695 int uv__tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
696 uv_read_cb read_cb) {
697 uv_loop_t* loop = handle->loop;
698
699 handle->flags |= UV_HANDLE_READING;
700 handle->read_cb = read_cb;
701 handle->alloc_cb = alloc_cb;
702 INCREASE_ACTIVE_COUNT(loop, handle);
703
704 /* If reading was stopped and then started again, there could still be a read
705 * request pending. */
706 if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
707 if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
708 handle->read_req.event_handle == NULL) {
709 handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL);
710 if (handle->read_req.event_handle == NULL) {
711 uv_fatal_error(GetLastError(), "CreateEvent");
712 }
713 }
714 uv__tcp_queue_read(loop, handle);
715 }
716
717 return 0;
718 }
719
uv__is_loopback(const struct sockaddr_storage * storage)720 static int uv__is_loopback(const struct sockaddr_storage* storage) {
721 const struct sockaddr_in* in4;
722 const struct sockaddr_in6* in6;
723 int i;
724
725 if (storage->ss_family == AF_INET) {
726 in4 = (const struct sockaddr_in*) storage;
727 return in4->sin_addr.S_un.S_un_b.s_b1 == 127;
728 }
729 if (storage->ss_family == AF_INET6) {
730 in6 = (const struct sockaddr_in6*) storage;
731 for (i = 0; i < 7; ++i) {
732 if (in6->sin6_addr.u.Word[i] != 0)
733 return 0;
734 }
735 return in6->sin6_addr.u.Word[7] == htons(1);
736 }
737 return 0;
738 }
739
740 // Check if Windows version is 10.0.16299 or later
uv__is_fast_loopback_fail_supported(void)741 static int uv__is_fast_loopback_fail_supported(void) {
742 OSVERSIONINFOW os_info;
743 if (!pRtlGetVersion)
744 return 0;
745 pRtlGetVersion(&os_info);
746 if (os_info.dwMajorVersion < 10)
747 return 0;
748 if (os_info.dwMajorVersion > 10)
749 return 1;
750 if (os_info.dwMinorVersion > 0)
751 return 1;
752 return os_info.dwBuildNumber >= 16299;
753 }
754
uv__tcp_try_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,unsigned int addrlen,uv_connect_cb cb)755 static int uv__tcp_try_connect(uv_connect_t* req,
756 uv_tcp_t* handle,
757 const struct sockaddr* addr,
758 unsigned int addrlen,
759 uv_connect_cb cb) {
760 uv_loop_t* loop = handle->loop;
761 TCP_INITIAL_RTO_PARAMETERS retransmit_ioctl;
762 const struct sockaddr* bind_addr;
763 struct sockaddr_storage converted;
764 BOOL success;
765 DWORD bytes;
766 int err;
767
768 err = uv__convert_to_localhost_if_unspecified(addr, &converted);
769 if (err)
770 return err;
771
772 if (handle->delayed_error != 0)
773 goto out;
774
775 if (!(handle->flags & UV_HANDLE_BOUND)) {
776 if (addrlen == sizeof(uv_addr_ip4_any_)) {
777 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
778 } else if (addrlen == sizeof(uv_addr_ip6_any_)) {
779 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
780 } else {
781 abort();
782 }
783 err = uv__tcp_try_bind(handle, bind_addr, addrlen, 0);
784 if (err)
785 return err;
786 if (handle->delayed_error != 0)
787 goto out;
788 }
789
790 if (!handle->tcp.conn.func_connectex) {
791 if (!uv__get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) {
792 return WSAEAFNOSUPPORT;
793 }
794 }
795
796 /* This makes connect() fail instantly if the target port on the localhost
797 * is not reachable, instead of waiting for 2s. We do not care if this fails.
798 * This only works on Windows version 10.0.16299 and later.
799 */
800 if (uv__is_fast_loopback_fail_supported() && uv__is_loopback(&converted)) {
801 memset(&retransmit_ioctl, 0, sizeof(retransmit_ioctl));
802 retransmit_ioctl.Rtt = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
803 retransmit_ioctl.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
804 WSAIoctl(handle->socket,
805 SIO_TCP_INITIAL_RTO,
806 &retransmit_ioctl,
807 sizeof(retransmit_ioctl),
808 NULL,
809 0,
810 &bytes,
811 NULL,
812 NULL);
813 }
814
815 out:
816
817 UV_REQ_INIT(req, UV_CONNECT);
818 req->handle = (uv_stream_t*) handle;
819 req->cb = cb;
820 memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
821
822 if (handle->delayed_error != 0) {
823 /* Process the req without IOCP. */
824 handle->reqs_pending++;
825 REGISTER_HANDLE_REQ(loop, handle, req);
826 uv__insert_pending_req(loop, (uv_req_t*)req);
827 return 0;
828 }
829
830 success = handle->tcp.conn.func_connectex(handle->socket,
831 (const struct sockaddr*) &converted,
832 addrlen,
833 NULL,
834 0,
835 &bytes,
836 &req->u.io.overlapped);
837
838 if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
839 /* Process the req without IOCP. */
840 handle->reqs_pending++;
841 REGISTER_HANDLE_REQ(loop, handle, req);
842 uv__insert_pending_req(loop, (uv_req_t*)req);
843 } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
844 /* The req will be processed with IOCP. */
845 handle->reqs_pending++;
846 REGISTER_HANDLE_REQ(loop, handle, req);
847 } else {
848 return WSAGetLastError();
849 }
850
851 return 0;
852 }
853
854
uv_tcp_getsockname(const uv_tcp_t * handle,struct sockaddr * name,int * namelen)855 int uv_tcp_getsockname(const uv_tcp_t* handle,
856 struct sockaddr* name,
857 int* namelen) {
858
859 return uv__getsockpeername((const uv_handle_t*) handle,
860 getsockname,
861 name,
862 namelen,
863 handle->delayed_error);
864 }
865
866
uv_tcp_getpeername(const uv_tcp_t * handle,struct sockaddr * name,int * namelen)867 int uv_tcp_getpeername(const uv_tcp_t* handle,
868 struct sockaddr* name,
869 int* namelen) {
870
871 return uv__getsockpeername((const uv_handle_t*) handle,
872 getpeername,
873 name,
874 namelen,
875 handle->delayed_error);
876 }
877
878
uv__tcp_write(uv_loop_t * loop,uv_write_t * req,uv_tcp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,uv_write_cb cb)879 int uv__tcp_write(uv_loop_t* loop,
880 uv_write_t* req,
881 uv_tcp_t* handle,
882 const uv_buf_t bufs[],
883 unsigned int nbufs,
884 uv_write_cb cb) {
885 int result;
886 DWORD bytes;
887
888 UV_REQ_INIT(req, UV_WRITE);
889 req->handle = (uv_stream_t*) handle;
890 req->cb = cb;
891
892 /* Prepare the overlapped structure. */
893 memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
894 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
895 req->event_handle = CreateEvent(NULL, 0, 0, NULL);
896 if (req->event_handle == NULL) {
897 uv_fatal_error(GetLastError(), "CreateEvent");
898 }
899 req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
900 req->wait_handle = INVALID_HANDLE_VALUE;
901 }
902
903 result = WSASend(handle->socket,
904 (WSABUF*) bufs,
905 nbufs,
906 &bytes,
907 0,
908 &req->u.io.overlapped,
909 NULL);
910
911 if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
912 /* Request completed immediately. */
913 req->u.io.queued_bytes = 0;
914 handle->reqs_pending++;
915 handle->stream.conn.write_reqs_pending++;
916 REGISTER_HANDLE_REQ(loop, handle, req);
917 uv__insert_pending_req(loop, (uv_req_t*) req);
918 } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
919 /* Request queued by the kernel. */
920 req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
921 handle->reqs_pending++;
922 handle->stream.conn.write_reqs_pending++;
923 REGISTER_HANDLE_REQ(loop, handle, req);
924 handle->write_queue_size += req->u.io.queued_bytes;
925 if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
926 !RegisterWaitForSingleObject(&req->wait_handle,
927 req->event_handle, post_write_completion, (void*) req,
928 INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
929 SET_REQ_ERROR(req, GetLastError());
930 uv__insert_pending_req(loop, (uv_req_t*)req);
931 }
932 } else {
933 /* Send failed due to an error, report it later */
934 req->u.io.queued_bytes = 0;
935 handle->reqs_pending++;
936 handle->stream.conn.write_reqs_pending++;
937 REGISTER_HANDLE_REQ(loop, handle, req);
938 SET_REQ_ERROR(req, WSAGetLastError());
939 uv__insert_pending_req(loop, (uv_req_t*) req);
940 }
941
942 return 0;
943 }
944
945
uv__tcp_try_write(uv_tcp_t * handle,const uv_buf_t bufs[],unsigned int nbufs)946 int uv__tcp_try_write(uv_tcp_t* handle,
947 const uv_buf_t bufs[],
948 unsigned int nbufs) {
949 int result;
950 DWORD bytes;
951
952 if (handle->stream.conn.write_reqs_pending > 0)
953 return UV_EAGAIN;
954
955 result = WSASend(handle->socket,
956 (WSABUF*) bufs,
957 nbufs,
958 &bytes,
959 0,
960 NULL,
961 NULL);
962
963 if (result == SOCKET_ERROR)
964 return uv_translate_sys_error(WSAGetLastError());
965 else
966 return bytes;
967 }
968
969
uv__process_tcp_read_req(uv_loop_t * loop,uv_tcp_t * handle,uv_req_t * req)970 void uv__process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
971 uv_req_t* req) {
972 DWORD bytes, flags, err;
973 uv_buf_t buf;
974 int count;
975
976 assert(handle->type == UV_TCP);
977
978 handle->flags &= ~UV_HANDLE_READ_PENDING;
979
980 if (!REQ_SUCCESS(req)) {
981 /* An error occurred doing the read. */
982 if ((handle->flags & UV_HANDLE_READING) ||
983 !(handle->flags & UV_HANDLE_ZERO_READ)) {
984 handle->flags &= ~UV_HANDLE_READING;
985 DECREASE_ACTIVE_COUNT(loop, handle);
986 buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
987 uv_buf_init(NULL, 0) : handle->tcp.conn.read_buffer;
988
989 err = GET_REQ_SOCK_ERROR(req);
990
991 if (err == WSAECONNABORTED) {
992 /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
993 */
994 err = WSAECONNRESET;
995 }
996 handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
997
998 handle->read_cb((uv_stream_t*)handle,
999 uv_translate_sys_error(err),
1000 &buf);
1001 }
1002 } else {
1003 if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
1004 /* The read was done with a non-zero buffer length. */
1005 if (req->u.io.overlapped.InternalHigh > 0) {
1006 /* Successful read */
1007 handle->read_cb((uv_stream_t*)handle,
1008 req->u.io.overlapped.InternalHigh,
1009 &handle->tcp.conn.read_buffer);
1010 /* Read again only if bytes == buf.len */
1011 if (req->u.io.overlapped.InternalHigh < handle->tcp.conn.read_buffer.len) {
1012 goto done;
1013 }
1014 } else {
1015 /* Connection closed */
1016 if (handle->flags & UV_HANDLE_READING) {
1017 handle->flags &= ~UV_HANDLE_READING;
1018 DECREASE_ACTIVE_COUNT(loop, handle);
1019 }
1020
1021 buf.base = 0;
1022 buf.len = 0;
1023 handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->tcp.conn.read_buffer);
1024 goto done;
1025 }
1026 }
1027
1028 /* Do nonblocking reads until the buffer is empty */
1029 count = 32;
1030 while ((handle->flags & UV_HANDLE_READING) && (count-- > 0)) {
1031 buf = uv_buf_init(NULL, 0);
1032 handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
1033 if (buf.base == NULL || buf.len == 0) {
1034 handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
1035 break;
1036 }
1037 assert(buf.base != NULL);
1038
1039 flags = 0;
1040 if (WSARecv(handle->socket,
1041 (WSABUF*)&buf,
1042 1,
1043 &bytes,
1044 &flags,
1045 NULL,
1046 NULL) != SOCKET_ERROR) {
1047 if (bytes > 0) {
1048 /* Successful read */
1049 handle->read_cb((uv_stream_t*)handle, bytes, &buf);
1050 /* Read again only if bytes == buf.len */
1051 if (bytes < buf.len) {
1052 break;
1053 }
1054 } else {
1055 /* Connection closed */
1056 handle->flags &= ~UV_HANDLE_READING;
1057 DECREASE_ACTIVE_COUNT(loop, handle);
1058
1059 handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf);
1060 break;
1061 }
1062 } else {
1063 err = WSAGetLastError();
1064 if (err == WSAEWOULDBLOCK) {
1065 /* Read buffer was completely empty, report a 0-byte read. */
1066 handle->read_cb((uv_stream_t*)handle, 0, &buf);
1067 } else {
1068 /* Ouch! serious error. */
1069 handle->flags &= ~UV_HANDLE_READING;
1070 DECREASE_ACTIVE_COUNT(loop, handle);
1071
1072 if (err == WSAECONNABORTED) {
1073 /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with
1074 * Unix. */
1075 err = WSAECONNRESET;
1076 }
1077 handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
1078
1079 handle->read_cb((uv_stream_t*)handle,
1080 uv_translate_sys_error(err),
1081 &buf);
1082 }
1083 break;
1084 }
1085 }
1086
1087 done:
1088 /* Post another read if still reading and not closing. */
1089 if ((handle->flags & UV_HANDLE_READING) &&
1090 !(handle->flags & UV_HANDLE_READ_PENDING)) {
1091 uv__tcp_queue_read(loop, handle);
1092 }
1093 }
1094
1095 DECREASE_PENDING_REQ_COUNT(handle);
1096 }
1097
1098
uv__process_tcp_write_req(uv_loop_t * loop,uv_tcp_t * handle,uv_write_t * req)1099 void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
1100 uv_write_t* req) {
1101 int err;
1102
1103 assert(handle->type == UV_TCP);
1104
1105 assert(handle->write_queue_size >= req->u.io.queued_bytes);
1106 handle->write_queue_size -= req->u.io.queued_bytes;
1107
1108 UNREGISTER_HANDLE_REQ(loop, handle, req);
1109
1110 if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1111 if (req->wait_handle != INVALID_HANDLE_VALUE) {
1112 UnregisterWait(req->wait_handle);
1113 req->wait_handle = INVALID_HANDLE_VALUE;
1114 }
1115 if (req->event_handle != NULL) {
1116 CloseHandle(req->event_handle);
1117 req->event_handle = NULL;
1118 }
1119 }
1120
1121 if (req->cb) {
1122 err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req));
1123 if (err == UV_ECONNABORTED) {
1124 /* use UV_ECANCELED for consistency with Unix */
1125 err = UV_ECANCELED;
1126 }
1127 req->cb(req, err);
1128 }
1129
1130 handle->stream.conn.write_reqs_pending--;
1131 if (handle->stream.conn.write_reqs_pending == 0) {
1132 if (handle->flags & UV_HANDLE_CLOSING) {
1133 closesocket(handle->socket);
1134 handle->socket = INVALID_SOCKET;
1135 }
1136 if (uv__is_stream_shutting(handle))
1137 uv__process_tcp_shutdown_req(loop,
1138 handle,
1139 handle->stream.conn.shutdown_req);
1140 }
1141
1142 DECREASE_PENDING_REQ_COUNT(handle);
1143 }
1144
1145
uv__process_tcp_accept_req(uv_loop_t * loop,uv_tcp_t * handle,uv_req_t * raw_req)1146 void uv__process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
1147 uv_req_t* raw_req) {
1148 uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req;
1149 int err;
1150
1151 assert(handle->type == UV_TCP);
1152
1153 /* If handle->accepted_socket is not a valid socket, then uv_queue_accept
1154 * must have failed. This is a serious error. We stop accepting connections
1155 * and report this error to the connection callback. */
1156 if (req->accept_socket == INVALID_SOCKET) {
1157 if (handle->flags & UV_HANDLE_LISTENING) {
1158 handle->flags &= ~UV_HANDLE_LISTENING;
1159 DECREASE_ACTIVE_COUNT(loop, handle);
1160 if (handle->stream.serv.connection_cb) {
1161 err = GET_REQ_SOCK_ERROR(req);
1162 handle->stream.serv.connection_cb((uv_stream_t*)handle,
1163 uv_translate_sys_error(err));
1164 }
1165 }
1166 } else if (REQ_SUCCESS(req) &&
1167 setsockopt(req->accept_socket,
1168 SOL_SOCKET,
1169 SO_UPDATE_ACCEPT_CONTEXT,
1170 (char*)&handle->socket,
1171 sizeof(handle->socket)) == 0) {
1172 req->next_pending = handle->tcp.serv.pending_accepts;
1173 handle->tcp.serv.pending_accepts = req;
1174
1175 /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */
1176 if (handle->stream.serv.connection_cb) {
1177 handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
1178 }
1179 } else {
1180 /* Error related to accepted socket is ignored because the server socket
1181 * may still be healthy. If the server socket is broken uv_queue_accept
1182 * will detect it. */
1183 closesocket(req->accept_socket);
1184 req->accept_socket = INVALID_SOCKET;
1185 if (handle->flags & UV_HANDLE_LISTENING) {
1186 uv__tcp_queue_accept(handle, req);
1187 }
1188 }
1189
1190 DECREASE_PENDING_REQ_COUNT(handle);
1191 }
1192
1193
uv__process_tcp_connect_req(uv_loop_t * loop,uv_tcp_t * handle,uv_connect_t * req)1194 void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
1195 uv_connect_t* req) {
1196 int err;
1197
1198 assert(handle->type == UV_TCP);
1199
1200 UNREGISTER_HANDLE_REQ(loop, handle, req);
1201
1202 err = 0;
1203 if (handle->delayed_error) {
1204 /* To smooth over the differences between unixes errors that
1205 * were reported synchronously on the first connect can be delayed
1206 * until the next tick--which is now.
1207 */
1208 err = handle->delayed_error;
1209 handle->delayed_error = 0;
1210 } else if (REQ_SUCCESS(req)) {
1211 if (handle->flags & UV_HANDLE_CLOSING) {
1212 /* use UV_ECANCELED for consistency with Unix */
1213 err = ERROR_OPERATION_ABORTED;
1214 } else if (setsockopt(handle->socket,
1215 SOL_SOCKET,
1216 SO_UPDATE_CONNECT_CONTEXT,
1217 NULL,
1218 0) == 0) {
1219 uv__connection_init((uv_stream_t*)handle);
1220 handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
1221 } else {
1222 err = WSAGetLastError();
1223 }
1224 } else {
1225 err = GET_REQ_SOCK_ERROR(req);
1226 }
1227 req->cb(req, uv_translate_sys_error(err));
1228
1229 DECREASE_PENDING_REQ_COUNT(handle);
1230 }
1231
1232
uv__tcp_xfer_export(uv_tcp_t * handle,int target_pid,uv__ipc_socket_xfer_type_t * xfer_type,uv__ipc_socket_xfer_info_t * xfer_info)1233 int uv__tcp_xfer_export(uv_tcp_t* handle,
1234 int target_pid,
1235 uv__ipc_socket_xfer_type_t* xfer_type,
1236 uv__ipc_socket_xfer_info_t* xfer_info) {
1237 if (handle->flags & UV_HANDLE_CONNECTION) {
1238 *xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION;
1239 } else {
1240 *xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER;
1241 /* We're about to share the socket with another process. Because this is a
1242 * listening socket, we assume that the other process will be accepting
1243 * connections on it. Thus, before sharing the socket with another process,
1244 * we call listen here in the parent process. */
1245 if (!(handle->flags & UV_HANDLE_LISTENING)) {
1246 if (!(handle->flags & UV_HANDLE_BOUND)) {
1247 return ERROR_NOT_SUPPORTED;
1248 }
1249 if (handle->delayed_error == 0 &&
1250 listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
1251 handle->delayed_error = WSAGetLastError();
1252 }
1253 }
1254 }
1255
1256 if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info))
1257 return WSAGetLastError();
1258 xfer_info->delayed_error = handle->delayed_error;
1259
1260 /* Mark the local copy of the handle as 'shared' so we behave in a way that's
1261 * friendly to the process(es) that we share the socket with. */
1262 handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
1263
1264 return 0;
1265 }
1266
1267
uv__tcp_xfer_import(uv_tcp_t * tcp,uv__ipc_socket_xfer_type_t xfer_type,uv__ipc_socket_xfer_info_t * xfer_info)1268 int uv__tcp_xfer_import(uv_tcp_t* tcp,
1269 uv__ipc_socket_xfer_type_t xfer_type,
1270 uv__ipc_socket_xfer_info_t* xfer_info) {
1271 int err;
1272 SOCKET socket;
1273
1274 assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER ||
1275 xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION);
1276
1277 socket = WSASocketW(FROM_PROTOCOL_INFO,
1278 FROM_PROTOCOL_INFO,
1279 FROM_PROTOCOL_INFO,
1280 &xfer_info->socket_info,
1281 0,
1282 WSA_FLAG_OVERLAPPED);
1283
1284 if (socket == INVALID_SOCKET) {
1285 return WSAGetLastError();
1286 }
1287
1288 err = uv__tcp_set_socket(
1289 tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);
1290 if (err) {
1291 closesocket(socket);
1292 return err;
1293 }
1294
1295 tcp->delayed_error = xfer_info->delayed_error;
1296 tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
1297
1298 if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {
1299 uv__connection_init((uv_stream_t*)tcp);
1300 tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
1301 }
1302
1303 return 0;
1304 }
1305
1306
uv_tcp_nodelay(uv_tcp_t * handle,int enable)1307 int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
1308 int err;
1309
1310 if (handle->socket != INVALID_SOCKET) {
1311 err = uv__tcp_nodelay(handle, handle->socket, enable);
1312 if (err)
1313 return uv_translate_sys_error(err);
1314 }
1315
1316 if (enable) {
1317 handle->flags |= UV_HANDLE_TCP_NODELAY;
1318 } else {
1319 handle->flags &= ~UV_HANDLE_TCP_NODELAY;
1320 }
1321
1322 return 0;
1323 }
1324
1325
uv_tcp_keepalive(uv_tcp_t * handle,int enable,unsigned int delay)1326 int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
1327 int err;
1328
1329 if (handle->socket != INVALID_SOCKET) {
1330 err = uv__tcp_keepalive(handle, handle->socket, enable, delay);
1331 if (err)
1332 return uv_translate_sys_error(err);
1333 }
1334
1335 if (enable) {
1336 handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
1337 } else {
1338 handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
1339 }
1340
1341 /* TODO: Store delay if handle->socket isn't created yet. */
1342
1343 return 0;
1344 }
1345
1346
uv_tcp_simultaneous_accepts(uv_tcp_t * handle,int enable)1347 int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
1348 if (handle->flags & UV_HANDLE_CONNECTION) {
1349 return UV_EINVAL;
1350 }
1351
1352 /* Check if we're already in the desired mode. */
1353 if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) ||
1354 (!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
1355 return 0;
1356 }
1357
1358 /* Don't allow switching from single pending accept to many. */
1359 if (enable) {
1360 return UV_ENOTSUP;
1361 }
1362
1363 /* Check if we're in a middle of changing the number of pending accepts. */
1364 if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) {
1365 return 0;
1366 }
1367
1368 handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
1369
1370 /* Flip the changing flag if we have already queued multiple accepts. */
1371 if (handle->flags & UV_HANDLE_LISTENING) {
1372 handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
1373 }
1374
1375 return 0;
1376 }
1377
1378
uv__tcp_try_cancel_reqs(uv_tcp_t * tcp)1379 static void uv__tcp_try_cancel_reqs(uv_tcp_t* tcp) {
1380 SOCKET socket;
1381 int non_ifs_lsp;
1382 int reading;
1383 int writing;
1384
1385 socket = tcp->socket;
1386 reading = tcp->flags & UV_HANDLE_READ_PENDING;
1387 writing = tcp->stream.conn.write_reqs_pending > 0;
1388 if (!reading && !writing)
1389 return;
1390
1391 /* TODO: in libuv v2, keep explicit track of write_reqs, so we can cancel
1392 * them each explicitly with CancelIoEx (like unix). */
1393 if (reading)
1394 CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped);
1395 if (writing)
1396 CancelIo((HANDLE) socket);
1397
1398 /* Check if we have any non-IFS LSPs stacked on top of TCP */
1399 non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
1400 uv_tcp_non_ifs_lsp_ipv4;
1401
1402 /* If there are non-ifs LSPs then try to obtain a base handle for the socket.
1403 */
1404 if (non_ifs_lsp) {
1405 DWORD bytes;
1406 if (WSAIoctl(socket,
1407 SIO_BASE_HANDLE,
1408 NULL,
1409 0,
1410 &socket,
1411 sizeof socket,
1412 &bytes,
1413 NULL,
1414 NULL) != 0) {
1415 /* Failed. We can't do CancelIo. */
1416 return;
1417 }
1418 }
1419
1420 assert(socket != 0 && socket != INVALID_SOCKET);
1421
1422 if (socket != tcp->socket) {
1423 if (reading)
1424 CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped);
1425 if (writing)
1426 CancelIo((HANDLE) socket);
1427 }
1428 }
1429
1430
uv__tcp_close(uv_loop_t * loop,uv_tcp_t * tcp)1431 void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
1432 if (tcp->flags & UV_HANDLE_CONNECTION) {
1433 if (tcp->flags & UV_HANDLE_READING) {
1434 uv_read_stop((uv_stream_t*) tcp);
1435 }
1436 uv__tcp_try_cancel_reqs(tcp);
1437 } else {
1438 if (tcp->tcp.serv.accept_reqs != NULL) {
1439 /* First close the incoming sockets to cancel the accept operations before
1440 * we free their resources. */
1441 unsigned int i;
1442 for (i = 0; i < uv_simultaneous_server_accepts; i++) {
1443 uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
1444 if (req->accept_socket != INVALID_SOCKET) {
1445 closesocket(req->accept_socket);
1446 req->accept_socket = INVALID_SOCKET;
1447 }
1448 }
1449 }
1450 assert(!(tcp->flags & UV_HANDLE_READING));
1451 }
1452
1453 if (tcp->flags & UV_HANDLE_LISTENING) {
1454 tcp->flags &= ~UV_HANDLE_LISTENING;
1455 DECREASE_ACTIVE_COUNT(loop, tcp);
1456 }
1457
1458 tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
1459 uv__handle_closing(tcp);
1460
1461 /* If any overlapped req failed to cancel, calling `closesocket` now would
1462 * cause Win32 to send an RST packet. Try to avoid that for writes, if
1463 * possibly applicable, by waiting to process the completion notifications
1464 * first (which typically should be cancellations). There's not much we can
1465 * do about canceled reads, which also will generate an RST packet. */
1466 if (!(tcp->flags & UV_HANDLE_CONNECTION) ||
1467 tcp->stream.conn.write_reqs_pending == 0) {
1468 closesocket(tcp->socket);
1469 tcp->socket = INVALID_SOCKET;
1470 }
1471
1472 if (tcp->reqs_pending == 0)
1473 uv__want_endgame(loop, (uv_handle_t*) tcp);
1474 }
1475
1476
uv_tcp_open(uv_tcp_t * handle,uv_os_sock_t sock)1477 int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
1478 WSAPROTOCOL_INFOW protocol_info;
1479 int opt_len;
1480 int err;
1481 struct sockaddr_storage saddr;
1482 int saddr_len;
1483
1484 /* Detect the address family of the socket. */
1485 opt_len = (int) sizeof protocol_info;
1486 if (getsockopt(sock,
1487 SOL_SOCKET,
1488 SO_PROTOCOL_INFOW,
1489 (char*) &protocol_info,
1490 &opt_len) == SOCKET_ERROR) {
1491 return uv_translate_sys_error(GetLastError());
1492 }
1493
1494 err = uv__tcp_set_socket(handle->loop,
1495 handle,
1496 sock,
1497 protocol_info.iAddressFamily,
1498 1);
1499 if (err) {
1500 return uv_translate_sys_error(err);
1501 }
1502
1503 /* Support already active socket. */
1504 saddr_len = sizeof(saddr);
1505 if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) {
1506 /* Socket is already bound. */
1507 handle->flags |= UV_HANDLE_BOUND;
1508 saddr_len = sizeof(saddr);
1509 if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) {
1510 /* Socket is already connected. */
1511 uv__connection_init((uv_stream_t*) handle);
1512 handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
1513 }
1514 }
1515
1516 return 0;
1517 }
1518
1519
1520 /* This function is an egress point, i.e. it returns libuv errors rather than
1521 * system errors.
1522 */
uv__tcp_bind(uv_tcp_t * handle,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)1523 int uv__tcp_bind(uv_tcp_t* handle,
1524 const struct sockaddr* addr,
1525 unsigned int addrlen,
1526 unsigned int flags) {
1527 int err;
1528
1529 err = uv__tcp_try_bind(handle, addr, addrlen, flags);
1530 if (err)
1531 return uv_translate_sys_error(err);
1532
1533 return 0;
1534 }
1535
1536
1537 /* This function is an egress point, i.e. it returns libuv errors rather than
1538 * system errors.
1539 */
uv__tcp_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,unsigned int addrlen,uv_connect_cb cb)1540 int uv__tcp_connect(uv_connect_t* req,
1541 uv_tcp_t* handle,
1542 const struct sockaddr* addr,
1543 unsigned int addrlen,
1544 uv_connect_cb cb) {
1545 int err;
1546
1547 err = uv__tcp_try_connect(req, handle, addr, addrlen, cb);
1548 if (err)
1549 return uv_translate_sys_error(err);
1550
1551 return 0;
1552 }
1553
1554 #ifndef WSA_FLAG_NO_HANDLE_INHERIT
1555 /* Added in Windows 7 SP1. Specify this to avoid race conditions, */
1556 /* but also manually clear the inherit flag in case this failed. */
1557 #define WSA_FLAG_NO_HANDLE_INHERIT 0x80
1558 #endif
1559
uv_socketpair(int type,int protocol,uv_os_sock_t fds[2],int flags0,int flags1)1560 int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
1561 SOCKET server = INVALID_SOCKET;
1562 SOCKET client0 = INVALID_SOCKET;
1563 SOCKET client1 = INVALID_SOCKET;
1564 SOCKADDR_IN name;
1565 LPFN_ACCEPTEX func_acceptex;
1566 WSAOVERLAPPED overlap;
1567 char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];
1568 int namelen;
1569 int err;
1570 DWORD bytes;
1571 DWORD flags;
1572 DWORD client0_flags = WSA_FLAG_NO_HANDLE_INHERIT;
1573 DWORD client1_flags = WSA_FLAG_NO_HANDLE_INHERIT;
1574
1575 if (flags0 & UV_NONBLOCK_PIPE)
1576 client0_flags |= WSA_FLAG_OVERLAPPED;
1577 if (flags1 & UV_NONBLOCK_PIPE)
1578 client1_flags |= WSA_FLAG_OVERLAPPED;
1579
1580 server = WSASocketW(AF_INET, type, protocol, NULL, 0,
1581 WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
1582 if (server == INVALID_SOCKET)
1583 goto wsaerror;
1584 if (!SetHandleInformation((HANDLE) server, HANDLE_FLAG_INHERIT, 0))
1585 goto error;
1586 name.sin_family = AF_INET;
1587 name.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1588 name.sin_port = 0;
1589 if (bind(server, (SOCKADDR*) &name, sizeof(name)) != 0)
1590 goto wsaerror;
1591 if (listen(server, 1) != 0)
1592 goto wsaerror;
1593 namelen = sizeof(name);
1594 if (getsockname(server, (SOCKADDR*) &name, &namelen) != 0)
1595 goto wsaerror;
1596 client0 = WSASocketW(AF_INET, type, protocol, NULL, 0, client0_flags);
1597 if (client0 == INVALID_SOCKET)
1598 goto wsaerror;
1599 if (!SetHandleInformation((HANDLE) client0, HANDLE_FLAG_INHERIT, 0))
1600 goto error;
1601 if (connect(client0, (SOCKADDR*) &name, sizeof(name)) != 0)
1602 goto wsaerror;
1603 client1 = WSASocketW(AF_INET, type, protocol, NULL, 0, client1_flags);
1604 if (client1 == INVALID_SOCKET)
1605 goto wsaerror;
1606 if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0))
1607 goto error;
1608 if (!uv__get_acceptex_function(server, &func_acceptex)) {
1609 err = WSAEAFNOSUPPORT;
1610 goto cleanup;
1611 }
1612 memset(&overlap, 0, sizeof(overlap));
1613 if (!func_acceptex(server,
1614 client1,
1615 accept_buffer,
1616 0,
1617 sizeof(struct sockaddr_storage),
1618 sizeof(struct sockaddr_storage),
1619 &bytes,
1620 &overlap)) {
1621 err = WSAGetLastError();
1622 if (err == ERROR_IO_PENDING) {
1623 /* Result should complete immediately, since we already called connect,
1624 * but empirically, we sometimes have to poll the kernel a couple times
1625 * until it notices that. */
1626 while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) {
1627 err = WSAGetLastError();
1628 if (err != WSA_IO_INCOMPLETE)
1629 goto cleanup;
1630 SwitchToThread();
1631 }
1632 }
1633 else {
1634 goto cleanup;
1635 }
1636 }
1637 if (setsockopt(client1, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
1638 (char*) &server, sizeof(server)) != 0) {
1639 goto wsaerror;
1640 }
1641
1642 closesocket(server);
1643
1644 fds[0] = client0;
1645 fds[1] = client1;
1646
1647 return 0;
1648
1649 wsaerror:
1650 err = WSAGetLastError();
1651 goto cleanup;
1652
1653 error:
1654 err = GetLastError();
1655 goto cleanup;
1656
1657 cleanup:
1658 if (server != INVALID_SOCKET)
1659 closesocket(server);
1660 if (client0 != INVALID_SOCKET)
1661 closesocket(client0);
1662 if (client1 != INVALID_SOCKET)
1663 closesocket(client1);
1664
1665 assert(err);
1666 return uv_translate_sys_error(err);
1667 }
1668