worker.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 1,085 行 · 第 1/3 页

CPP
1,085
字号

error:
    // Restore the original ctpRetry time
    ctpManager->getConfig()->setCtpRetry(defaultCtpRetry);
    ctpManager->closeConnection();

finally:
    PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);
    LOG.debug("Exiting ctpWorker thread");
    return ret;
}



/**
 * This is used as a thread for the CTP process, called once CTP
 * is connected and ready to receive notifications from the Server.
 * We listen to the CTP socket connection, calling ctpManager->receiveStatusMsg().
 * - In case of error/wrong status from the Server, we get back to receiving.
 * - If a OK message is received, we get back to receiving.
 * - If a SYNC message is received, we start the sync process.
 *
 * @param lpv  unused
 * @note  exit only in case of errors or if we're in leaving state.
 * @return 0 if no errors
 */
DWORD WINAPI receiveWorker(LPVOID lpv) {

    LOG.debug("Starting receiveWorker thread");
    int ret = 0;
    CTPManager* ctpManager = CTPManager::getInstance();

    PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);


    // Keep the socket open, always in 'receive' state.
    // Exit only in case of errors or if we're leaving CTP.
    while (ctpManager->isLeaving() == false) {

        // Receive msg from Server
        CTPMessage* statusMsg = ctpManager->receiveStatusMsg();
        if (!statusMsg) {
            // Error on receiving -> exit thread
            ret = -1;
            goto finally;
        }

        char status = statusMsg->getGenericCommand();
        SyncNotification* sn = NULL;
        switch (status) {

            case ST_OK:
                // 'OK' to our 'READY' command -> back to recv
                LOG.info("[OK] received -> back to receive state");
                break;

            case ST_SYNC:
                //
                // Start the sync!
                // ---------------
                LOG.info("[SYNC] notification received! Starting the sync");
                sn = statusMsg->getSyncNotification();
                startSyncFromSAN(sn);

                // Back to recv
                LOG.debug("Back to receive state");
                break;

            case ST_ERROR:
                LOG.debug("[ERROR] message received");
                //printErrorStatus(statusMsg);
            default:
                // Error from server -> exit thread (will try restoring the socket from scratch)
                LOG.debug("Bad status received (code 0x%02x), exiting thread", status);
                ret = -2;
                goto finally;
        }
    }

finally:
    PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);
    LOG.debug("Exiting receiveWorker thread");
    return ret;
}



/**
 * Thread used to send 'READY' messages as a heartbeat, every 'ctpReady' seconds.
 * It ends only if CTP is in 'leaving state' (Client stops CTP).
 * @param lpv  unused
 * @return 0 if no errors
 */
DWORD WINAPI heartbeatWorker(LPVOID lpv) {
    LOG.debug("Starting heartbeatWorker thread");
    int ret = 0;

    PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

    // Load the sleep interval (ctpReady)
    CTPManager* ctpManager = CTPManager::getInstance();
    int sleepInterval = ctpManager->getConfig()->getCtpReady();

    // Send 'ready' message to Server and sleep ctpReady seconds
    while (ctpManager->isLeaving() == false) {
        LOG.info("Sending [READY] message...");
        if (ctpManager->sendReadyMsg()) {
            LOG.debug("Error sending READY msg");
            ret = 1;
            break;
        }
        LOG.debug("Next ready msg will be sent in %d seconds...", sleepInterval);
        Sleep(sleepInterval * 1000);
    }

    PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);
    LOG.debug("Exiting heartbeatWorker thread");
    return ret;
}




/**
 * Thread used to check if a response arrived in ctpCmdTimeout seconds.
 * If not, the CTP connection will be pulled down so that ctpThread
 * will restore the whole CTP connection.
 * This thread is started every time a message is sent.
 * @param lpv  unused
 */
DWORD WINAPI cmdTimeoutWorker(LPVOID lpv) {
    LOG.debug("Starting cmdTimeoutWorker thread");

    PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

    // Load the timeout (ctpCmdTimeout)
    CTPManager* ctpManager = CTPManager::getInstance();
    DWORD timeout = ctpManager->getConfig()->getCtpCmdTimeout();
    if (!timeout) {
        timeout = 180;      // 3 minutes max
    }

    Sleep(timeout * 1000);

    if ( (ctpManager->isLeaving() == false) &&
         (ctpManager->getCtpState() == CTP_STATE_WAITING_RESPONSE) ) {
        // Response not received -> close ctp connection so that
        // the receiveThread will exit with error, so ctpThread will restore ctp.
        LOG.info("No response received from Server after %d seconds: closing CTP", timeout);
        ctpManager->closeConnection();
    }

    PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);
    LOG.debug("Exiting cmdTimeoutWorker thread");
    return 0;
}


/**
 * Thread used to check the connection after an interval.
 * used to understand if the connection is up for the stp method
 * Every (10 x interval) we check if CP is running: if not, restart it.
 * @interval - the value in minutes to wait before internet check 
 */
DWORD WINAPI checkInternetConnectionWorker(LPVOID lpv) {
    LOG.debug("Starting checkInternetConnection thread");
    int ret = 0;
    int interval = (int)lpv; 

    PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);
    
    int j = 0;
    while (1) {
            EstablishConnection();
        Sleep(interval * 1000);

        // Once every (10 x interval) = 40 mins we check CP: if not running, restart it.
        j++;
        if (j == 10) {
            startClientPushWorker(NULL);  // Will do nothing if already running.
            j = 0;
        }
    }

    PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);
    LOG.debug("Exiting checkInternetConnection thread");
    return ret;
}

