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