static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { BOOL success; DWORD bytes; SOCKET accept_socket; short family; LPFN_ACCEPTEX pAcceptExFamily; assert(handle->flags & UV_HANDLE_LISTENING); assert(req->accept_socket == INVALID_SOCKET); /* choose family and extension function */ if ((handle->flags & UV_HANDLE_IPV6) != 0) { family = AF_INET6; pAcceptExFamily = pAcceptEx6; } else { family = AF_INET; pAcceptExFamily = pAcceptEx; } /* Open a socket for the accepted connection. */ accept_socket = socket(family, SOCK_STREAM, 0); if (accept_socket == INVALID_SOCKET) { req->error = uv_new_sys_error(WSAGetLastError()); uv_insert_pending_req((uv_req_t*)req); handle->reqs_pending++; return; } /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); success = pAcceptExFamily(handle->socket, accept_socket, (void*)req->accept_buffer, 0, sizeof(struct sockaddr_storage), sizeof(struct sockaddr_storage), &bytes, &req->overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { /* Process the req without IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; uv_insert_pending_req((uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { /* The req will be processed with IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; } else { /* Make this req pending reporting an error. */ req->error = uv_new_sys_error(WSAGetLastError()); uv_insert_pending_req((uv_req_t*)req); handle->reqs_pending++; /* Destroy the preallocated client socket. */ closesocket(accept_socket); } }
static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL firstInstance) { assert(handle->flags & UV_HANDLE_LISTENING); if (!firstInstance) { assert(req->pipeHandle == INVALID_HANDLE_VALUE); req->pipeHandle = CreateNamedPipeW(handle->name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); if (req->pipeHandle == INVALID_HANDLE_VALUE) { req->error = uv_new_sys_error(GetLastError()); uv_insert_pending_req((uv_req_t*) req); handle->reqs_pending++; return; } if (uv_set_pipe_handle(handle, req->pipeHandle)) { CloseHandle(req->pipeHandle); req->pipeHandle = INVALID_HANDLE_VALUE; req->error = uv_new_sys_error(GetLastError()); uv_insert_pending_req((uv_req_t*) req); handle->reqs_pending++; return; } } assert(req->pipeHandle != INVALID_HANDLE_VALUE); /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && GetLastError() != ERROR_IO_PENDING) { if (GetLastError() == ERROR_PIPE_CONNECTED) { req->error = uv_ok_; } else { CloseHandle(req->pipeHandle); req->pipeHandle = INVALID_HANDLE_VALUE; /* Make this req pending reporting an error. */ req->error = uv_new_sys_error(GetLastError()); } uv_insert_pending_req((uv_req_t*) req); handle->reqs_pending++; return; } handle->reqs_pending++; }
static void uv_pipe_queue_read(uv_pipe_t* handle) { uv_req_t* req; int result; assert(handle->flags & UV_HANDLE_READING); assert(!(handle->flags & UV_HANDLE_READ_PENDING)); assert(handle->handle != INVALID_HANDLE_VALUE); req = &handle->read_req; memset(&req->overlapped, 0, sizeof(req->overlapped)); /* Do 0-read */ result = ReadFile(handle->handle, &uv_zero_, 0, NULL, &req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { /* Make this req pending reporting an error. */ req->error = uv_new_sys_error(WSAGetLastError()); uv_insert_pending_req(req); handle->reqs_pending++; return; } handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; }
static void uv_poll(int block) { BOOL success; DWORD bytes, timeout; ULONG_PTR key; OVERLAPPED* overlapped; uv_req_t* req; if (block) { timeout = uv_get_poll_timeout(); } else { timeout = 0; } success = GetQueuedCompletionStatus(LOOP->iocp, &bytes, &key, &overlapped, timeout); if (overlapped) { /* Package was dequeued */ req = uv_overlapped_to_req(overlapped); if (!success) { req->error = uv_new_sys_error(GetLastError()); } uv_insert_pending_req(req); } else if (GetLastError() != WAIT_TIMEOUT) { /* Serious error */ uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); } }
static void uv_tcp_queue_read(uv_tcp_t* handle) { uv_req_t* req; uv_buf_t buf; int result; DWORD bytes, flags; assert(handle->flags & UV_HANDLE_READING); assert(!(handle->flags & UV_HANDLE_READ_PENDING)); req = &handle->read_req; memset(&req->overlapped, 0, sizeof(req->overlapped)); /* * Preallocate a read buffer if the number of active streams is below * the threshold. */ if (active_tcp_streams < uv_active_tcp_streams_threshold) { handle->flags &= ~UV_HANDLE_TCP_ZERO_READ; handle->read_buffer = handle->alloc_cb((uv_stream_t*)handle, 65536); assert(handle->read_buffer.len > 0); buf = handle->read_buffer; } else { handle->flags |= UV_HANDLE_TCP_ZERO_READ; buf.base = (char*) &uv_zero_; buf.len = 0; } flags = 0; result = WSARecv(handle->socket, (WSABUF*)&buf, 1, &bytes, &flags, &req->overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; req->overlapped.InternalHigh = bytes; handle->reqs_pending++; uv_insert_pending_req(req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* The req will be processed with IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; } else { /* Make this req pending reporting an error. */ req->error = uv_new_sys_error(WSAGetLastError()); uv_insert_pending_req(req); handle->reqs_pending++; } }
int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in6 address, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int addrsize = sizeof(struct sockaddr_in6); BOOL success; DWORD bytes; if (!uv_allow_ipv6) { uv_new_sys_error(WSAEAFNOSUPPORT); return -1; } if (handle->flags & UV_HANDLE_BIND_ERROR) { loop->last_error = handle->bind_error; return -1; } if (address.sin6_family != AF_INET6) { uv_set_sys_error(loop, WSAEFAULT); return -1; } if (!(handle->flags & UV_HANDLE_BOUND) && uv_tcp_bind6(handle, uv_addr_ip6_any_) < 0) return -1; uv_req_init(loop, (uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->overlapped, 0, sizeof(req->overlapped)); success = pConnectEx6(handle->socket, (struct sockaddr*) &address, addrsize, NULL, 0, &bytes, &req->overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { handle->reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { handle->reqs_pending++; } else { uv_set_sys_error(loop, WSAGetLastError()); return -1; } return 0; }
int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) { if (addr.sin6_family != AF_INET6) { uv_set_sys_error(WSAEFAULT); return -1; } if (uv_allow_ipv6) { handle->flags |= UV_HANDLE_IPV6; return uv__bind(handle, AF_INET6, (struct sockaddr*)&addr, sizeof(struct sockaddr_in6)); } else { uv_new_sys_error(WSAEAFNOSUPPORT); return -1; } }
static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { HANDLE pipeHandle = INVALID_HANDLE_VALUE; int errno; uv_pipe_t* handle; uv_connect_t* req; req = (uv_connect_t*)parameter; assert(req); handle = (uv_pipe_t*)req->handle; assert(handle); /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait for the pipe to become available with WaitNamedPipe. */ while (WaitNamedPipeW(handle->name, 30000)) { /* The pipe is now available, try to connect. */ pipeHandle = CreateFileW(handle->name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (pipeHandle != INVALID_HANDLE_VALUE) { break; } } if (pipeHandle != INVALID_HANDLE_VALUE && !uv_set_pipe_handle(handle, pipeHandle)) { handle->handle = pipeHandle; req->error = uv_ok_; } else { req->error = uv_new_sys_error(GetLastError()); } memset(&req->overlapped, 0, sizeof(req->overlapped)); /* Post completed */ if (!PostQueuedCompletionStatus(LOOP->iocp, 0, 0, &req->overlapped)) { uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); } return 0; }
void uv_tcp_endgame(uv_tcp_t* handle) { uv_err_t err; int status; if (handle->flags & UV_HANDLE_CONNECTION && handle->flags & UV_HANDLE_SHUTTING && !(handle->flags & UV_HANDLE_SHUT) && handle->write_reqs_pending == 0) { if (shutdown(handle->socket, SD_SEND) != SOCKET_ERROR) { status = 0; handle->flags |= UV_HANDLE_SHUT; } else { status = -1; err = uv_new_sys_error(WSAGetLastError()); } if (handle->shutdown_req->cb) { if (status == -1) { LOOP->last_error = err; } handle->shutdown_req->cb(handle->shutdown_req, status); } handle->reqs_pending--; } if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->accept_reqs) { free(handle->accept_reqs); handle->accept_reqs = NULL; } if (handle->close_cb) { handle->close_cb((uv_handle_t*)handle); } active_tcp_streams--; uv_unref(); } }
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned int flags) { uv_loop_t* loop = handle->loop; if (addr.sin6_family != AF_INET6) { uv_set_sys_error(loop, WSAEFAULT); return -1; } if (uv_allow_ipv6) { handle->flags |= UV_HANDLE_IPV6; return uv__bind(handle, AF_INET6, (struct sockaddr*) &addr, sizeof(struct sockaddr_in6), flags); } else { uv_new_sys_error(WSAEAFNOSUPPORT); return -1; } }
static void uv_poll_ex(int block) { BOOL success; DWORD timeout; uv_req_t* req; OVERLAPPED_ENTRY overlappeds[64]; ULONG count; ULONG i; if (block) { timeout = uv_get_poll_timeout(); } else { timeout = 0; } assert(pGetQueuedCompletionStatusEx); success = pGetQueuedCompletionStatusEx(LOOP->iocp, overlappeds, COUNTOF(overlappeds), &count, timeout, FALSE); if (success) { for (i = 0; i < count; i++) { /* Package was dequeued */ req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); if (overlappeds[i].lpOverlapped->Internal != STATUS_SUCCESS) { req->error = uv_new_sys_error(pRtlNtStatusToDosError( overlappeds[i].lpOverlapped->Internal)); } uv_insert_pending_req(req); } } else if (GetLastError() != WAIT_TIMEOUT) { /* Serious error */ uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); } }
static int uv__bind(uv_loop_t* loop, uv_tcp_t* handle, int domain, struct sockaddr* addr, int addrsize) { DWORD err; int r; SOCKET sock; if (handle->socket == INVALID_SOCKET) { sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { uv_set_sys_error(loop, WSAGetLastError()); return -1; } if (uv_tcp_set_socket(loop, handle, sock) == -1) { closesocket(sock); return -1; } } r = bind(handle->socket, addr, addrsize); if (r == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAEADDRINUSE) { /* Some errors are not to be reported until connect() or listen() */ handle->bind_error = uv_new_sys_error(err); handle->flags |= UV_HANDLE_BIND_ERROR; } else { uv_set_sys_error(loop, err); return -1; } } handle->flags |= UV_HANDLE_BOUND; return 0; }