Пример #1
0
int loom_net_writeTCPSocket(loom_socketId_t s, void *buffer, int bytesToWrite)
{
#if LOOM_PLATFORM == LOOM_PLATFORM_WIN32
    int winsockErrorCode;
#endif

    int bytesLeft = bytesToWrite;
    for ( ; ; )
    {
        int result = send((SOCKET)s, buffer, bytesLeft, MSG_NOSIGNAL);

        if (result >= 0)
        {
            bytesLeft -= result;
            if (bytesLeft != 0)
            {
                lmLogDebug(netLogGroup, "Partial write on socket %d, expected %d but wrote %d! Retrying...", s, bytesToWrite, result);

                // Set up to try again by advancing into the buffer.
                buffer = (void *)((char *)buffer + result);
                continue;
            }

            return bytesToWrite - bytesLeft;
        }

#if LOOM_PLATFORM == LOOM_PLATFORM_WIN32
        winsockErrorCode = WSAGetLastError();
        if (winsockErrorCode != WSAEWOULDBLOCK)
        {
            break;
        }
#else
        if (errno != EAGAIN)
        {
            break;
        }
#endif

        if (loom_net_isSocketDead(s))
        {
            break;
        }

        loom_thread_sleep(5);
    }

    return -1;
}
Пример #2
0
void loom_net_enableSocketKeepalive(loom_socketId_t s)
{
    int       optVal = 1;
    socklen_t optLen = sizeof(optVal);

    if (loom_net_isSocketDead(s))
    {
        lmLogError(netLogGroup, "Tried to set keepalive on dead socket.");
        return;
    }

    //lmLog(netLogGroup, "Setting keepalive with %d %d", optVal, optLen);

    if (setsockopt((int)s, SOL_SOCKET, SO_KEEPALIVE, (char *)&optVal, optLen) < 0)
    {
        // This failure when due to EINVAL (22 on darwin) on a freshly created
        // socket is often because the sockethas been shutdown asynchronously by the OS.
        lmLogError(netLogGroup, "Could not set SO_KEEPALIVE on socket %x due to %d", s, errno);
        return;
    }
}
Пример #3
0
// Service our connection to the asset agent.
static void loom_asset_serviceServer()
{
    loom_mutex_lock(gAssetServerSocketLock);

    // Try to connect to the asset server if we aren't already, and it is set.
    if ((gAssetServerSocket == NULL) &&
        ((ASSET_STREAM_HOST != NULL) && (strlen(ASSET_STREAM_HOST) > 0)) &&
        ((platform_getMilliseconds() - gAssetServerLastConnectTryTime) > gAssetServerConnectTryInterval))
    {
        lmLog(gAssetLogGroup, "Attempting to stream assets from %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT);
        gAssetServerLastConnectTryTime = platform_getMilliseconds();
        gAssetServerSocket             = loom_net_openTCPSocket(ASSET_STREAM_HOST, ASSET_STREAM_PORT, 0);
        gAssetConnectionOpen           = false;
        loom_asset_notifyPendingCountChange();

        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    if ((gAssetServerSocket != NULL) && (gAssetConnectionOpen == false))
    {
        // We are waiting on the connection, see if it's writable... If not, return.
        if (loom_net_isSocketWritable(gAssetServerSocket) == 0)
        {
            loom_mutex_unlock(gAssetServerSocketLock);
            return;
        }

        if (loom_net_isSocketDead(gAssetServerSocket) == 1)
        {
            // Might be DOA, ie, connect failed.
            lmLog(gAssetLogGroup, "Failed to connect to asset server %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT);

            loom_net_closeTCPSocket(gAssetServerSocket);

            gAssetServerSocket = NULL;
            lmSafeDelete(NULL, gAssetProtocolHandler);
            gAssetConnectionOpen = false;
            loom_asset_notifyPendingCountChange();
            loom_mutex_unlock(gAssetServerSocketLock);
            return;
        }

        lmLog(gAssetLogGroup, "Successfully connected to asset server %s:%d!", ASSET_STREAM_HOST, ASSET_STREAM_PORT);

        // Do this now to avoid clobbering error state and seeing the socket as
        // "open" when it is really dead.
        loom_net_enableSocketKeepalive(gAssetServerSocket);
        gAssetConnectionOpen = true;
        loom_asset_notifyPendingCountChange();

        // Make sure we have a protocol handler.
        if (!gAssetProtocolHandler)
        {
            gAssetProtocolHandler = lmNew(NULL) AssetProtocolHandler(gAssetServerSocket);
            gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolFileMessageListener());
            gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolCommandListener());
        }

        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    // See if the socket is dead, and if so, clean up.
    if ((gAssetServerSocket != NULL) && (loom_net_isSocketDead(gAssetServerSocket) == 1))
    {
        lmLog(gAssetLogGroup, "Lost connection to asset server.");
        loom_net_closeTCPSocket(gAssetServerSocket);
        gAssetServerSocket = NULL;
        lmSafeDelete(NULL, gAssetProtocolHandler);
        gAssetConnectionOpen = false;
        loom_asset_notifyPendingCountChange();
        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    // Bail if we don't have a connection.
    if (!gAssetServerSocket || !gAssetConnectionOpen)
    {
        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    // Ping if we need to.
    if (platform_getMilliseconds() - gAssetServerLastPingTime > gAssetServerPingInterval)
    {
        gAssetProtocolHandler->sendPing();
        gAssetServerLastPingTime = platform_getMilliseconds();
    }

    // Service the asset server connection.
    gAssetProtocolHandler->process();

    loom_mutex_unlock(gAssetServerSocketLock);
}
Пример #4
0
void loom_net_readTCPSocket(loom_socketId_t s, void *buffer, int *bytesToRead, int peek /*= 0*/)
{
    int errorCode;

    int waiting;

    int tmp = *bytesToRead;

    int bytesLeft;

    if (loom_net_isSocketDead(s))
    {
        *bytesToRead = 0;
        return;
    }

    if (peek) {
        *bytesToRead = recv((SOCKET)s, buffer, tmp, MSG_PEEK);
        return;
    }

    bytesLeft = *bytesToRead;

    while (bytesLeft > 0)
    {
        int received = recv((SOCKET)s, buffer, bytesLeft, 0);
        if (received == -1) {
            waiting = 0;
#if LOOM_PLATFORM == LOOM_PLATFORM_WIN32
            errorCode = WSAGetLastError();
            if (errorCode == WSAEWOULDBLOCK)
            {
                waiting = 1;
            }
#else
            errorCode = errno;
            if (errorCode == EAGAIN)
            {
                waiting = 1;
            }
#endif
            if (waiting)
            {
                // TODO figure out a better way to do this?
                //lmLogDebug(netLogGroup, "Waiting for receive buffer %d / %d", *bytesToRead - bytesLeft, *bytesToRead);
                loom_thread_sleep(5);
                continue;
            }
            else
            {
                lmLogError(netLogGroup, "Read socket error (%d)", errorCode);
                *bytesToRead = -1;
                return;
            }
        }
        bytesLeft -= received;
        buffer = (char*)buffer + received;
    }

    lmAssert(bytesLeft == 0, "Internal recv error, read too much data? %d", bytesLeft);
}