VOID VmDnsSockPosixFreeEventQueue( PVM_SOCK_EVENT_QUEUE pQueue ) { if (pQueue->pSignalReader) { VmDnsSockPosixReleaseSocket(pQueue->pSignalReader); } if (pQueue->pSignalWriter) { VmDnsSockPosixReleaseSocket(pQueue->pSignalWriter); } if (pQueue->pMutex) { VmDnsFreeMutex(pQueue->pMutex); } if (pQueue->epollFd >= 0) { close(pQueue->epollFd); } if (pQueue->pEventArray) { VmDnsFreeMemory(pQueue->pEventArray); pQueue->pEventArray = NULL; } VmDnsFreeMemory(pQueue); }
VOID VmDnsSockPosixFreeIoBuffer( PVM_SOCK_IO_BUFFER pIoBuffer ) { // VMDNS_LOG_DEBUG("pIoBuffer:%p released from thread %p", pIoBuffer, pthread_self()); if (pIoBuffer && pIoBuffer->pClientSocket) { VmDnsSockPosixReleaseSocket(pIoBuffer->pClientSocket); } PVM_SOCK_IO_CONTEXT pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); VMDNS_SAFE_FREE_MEMORY(pIoContext); }
VOID VmDnsSockPosixFreeIoBuffer( PVM_SOCK_IO_BUFFER pIoBuffer ) { PVM_SOCK_IO_CONTEXT pIoContext = NULL; if (pIoBuffer) { if (pIoBuffer->pClientSocket) { VmDnsSockPosixReleaseSocket(pIoBuffer->pClientSocket); } pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); VMDNS_SAFE_FREE_MEMORY(pIoContext); } }
static DWORD VmDnsSockPosixEventQueueDelete_inlock( PVM_SOCK_EVENT_QUEUE pQueue, PVM_SOCKET pSocket ) { DWORD dwError = 0; struct epoll_event event = {0}; if (pSocket->bInEventQueue == TRUE && epoll_ctl(pQueue->epollFd, EPOLL_CTL_DEL, pSocket->fd, &event) < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } pSocket->bInEventQueue = FALSE; VmDnsSockPosixReleaseSocket(pSocket); error: return dwError; }
DWORD VmDnsSockPosixWaitForEvent( PVM_SOCK_EVENT_QUEUE pQueue, int iTimeoutMS, PVM_SOCKET* ppSocket, PVM_SOCK_EVENT_TYPE pEventType, PVM_SOCK_IO_BUFFER* ppIoBuffer ) { DWORD dwError = 0; BOOLEAN bLocked = FALSE; VM_SOCK_EVENT_TYPE eventType = VM_SOCK_EVENT_TYPE_UNKNOWN; PVM_SOCKET pSocket = NULL; PVM_SOCK_IO_BUFFER pIoBuffer = NULL; PVM_SOCK_IO_CONTEXT pIoContext = NULL; uint64_t uiTriggerCount = 0; if (!pQueue || !ppSocket || !pEventType) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_POSIX_SOCK_ERROR(dwError); } dwError = VmDnsLockMutex(pQueue->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); bLocked = TRUE; if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } if ((pQueue->state == VM_SOCK_POSIX_EVENT_STATE_PROCESS) && (pQueue->iReady >= pQueue->nReady)) { pQueue->state = VM_SOCK_POSIX_EVENT_STATE_WAIT; } if (pQueue->state == VM_SOCK_POSIX_EVENT_STATE_WAIT) { pQueue->iReady = 0; pQueue->nReady = -1; while (pQueue->nReady < 0) { pQueue->nReady = epoll_wait( pQueue->epollFd, pQueue->pEventArray, pQueue->dwSize, iTimeoutMS); if ((pQueue->nReady < 0) && (errno != EINTR)) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } } pQueue->state = VM_SOCK_POSIX_EVENT_STATE_PROCESS; } if (pQueue->state == VM_SOCK_POSIX_EVENT_STATE_PROCESS) { if (pQueue->iReady < pQueue->nReady) { struct epoll_event* pEvent = &pQueue->pEventArray[pQueue->iReady]; PVM_SOCKET pEventSocket = (PVM_SOCKET)pEvent->data.ptr; if (!pEventSocket) { dwError = ERROR_INVALID_STATE; BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (pEvent->events & (EPOLLERR | EPOLLHUP)) { eventType = VM_SOCK_EVENT_TYPE_CONNECTION_CLOSED; pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); dwError = VmDnsSockPosixEventQueueDelete_inlock( pQueue, pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); } else if (pEventSocket->type == VM_SOCK_TYPE_LISTENER) { switch (pEventSocket->protocol) { case VM_SOCK_PROTOCOL_TCP: dwError = VmDnsSockPosixAcceptConnection( pEventSocket, &pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); dwError = VmDnsSockPosixSetNonBlocking(pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); eventType = VM_SOCK_EVENT_TYPE_TCP_NEW_CONNECTION; break; case VM_SOCK_PROTOCOL_UDP: pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE; break; default: dwError = ERROR_INVALID_STATE; BAIL_ON_POSIX_SOCK_ERROR(dwError); break; } } else if (pEventSocket->type == VM_SOCK_TYPE_SERVER) { switch (pEventSocket->protocol) { case VM_SOCK_PROTOCOL_TCP: if (!pEventSocket->pData) { eventType = VM_SOCK_EVENT_TYPE_TCP_REQUEST_SIZE_READ; } pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); break; default: dwError = ERROR_INVALID_STATE; BAIL_ON_POSIX_SOCK_ERROR(dwError); break; } } else if (pEventSocket->type == VM_SOCK_TYPE_SIGNAL) { if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } else { pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); } } else if (pEventSocket->type == VM_SOCK_TYPE_TIMER) { if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } else { pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); if (read(pSocket->fd, &uiTriggerCount, sizeof(uiTriggerCount)) < 0) { VMDNS_LOG_ERROR("%s: read() on timer fd failed (%d)", __FUNCTION__, errno); } eventType = VM_SOCK_EVENT_TYPE_TIMER_EXPIRATION; } } else { pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); } } pQueue->iReady++; } dwError = VmDnsSockPosixSetData(pSocket, NULL, (PVOID *)&pIoBuffer); BAIL_ON_POSIX_SOCK_ERROR(dwError); if (pIoBuffer && eventType == VM_SOCK_EVENT_TYPE_UNKNOWN) { pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); eventType = pIoContext->eventType; } *ppSocket = pSocket; *ppIoBuffer = pIoBuffer; *pEventType = eventType; cleanup: if (bLocked) { VmDnsUnlockMutex(pQueue->pMutex); } return dwError; error: if (ppSocket) { *ppSocket = NULL; } if (ppIoBuffer) { *ppIoBuffer = NULL; } if (pEventType) { *pEventType = VM_SOCK_EVENT_TYPE_UNKNOWN; } if (pSocket) { VmDnsSockPosixReleaseSocket(pSocket); } goto cleanup; }