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