/**
* start the thread of to check the internet connection every CHECK_INTERNET_CONNECTION_TIME.
* It is called in the init of the dll
*/
HANDLE starCheckInternetConnectionWorker() {
    
    try {
        if (IConnectionThread) {
            stopCheckInternetConnectionWorker(1);
        }

        IConnectionThread = CreateThread(NULL, 0, checkInternetConnectionWorker, 
                                        (LPVOID*)CHECK_INTERNET_CONNECTION_TIME, 0, NULL);
        if (!IConnectionThread) {
            LOG.error("Error creating IConnectionThread thread: code 0x%08x", GetLastError());        
        } 
    }
    catch (...) {
        DWORD errorCode = GetLastError();
        LOG.error("Unexpected exception in checkInternetConnectionWorker: code %d", errorCode);
    }
    return IConnectionThread;
    
}

/**
* end the thread of the internet connection. It is called in the deinit of the dll
*/
bool stopCheckInternetConnectionWorker(int exitCode) {
    
    if (IConnectionThread) {
        TerminateThread(IConnectionThread, exitCode);
        CloseHandle(IConnectionThread);
        IConnectionThread = NULL;
        return true;
    }
    return false;
}


/// Tries to estabilish internet connection.
DWORD WINAPI establishConnectionWorker(LPVOID lpv) {
    Sleep(2000);
    EstablishConnection();
    return 0;
}



// *************************** CLIENT PUSH handling ******************************

void startClientPush() {

    HANDLE h = CreateThread(NULL, 0, startClientPushWorker, NULL, 0, NULL);
    if (!h) {
        LOG.error("Error creating startClientPushWorker thread: code 0x%08x", GetLastError());
        return;
    }
    CloseHandle(h);
}

// Starts the CP process
DWORD WINAPI startClientPushWorker(LPVOID lpv) {

    // Exit if we don't want to use CP
    if (!USE_CP) { return 0; }

    // Check if process is not running.
    DWORD pid = isClientPushRunning();

    if (!pid) {

        // Create the CP process.
        LOG.info("Starting the process 'ClientPush.exe'.");
        pid = startProgram(TEXT("ClientPush.exe"), TEXT(""));

        // Save the pid into registry.
        LOG.debug("Saving the CP PID to registry: %d", pid);
        DMTree* dmt = DMTreeFactory::getDMTree(APPLICATION_URI);
        ManagementNode* node = dmt->readManagementNode(APPLICATION_URI);
        if (!node) {
            LOG.error("Cannot store CP PID, error reading management node '%s'", APPLICATION_URI);
            return 1;
        }
        StringBuffer value;
        value.sprintf("%d", pid);
        node->setPropertyValue(CP_PID, value.c_str());
    }
    else {
        LOG.debug("CP already running: current PID = %d", pid);
    }
    return 0;
}


// Stops the CP process
void stopClientPush() {

    // Check if process is running.
    DWORD pid = isClientPushRunning();
    if (pid) {

        // Send WM_CLOSE message to the CP window.
        HWND cpWindow = FindWindow(TEXT("ClientPushWindow"), NULL);
        if (cpWindow) {
            LOG.info("Closing the process 'ClientPush.exe'.");
            SendMessage(cpWindow, WM_CLOSE, NULL, NULL);
        }
        else {
            LOG.error("Cannot find the CP window.");
        }

        // Clear the pid in registry.
        LOG.debug("Clear the CP PID to registry");
        DMTree* dmt = DMTreeFactory::getDMTree(APPLICATION_URI);
        ManagementNode* node = dmt->readManagementNode(APPLICATION_URI);
        if (!node) {
            LOG.error("Cannot clear CP PID, error reading management node '%s'", APPLICATION_URI);
            return;
        }
        node->setPropertyValue(CP_PID, "0");
    }
}



// Returns the PID if CP is running, or 0 if not running.
DWORD isClientPushRunning() {

    // Exit if we don't want to use CP
    if (!USE_CP) { return 0; }

    DWORD pid = 0;

    // Read PID from registry
    DMTree* dmt = DMTreeFactory::getDMTree(APPLICATION_URI);
    ManagementNode* node = dmt->readManagementNode(APPLICATION_URI);
    if (!node) {
        LOG.error("Cannot read CP PID, error reading management node '%s'", APPLICATION_URI);
        return 0;
    }

    char* value = node->readPropertyValue(CP_PID);
    if (value && strlen(value)>0) {
        pid = atol(value);
        LOG.debug("CP PID from registry is %d", pid);

        if (pid != 0) {
            // Check if CP process is running
            DWORD code = 0;
            HANDLE h = OpenProcess(0, FALSE, pid);
            if (h) {
                GetExitCodeProcess(h, &code);
                if (code != STILL_ACTIVE) {
                    pid = 0;
                }
                CloseHandle(h);
            }
            else {
                LOG.error("Error opening process.");
                pid = 0;
            }
        }
    }
    else {
        LOG.error("Cannot read CP PID, error '%s' registry key", CP_PID);
        pid = 0;
    }

    if (value) { delete [] value; }
    return pid;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?