Пример #1
0
DWORD
VmDnsSockPosixSetNonBlocking(
    PVM_SOCKET pSocket
    )
{
    DWORD dwError = 0;
    BOOLEAN bLocked = FALSE;

    dwError = VmDnsLockMutex(pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    bLocked = TRUE;

    dwError = VmDnsSockPosixSetDescriptorNonBlocking(pSocket->fd);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }

    return dwError;

error:

    goto cleanup;
}
Пример #2
0
DWORD
VmDnsSockPosixCloseSocket(
    PVM_SOCKET pSocket
    )
{
    DWORD dwError = 0;
    BOOLEAN bLocked = FALSE;

    dwError = VmDnsLockMutex(pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    bLocked = TRUE;

    if (pSocket->fd >= 0)
    {
        close(pSocket->fd);
        pSocket->fd = -1;
    }

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }

    return dwError;

error:

    goto cleanup;
}
Пример #3
0
DWORD
VmDnsConditionTimedWait(
    PVMDNS_COND pCondition,
    PVMDNS_MUTEX pMutex,
    DWORD dwMilliseconds
)
{
    DWORD dwError = ERROR_SUCCESS;
    struct timespec ts = {0};
    BOOL bLocked = FALSE;

    if ( ( pCondition == NULL )
         ||
         ( pCondition->bInitialized == FALSE )
         ||
         ( pMutex == NULL )
         ||
         ( pMutex->bInitialized == FALSE )
       )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    ts.tv_sec = time(NULL) + dwMilliseconds/1000;
    ts.tv_nsec = 0;

    dwError = VmDnsLockMutex(pMutex);
    BAIL_ON_VMDNS_ERROR(dwError);

    bLocked = TRUE;

    dwError = pthread_cond_timedwait(
        &(pCondition->cond),
        &(pMutex->critSect),
        &ts
    );
    BAIL_ON_VMDNS_ERROR(dwError);

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pMutex);
    }

    return dwError;

error:

    goto cleanup;
}
Пример #4
0
DWORD
VmDnsSockPosixSetData(
    PVM_SOCKET           pSocket,
    PVOID                pData,
    PVOID*               ppOldData
    )
{
    DWORD dwError = 0;
    BOOLEAN bLocked = FALSE;
    PVOID   pOldData = NULL;

    if (!pSocket)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    dwError = VmDnsLockMutex(pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    bLocked = TRUE;

    pOldData = pSocket->pData;

    pSocket->pData = pData;

    if (ppOldData)
    {
        *ppOldData = pOldData;
    }

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }

    return dwError;

error:

    if (ppOldData)
    {
        *ppOldData = NULL;
    }

    goto cleanup;
}
Пример #5
0
DWORD
VmDnsSockPosixSetTimeOut(
    PVM_SOCKET pSocket,
    DWORD      dwTimeOut
    )
{
    DWORD dwError = 0;
    BOOLEAN bLocked = FALSE;

    if (!pSocket)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    if (dwTimeOut)
    {
        struct timeval tv = {0};
        dwError = VmDnsLockMutex(pSocket->pMutex);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);

        bLocked = TRUE;

        tv.tv_sec = dwTimeOut;
        if (setsockopt(pSocket->fd, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0)
        {
            dwError = LwErrnoToWin32Error(errno);
            BAIL_ON_POSIX_SOCK_ERROR(dwError);
        }

        if (setsockopt(pSocket->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
        {
            dwError = LwErrnoToWin32Error(errno);
            BAIL_ON_POSIX_SOCK_ERROR(dwError);
        }
    }

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }
    return dwError;

error:

    goto cleanup;
}
Пример #6
0
DWORD
VmDnsSockPosixGetProtocol(
    PVM_SOCKET           pSocket,
    PDWORD               pdwProtocol
    )
{
    DWORD dwError = 0;
    BOOLEAN bLocked = FALSE;
    DWORD dwProtocol = 0;

    if (!pSocket || !pdwProtocol)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    dwError = VmDnsLockMutex(pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    bLocked = TRUE;

    switch (pSocket->protocol)
    {
        case VM_SOCK_PROTOCOL_UDP:

            dwProtocol = SOCK_DGRAM;

            break;

        case VM_SOCK_PROTOCOL_TCP:

            dwProtocol = SOCK_STREAM;

            break;

        default:

            dwError = ERROR_INTERNAL_ERROR;
            BAIL_ON_POSIX_SOCK_ERROR(dwError);

            break;
    }

    *pdwProtocol = dwProtocol;

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }

    return dwError;

error:

    if (pdwProtocol)
    {
        *pdwProtocol = 0;
    }

    goto cleanup;
}
Пример #7
0
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;
}
Пример #8
0
DWORD
VmDnsSockPosixWrite(
    PVM_SOCKET          pSocket,
    const struct sockaddr*    pClientAddress,
    socklen_t           addrLength,
    PVM_SOCK_IO_BUFFER  pIoBuffer
    )
{
    DWORD   dwError  = 0;
    BOOLEAN bLocked  = FALSE;
    int     flags    = 0;
    ssize_t nWritten = 0;
    DWORD dwBytesToWrite = 0;
    const struct sockaddr* pClientAddressLocal = NULL;
    socklen_t addrLengthLocal = 0;

    if (!pSocket || !pIoBuffer || !pIoBuffer->pData)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    dwBytesToWrite = pIoBuffer->dwExpectedSize - pIoBuffer->dwCurrentSize;

    if (pClientAddress && addrLength)
    {
        pClientAddressLocal = pClientAddress;
        addrLengthLocal = addrLength;
    }
    else
    {
        pClientAddressLocal = &pSocket->addr;
        addrLengthLocal = pSocket->addrLen;
    }

    dwError = VmDnsLockMutex(pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    bLocked = TRUE;

    nWritten = sendto(
                    pSocket->fd,
                    pIoBuffer->pData,
                    dwBytesToWrite,
                    flags,
                    pClientAddressLocal,
                    addrLengthLocal);
    if (nWritten < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    pIoBuffer->dwCurrentSize += nWritten;
    pIoBuffer->dwTotalBytesTransferred += nWritten;

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }

    return dwError;

error:

    goto cleanup;
}
Пример #9
0
DWORD
VmDnsSockPosixRead(
    PVM_SOCKET          pSocket,
    PVM_SOCK_IO_BUFFER  pIoBuffer
    )
{
    DWORD   dwError = 0;
    BOOLEAN bLocked = FALSE;
    int     flags   = 0;
    ssize_t nRead   = 0;
    DWORD dwBufSize = 0;
    DWORD dwSockAddrLen = 0;

    if (!pSocket || !pIoBuffer || !pIoBuffer->pData)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    if (pIoBuffer->dwExpectedSize < pIoBuffer->dwCurrentSize)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    dwBufSize = pIoBuffer->dwExpectedSize - pIoBuffer->dwCurrentSize;
    dwSockAddrLen = sizeof pIoBuffer->clientAddr;

    dwError = VmDnsLockMutex(pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    bLocked = TRUE;

    nRead = recvfrom(
                pSocket->fd,
                pIoBuffer->pData + pIoBuffer->dwCurrentSize,
                dwBufSize,
                flags,
                (struct sockaddr*)&pIoBuffer->clientAddr,
                &dwSockAddrLen);
    if (nRead < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    pIoBuffer->addrLen = dwSockAddrLen;

    pIoBuffer->dwCurrentSize += nRead;
    pIoBuffer->dwTotalBytesTransferred += nRead;

cleanup:

    if (bLocked)
    {
        VmDnsUnlockMutex(pSocket->pMutex);
    }

    return dwError;

error:

    goto cleanup;
}