//DESCRIPTION: // This function creates the completion port and the requested number of threads. // If threads creation fails, the successfully created threads' handles are closed before returning. // //INPUT: // nbOfThreads - the number of threads to create // pWorkerThreads - the ouput pointer to the thread handle array // pAsync_config - the config struct // //OUTPUT: // TRUE for success // FALSE for error // BOOL AsyncFuzzer::InitializeThreadsAndCompletionPort() { BOOL bResult = FALSE; hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0); if(hIocp) { // Associate the device handle to iocp bResult = (NULL!=CreateIoCompletionPort(hDev, hIocp, 0, 0)); if(bResult) { // Configure io completion port bResult = SetFileCompletionNotificationModes(hDev, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS); if(bResult) { bResult = CreateThreads(); if(!bResult){ TPRINT(VERBOSITY_ERROR, _T("Failed to create worker threads\n")); } } else { TPRINT(VERBOSITY_ERROR, _T("Failed to configure iocompletion port with error %#.8x\n"), GetLastError()); } } else { TPRINT(VERBOSITY_ERROR, _T("Failed to associate device with iocompletion port with error %#.8x\n"), GetLastError()); } } else { TPRINT(VERBOSITY_ERROR, _T("Failed to create I/O completion port with error %#.8x\n"), GetLastError()); } return bResult; }
void ThreadPool::AssociateHandle(native_handle_t h, LPFN_COMPLETION_PROC fn) { panic_if(queue == nullptr, "ThreadPool is not initialized"); if (startSockets.syncCompletion) { auto success = SetFileCompletionNotificationModes( (HANDLE)h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS); panic_if(!success, "FILE_SKIP_COMPLETION_PORT_ON_SUCCESS"); } queue->AssociateHandle((HANDLE)h, fn); }
static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, int family) { DWORD yes = 1; WSAPROTOCOL_INFOW info; int opt_len; if (handle->socket != INVALID_SOCKET) return UV_EBUSY; /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { return WSAGetLastError(); } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) { return GetLastError(); } /* Associate it with the I/O completion port. Use uv_handle_t pointer as * completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, 0) == NULL) { return GetLastError(); } /* All known Windows that support SetFileCompletionNotificationModes have a * bug that makes it impossible to use this function in conjunction with * datagram sockets. We can work around that but only if the user is using * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here * we check whether that is the case. */ opt_len = (int) sizeof info; if (getsockopt( socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) == SOCKET_ERROR) { return GetLastError(); } if (info.ProtocolChain.ChainLen == 1) { if (SetFileCompletionNotificationModes( (HANDLE) socket, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; handle->func_wsarecv = uv_wsarecv_workaround; handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; } else if (GetLastError() != ERROR_INVALID_FUNCTION) { return GetLastError(); } } handle->socket = socket; if (family == AF_INET6) { handle->flags |= UV_HANDLE_IPV6; } else { assert(!(handle->flags & UV_HANDLE_IPV6)); } return 0; }
DWORD CreateHttpListener( OUT PHTTP_LISTENER* httpListener ) { ULONG result; PHTTP_LISTENER _listener = (PHTTP_LISTENER)ALLOC_MEM(sizeof(HTTP_LISTENER)); ZeroMemory(_listener, sizeof(HTTP_LISTENER)); (*httpListener) = _listener; _listener->hRequestQueue = NULL; _listener->RequestQueueLength = 5000; // Default request queue length; _listener->errorCode = 0; _listener->urls = NULL; _listener->pthreadPoolIO = NULL; _listener->State = HTTP_LISTENER_STATE_FAULTED; _listener->stats = (PLISTENER_STATS)_aligned_malloc(sizeof(LISTENER_STATS),MEMORY_ALLOCATION_ALIGNMENT); HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_2; // // Initialize HTTP APIs. // result = HttpInitialize( HttpApiVersion, HTTP_INITIALIZE_SERVER, // Flags NULL // Reserved ); if (result != NO_ERROR) { DEBUG_ASSERT(false); LOG_ERROR(L"\nHttpInitialize failed with %lu", result); } if(result == NO_ERROR) { result = HttpCreateServerSession(HttpApiVersion, &_listener->SessionId, NULL); if(result) { LOG_ERROR(L"\nHttpCreateServerSession failed with %lu", result); } } if(result == NO_ERROR) { result = HttpCreateRequestQueue(HttpApiVersion, NULL, NULL, 0, &_listener->hRequestQueue); if(result) { LOG_ERROR(L"\nHttpCreateRequestQueue failed with %lu", result); } } if(result == NO_ERROR) { result = HttpSetRequestQueueProperty(_listener->hRequestQueue, HttpServerQueueLengthProperty, &_listener->RequestQueueLength, sizeof(_listener->RequestQueueLength), NULL, NULL); if(result) { LOG_ERROR(L"\nHttpSetRequestQueueProperty failed with %lu", result); } } if(result == NO_ERROR) { if(SetFileCompletionNotificationModes(_listener->hRequestQueue, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE) == FALSE) { result = GetLastError(); } } if(result == NO_ERROR) { result = HttpListenerInitializeThreadPool(_listener); } if(result == NO_ERROR) { _listener->pthreadPoolIO = CreateThreadpoolIo(_listener->hRequestQueue, HttpListenerDemuxer, (void*)_listener, &_listener->tpEnvironment); } InitializeIOContextCache(); InitializeHttpInputQueue(_listener); _listener->errorCode = result; return _listener->errorCode; }
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int family, int imported) { DWORD yes = 1; int non_ifs_lsp; int err; if (handle->socket != INVALID_SOCKET) return UV_EBUSY; /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { return WSAGetLastError(); } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) return GetLastError(); /* Associate it with the I/O completion port. Use uv_handle_t pointer as * completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, 0) == NULL) { if (imported) { handle->flags |= UV_HANDLE_EMULATE_IOCP; } else { return GetLastError(); } } if (family == AF_INET6) { non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6; } else { non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; } if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { UCHAR sfcnm_flags = FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags)) return GetLastError(); handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; } if (handle->flags & UV_HANDLE_TCP_NODELAY) { err = uv__tcp_nodelay(handle, socket, 1); if (err) return err; } /* TODO: Use stored delay. */ if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) { err = uv__tcp_keepalive(handle, socket, 1, 60); if (err) return err; } handle->socket = socket; if (family == AF_INET6) { handle->flags |= UV_HANDLE_IPV6; } else { assert(!(handle->flags & UV_HANDLE_IPV6)); } return 0; }
int api_tcp_listen(api_tcp_listener_t* listener, api_loop_t* loop, const char* ip, int port, int backlog) { struct sockaddr_in* addr_in = (struct sockaddr_in*)&listener->address.address; struct sockaddr_in6* addr_in6 = (struct sockaddr_in6*)&listener->address.address; struct sockaddr* a = (struct sockaddr*)&listener->address.address; HANDLE handle; DWORD sys_error = 0; int error; if (loop->terminated) { listener->status.terminated = 1; return API__TERMINATE; } memset(listener, 0, sizeof(*listener)); if (strchr(ip, ':') == 0) { // ipv4 listener->fd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); listener->address.length = sizeof(struct sockaddr_in); addr_in->sin_family = AF_INET; addr_in->sin_addr.s_addr = inet_addr(ip); addr_in->sin_port = htons(port); listener->os_win.af = AF_INET; } else { // ipv6 listener->fd = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); listener->address.length = sizeof(struct sockaddr_in6); addr_in6->sin6_family = AF_INET6; addr_in6->sin6_addr = in6addr_any; addr_in6->sin6_port = htons(port); inet_pton(AF_INET6, ip, (void*)&addr_in6->sin6_addr); listener->os_win.af = AF_INET6; } error = api_socket_non_block(listener->fd, 1); error = api_socket_recv_buffer_size(listener->fd, 0); error = api_socket_send_buffer_size(listener->fd, 0); error = api_tcp_nodelay(listener->fd, 1); if (0 != bind(listener->fd, a, listener->address.length)) return api_error_translate(WSAGetLastError()); if (0 != listen(listener->fd, backlog)) return api_error_translate(WSAGetLastError()); listener->loop = loop; listener->os_win.processor = api_tcp_listener_processor; listener->on_closed = api_tcp_listener_on_closed; listener->on_error = api_tcp_listener_on_error; listener->on_terminate = api_tcp_listener_on_terminate; listener->on_accept = api_tcp_listener_on_accept; handle = CreateIoCompletionPort((HANDLE)listener->fd, loop->iocp, (ULONG_PTR)&listener->os_win, 0); if (handle == NULL) { sys_error = GetLastError(); closesocket(listener->fd); error = api_error_translate(sys_error); } if (API__OK != error) { listener->loop = loop; api_loop_ref(loop); return API__OK; } else { SetFileCompletionNotificationModes((HANDLE)listener->fd, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS); } return error; }
int api_tcp_connect(api_tcp_t* tcp, api_loop_t* loop, const char* ip, int port, uint64_t tmeout) { struct sockaddr_in* addr_in = (struct sockaddr_in*)&tcp->address.address; struct sockaddr_in6* addr_in6 = (struct sockaddr_in6*)&tcp->address.address; struct sockaddr* a = (struct sockaddr*)&tcp->address.address; api_timer_t timeout; uint64_t timeout_value = tmeout; HANDLE handle; DWORD dwSent = 0; DWORD sys_error = 0; BOOL result; BOOL completed = FALSE; int af; int error = API__OK; memset(tcp, 0, sizeof(*tcp)); if (loop->terminated) { tcp->stream.status.terminated = 1; return API__TERMINATE; } tcp->stream.os_win.processor = api_tcp_connect_processor; tcp->stream.os_win.reserved[0] = loop->scheduler.current; if (strchr(ip, ':') == 0) { // ipv4 tcp->stream.fd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); af = AF_INET; tcp->address.length = sizeof(struct sockaddr_in); addr_in->sin_family = AF_INET; addr_in->sin_addr.s_addr = INADDR_ANY; addr_in->sin_port = 0; } else { // ipv6 tcp->stream.fd = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); af = AF_INET6; tcp->address.length = sizeof(struct sockaddr_in6); addr_in6->sin6_family = AF_INET6; addr_in6->sin6_addr = in6addr_any; addr_in6->sin6_port = 0; } error = api_socket_non_block(tcp->stream.fd, 1); error = api_socket_recv_buffer_size(tcp->stream.fd, 0); error = api_socket_send_buffer_size(tcp->stream.fd, 0); error = api_tcp_nodelay(tcp->stream.fd, 1); if (0 != bind(tcp->stream.fd, a, tcp->address.length)) { error = api_error_translate(WSAGetLastError()); closesocket(tcp->stream.fd); return error; } handle = CreateIoCompletionPort((HANDLE)tcp->stream.fd, loop->iocp, (ULONG_PTR)&tcp->stream.os_win, 0); if (handle == NULL) { sys_error = GetLastError(); closesocket(tcp->stream.fd); return api_error_translate(sys_error); } SetFileCompletionNotificationModes((HANDLE)tcp->stream.fd, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS); if (af == AF_INET) { addr_in->sin_family = AF_INET; addr_in->sin_addr.s_addr = inet_addr(ip); addr_in->sin_port = htons(port); } else { addr_in6->sin6_family = AF_INET6; addr_in6->sin6_addr = in6addr_any; addr_in6->sin6_port = htons(port); inet_pton(AF_INET6, ip, (void*)&addr_in6->sin6_addr); } if (timeout_value > 0) { memset(&timeout, 0, sizeof(timeout)); timeout.task = loop->scheduler.current; api_timeout_exec(&loop->timeouts, &timeout, timeout_value); } result = lpfnConnectEx(tcp->stream.fd, a, tcp->address.length, NULL, 0, &dwSent, (LPOVERLAPPED)&tcp->stream.os_win.read); if (!result) { sys_error = WSAGetLastError(); if (sys_error == ERROR_SUCCESS) { completed = TRUE; } else if (sys_error != WSA_IO_PENDING) { completed = TRUE; error = api_error_translate(sys_error); tcp->stream.status.error = error; } } else { completed = TRUE; } if (!completed) api_task_sleep(loop->scheduler.current); if (timeout_value > 0) api_timeout_exec(&loop->timeouts, &timeout, 0); if (timeout_value > 0 && timeout.elapsed) { tcp->stream.status.read_timeout = 1; if (API__OK != error) error = api_error_translate(ERROR_TIMEOUT); } if (API__OK == error) { api_stream_init(&tcp->stream, STREAM_Tcp, tcp->stream.fd); tcp->stream.loop = loop; api_loop_ref(loop); return API__OK; } else { closesocket(tcp->stream.fd); } return error; }