Example #1
0
DWORD
VmDnsSockPosixEventQueueRemove(
    PVM_SOCK_EVENT_QUEUE pQueue,
    PVM_SOCKET           pSocket
    )
{
    DWORD   dwError = 0;

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

    dwError = VmDnsSockPosixEventQueueDelete_inlock(pQueue, pSocket);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

cleanup:

    return dwError;

error:

    goto cleanup;
}
Example #2
0
static
DWORD
VmDnsSockPosixSetDescriptorNonBlocking(
    int fd
    )
{
    DWORD dwError = 0;
    int flags = 0;

    if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    flags |= O_NONBLOCK;

    if ((flags = fcntl(fd, F_SETFL, flags)) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

error:

    return dwError;
}
Example #3
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;
}
Example #4
0
static
DWORD
VmDnsSockPosixAcceptConnection(
    PVM_SOCKET  pListener,
    PVM_SOCKET* ppSocket
    )
{
    DWORD dwError = 0;
    PVM_SOCKET pSocket = NULL;
    int fd = -1;

    dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pSocket->refCount = 1;

    dwError = VmDnsAllocateMutex(&pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pSocket->protocol = pListener->protocol;
    pSocket->type = VM_SOCK_TYPE_SERVER;

    fd = accept(pListener->fd, &pSocket->addr, &pSocket->addrLen);
    if (fd < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }


    pSocket->fd = fd;

    pSocket->pAddr = &pSocket->addr;

    *ppSocket = pSocket;

cleanup:

    return dwError;

error:

    *ppSocket = NULL;

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

    goto cleanup;
}
Example #5
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;
}
Example #6
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;
}
Example #7
0
DWORD
VmDnsSockPosixGetEventContext(
    PVM_SOCK_IO_BUFFER        pIoBuffer,
    PVM_SOCK_EVENT_CONTEXT*   ppEventContext
    )
{
    DWORD dwError = 0;
    PVM_SOCK_EVENT_CONTEXT pEventContext = NULL;
    PVM_SOCK_IO_CONTEXT pIoContext = NULL;

    if (!pIoBuffer || !ppEventContext)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }


    pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer);

    pEventContext = pIoContext->pEventContext;

    *ppEventContext = pEventContext;

cleanup:

    return dwError;
error:

    if (ppEventContext)
    {
        *ppEventContext = NULL;
    }
    goto cleanup;
}
Example #8
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;
}
Example #9
0
static
DWORD
VmDnsSockPosixEventQueueRearm_inlock(
    PVM_SOCK_EVENT_QUEUE pQueue,
    BOOL                 bOneShot,
    PVM_SOCKET           pSocket
    )
{
    DWORD dwError = 0;
    struct epoll_event event = {0};

    event.data.ptr = pSocket;
    event.events = EPOLLIN;
    if (bOneShot)
    {
       event.events = event.events | EPOLLONESHOT;
    }

    if (pSocket->bInEventQueue == TRUE &&
        epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

error:

    return dwError;
}
Example #10
0
static
DWORD
VmDnsSockPosixSetReuseAddress(
    int fd
    )
{
    DWORD dwError = 0;
    int on = 1;

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

error:

    return dwError;
}
Example #11
0
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;
}
Example #12
0
DWORD
VmDnsSockPosixCreateTimerSocket(
    DWORD       dwInitialMS,
    DWORD       dwIntervalMS,
    PVM_SOCKET* ppSocket
    )
{
    DWORD       dwError = 0;
    int         timerFd = -1;
    PVM_SOCKET  pSocket = NULL;
    struct      itimerspec ts = {0};
    int         nSec = 0;
    int         nNanoSec = 0;

    if (!ppSocket)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }
    timerFd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (timerFd == -1)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    nSec = dwInitialMS / 1000;
    nNanoSec = (dwInitialMS % 1000) * 1000000;
    ts.it_value.tv_sec = nSec;
    ts.it_value.tv_nsec = nNanoSec;

    nSec = dwIntervalMS / 1000;
    nNanoSec = (dwIntervalMS % 1000) * 1000000;
    ts.it_interval.tv_sec = nSec;
    ts.it_interval.tv_nsec = nNanoSec;

    if (timerfd_settime(timerFd, 0, &ts, NULL) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    dwError = VmDnsAllocateMemory(
                  sizeof(VM_SOCKET),
                  (PVOID*)&pSocket);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    dwError = VmDnsAllocateMutex(&pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pSocket->refCount = 1;
    pSocket->protocol = VM_SOCK_PROTOCOL_UNKNOWN;
    pSocket->type = VM_SOCK_TYPE_TIMER;
    pSocket->fd = timerFd;

    *ppSocket = pSocket;

cleanup:

    return dwError;

error:

    if (timerFd > 0)
    {
        close(timerFd);
    }

    if (pSocket)
    {
        VmDnsSockPosixFreeSocket(pSocket);
        pSocket = NULL;
    }

    goto cleanup;
}
Example #13
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;
}
Example #14
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;
}
Example #15
0
DWORD
VmDnsSockPosixOpenClient(
    PCSTR                pszHost,
    USHORT               usPort,
    VM_SOCK_CREATE_FLAGS dwFlags,
    DWORD                dwTimeoutMS,
    PVM_SOCKET*          ppSocket
    )
{
    DWORD dwError = 0;
    struct addrinfo  hints   = {0};
    struct addrinfo* pAddrInfo = NULL;
    struct addrinfo* pInfo = NULL;
    int fd = -1;
    PVM_SOCKET pSocket = NULL;
    CHAR szPort[32];
    struct timeval sTimeout = {0};

    if (!pszHost || !usPort || !ppSocket)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    sprintf(szPort, "%d", usPort);

    if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6)
    {
        hints.ai_family = AF_INET6;
    }
    else if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV4)
    {
        hints.ai_family = AF_INET;
    }
    else
    {
        hints.ai_family = AF_UNSPEC;
    }

    if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP)
    {
        hints.ai_socktype = SOCK_DGRAM;
    }
    else
    {
        hints.ai_socktype = SOCK_STREAM;
    }

    hints.ai_flags    = AI_CANONNAME | AI_NUMERICSERV;

    /* This will use DNS */
    if (getaddrinfo(pszHost, szPort, &hints, &pAddrInfo) != 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    for (pInfo = pAddrInfo; (fd < 0) && (pInfo != NULL); pInfo = pInfo->ai_next)
    {
        fd = socket(pInfo->ai_family, pInfo->ai_socktype, pInfo->ai_protocol);

        if (fd < 0)
        {
            continue;
        }

        if (dwTimeoutMS)
        {
            sTimeout.tv_sec  = dwTimeoutMS / 1000;
            sTimeout.tv_usec = (dwTimeoutMS % 1000) * 1000;
            if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&sTimeout, sizeof(sTimeout)) == -1)
            {
                close(fd);
                fd = -1;

                continue;
            }
        }

        if (connect(fd, pInfo->ai_addr, pInfo->ai_addrlen) < 0)
        {
            close(fd);
            fd = -1;

            continue;
        }

        break;
    }

    if (fd < 0)
    {
        dwError = ERROR_CONNECTION_UNAVAIL;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    if (dwFlags & VM_SOCK_CREATE_FLAGS_NON_BLOCK)
    {
        dwError = VmDnsSockPosixSetDescriptorNonBlocking(fd);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pSocket->refCount = 1;

    pSocket->type = VM_SOCK_TYPE_CLIENT;

    if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP)
    {
        pSocket->protocol = VM_SOCK_PROTOCOL_UDP;
    }
    else
    {
        pSocket->protocol = VM_SOCK_PROTOCOL_TCP;
    }

    dwError = VmDnsAllocateMutex(&pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    memcpy(&pSocket->addr, pInfo->ai_addr, pInfo->ai_addrlen);
    pSocket->addrLen = pInfo->ai_addrlen;
    pSocket->fd = fd;

    *ppSocket = pSocket;

cleanup:

    if (pAddrInfo)
    {
        freeaddrinfo(pAddrInfo);
    }

    return dwError;

error:

    if (ppSocket)
    {
        *ppSocket = NULL;
    }
    if (pSocket)
    {
        VmDnsSockPosixFreeSocket(pSocket);
    }
    if (fd >= 0)
    {
        close(fd);
    }

    goto cleanup;
}
Example #16
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;
}
Example #17
0
DWORD
VmDnsSockPosixCreateEventQueue(
    int                   iEventQueueSize,
    PVM_SOCK_EVENT_QUEUE* ppQueue
    )
{
    DWORD dwError = 0;
    PVM_SOCK_EVENT_QUEUE pQueue = NULL;

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

    if (iEventQueueSize <= 0)
    {
        iEventQueueSize = VM_SOCK_POSIX_DEFAULT_QUEUE_SIZE;
    }

    dwError = VmDnsAllocateMemory(sizeof(*pQueue), (PVOID*)&pQueue);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    dwError = VmDnsSockPosixCreateSignalSockets(
                    &pQueue->pSignalReader,
                    &pQueue->pSignalWriter);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    dwError = VmDnsAllocateMutex(&pQueue->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    dwError = VmDnsAllocateMemory(
                    iEventQueueSize * sizeof(*pQueue->pEventArray),
                    (PVOID*)&pQueue->pEventArray);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pQueue->dwSize = iEventQueueSize;

    pQueue->epollFd = epoll_create(pQueue->dwSize);
    if (pQueue->epollFd < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    pQueue->state  = VM_SOCK_POSIX_EVENT_STATE_WAIT;
    pQueue->nReady = -1;
    pQueue->iReady = 0;

    dwError = VmDnsSockPosixEventQueueAdd_inlock(pQueue, FALSE, pQueue->pSignalReader);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    *ppQueue = pQueue;

cleanup:

    return dwError;

error:

    if (ppQueue)
    {
        *ppQueue = NULL;
    }

    if (pQueue)
    {
        VmDnsSockPosixFreeEventQueue(pQueue);
    }

    goto cleanup;
}
Example #18
0
DWORD
VmDnsSockPosixOpenServer(
    USHORT               usPort,
    int                  iListenQueueSize,
    VM_SOCK_CREATE_FLAGS dwFlags,
    PVM_SOCKET*          ppSocket
    )
{
    DWORD dwError = 0;
    union
    {
#ifdef AF_INET6
        struct sockaddr_in6 servaddr_ipv6;
#endif
        struct sockaddr_in  servaddr_ipv4;
    } servaddr;
    struct
    {
        int domain;
        int type;
        int protocol;
    } socketParams;
    struct sockaddr* pSockAddr = NULL;
    socklen_t addrLen = 0;
    int fd = -1;
    PVM_SOCKET pSocket = NULL;

    if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6)
    {
#ifdef AF_INET6
        socketParams.domain = AF_INET6;
#else
        dwError = ERROR_NOT_SUPPORTED;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
#endif
    }
    else
    {
        socketParams.domain = AF_INET;
    }

    if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP)
    {
        socketParams.type = SOCK_DGRAM;
    }
    else
    {
        socketParams.type = SOCK_STREAM;
    }

    socketParams.protocol = 0;

    fd = socket(socketParams.domain, socketParams.type, socketParams.protocol);
    if (fd < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    if (dwFlags & VM_SOCK_CREATE_FLAGS_REUSE_ADDR)
    {
        dwError = VmDnsSockPosixSetReuseAddress(fd);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    memset(&servaddr, 0, sizeof(servaddr));

    if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6)
    {
#ifdef AF_INET6
        servaddr.servaddr_ipv6.sin6_family = AF_INET6;
        servaddr.servaddr_ipv6.sin6_addr = in6addr_any;
        servaddr.servaddr_ipv6.sin6_port = htons(usPort);

        pSockAddr = (struct sockaddr*) &servaddr.servaddr_ipv6;
        addrLen = sizeof(servaddr.servaddr_ipv6);

#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
        int one = 1;
        setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (void *) &one, sizeof(one));
#endif

#else
        dwError = ERROR_NOT_SUPPORTED;
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
#endif
    }
    else
    {
        servaddr.servaddr_ipv4.sin_family = AF_INET;
        servaddr.servaddr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.servaddr_ipv4.sin_port = htons(usPort);

        pSockAddr = (struct sockaddr*) &servaddr.servaddr_ipv4;
        addrLen = sizeof(servaddr.servaddr_ipv4);
    }

    if (bind(fd, pSockAddr, addrLen) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    if (dwFlags & VM_SOCK_CREATE_FLAGS_NON_BLOCK)
    {
        dwError = VmDnsSockPosixSetDescriptorNonBlocking(fd);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    if (!(dwFlags & VM_SOCK_CREATE_FLAGS_UDP))
    {
        if (iListenQueueSize <= 0)
        {
            iListenQueueSize = VM_SOCK_POSIX_DEFAULT_LISTEN_QUEUE_SIZE;
        }

        if (listen(fd, iListenQueueSize) < 0)
        {
            dwError = LwErrnoToWin32Error(errno);
            BAIL_ON_POSIX_SOCK_ERROR(dwError);
        }
    }

    dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pSocket->refCount = 1;

    dwError = VmDnsAllocateMutex(&pSocket->pMutex);
    BAIL_ON_POSIX_SOCK_ERROR(dwError);

    pSocket->type = VM_SOCK_TYPE_LISTENER;

    if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP)
    {
        pSocket->protocol = VM_SOCK_PROTOCOL_UDP;
    }
    else
    {
        pSocket->protocol = VM_SOCK_PROTOCOL_TCP;
    }

    pSocket->fd = fd;

    *ppSocket = pSocket;

cleanup:

    return dwError;

error:

    if (ppSocket)
    {
        *ppSocket = NULL;
    }

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

    goto cleanup;
}
Example #19
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;
}
Example #20
0
static
DWORD
VmDnsSockPosixCreateSignalSockets(
    PVM_SOCKET* ppReaderSocket,
    PVM_SOCKET* ppWriterSocket
    )
{
    DWORD dwError = 0;
    PVM_SOCKET pReaderSocket = NULL;
    PVM_SOCKET pWriterSocket = NULL;
    PVM_SOCKET* sockets[] = { &pReaderSocket, &pWriterSocket };
    int   fdPair[] = { -1, -1 };
    DWORD iSock = 0;

    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fdPair) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);
    }

    for (; iSock < sizeof(sockets)/sizeof(sockets[0]); iSock++)
    {
        PVM_SOCKET pSocket = NULL;

        dwError = VmDnsAllocateMemory(sizeof(VM_SOCKET), (PVOID*)sockets[iSock]);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);

        pSocket = *sockets[iSock];

        pSocket->refCount = 1;

        dwError = VmDnsAllocateMutex(&pSocket->pMutex);
        BAIL_ON_POSIX_SOCK_ERROR(dwError);

        pSocket->protocol = VM_SOCK_PROTOCOL_TCP;
        pSocket->type = VM_SOCK_TYPE_SIGNAL;
        pSocket->fd = fdPair[iSock];

        fdPair[iSock] = -1;
    }

    *ppReaderSocket = pReaderSocket;
    *ppWriterSocket = pWriterSocket;

cleanup:

    return dwError;

error:

    *ppReaderSocket = NULL;
    *ppWriterSocket = NULL;

    if (pReaderSocket)
    {
        VmDnsSockPosixFreeSocket(pReaderSocket);
    }
    if (pWriterSocket)
    {
        VmDnsSockPosixFreeSocket(pWriterSocket);
    }
    for (iSock = 0; iSock < sizeof(fdPair)/sizeof(fdPair[0]); iSock++)
    {
        if (fdPair[iSock] >= 0)
        {
            close(fdPair[iSock]);
        }
    }

    goto cleanup;
}