worker.cpp

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

CPP
1,085
字号
            case WAIT_OBJECT_0: {
                GetExitCodeProcess(procinfo.hProcess, &exitcode);
                responseCode = exitcode;
                break;
            }
            default:
                responseCode = exitcode;
    }
    //int responseCode = notifyAddressChange(TEXT(APPLICATION_URI));
    //int responseCode = AN_AddressAccepted;

    if(responseCode == AN_AddressAccepted ){
        setServerNotified(true);
    }
    else {
        setServerNotified(false);
    }

    LOG.debug("Exiting stpWorker thread: response = %d", responseCode);
    return responseCode;
}



// -------------------- CTP --------------------------
/**
 * This is the main CTP thread. Manages the CTP connection using CTPManager:
 * 1. waits until the stpThread is finished, if successfully we exit this thread
 *    (STP is working), otherwise continue with CTP (STP is not working)
 * 2. Opens the CTP socket connection
 * 3. Authenticate the client
 * 4. Starts threads to receive messages and to send 'ready' msg.
 * 
 * @param lpv  the HANDLE of the stpThread running (NULL if not started)
 * @return a value >= 0 if no errors:
 *         0 if CTP closed correctly (Client closed CTP)
 *         1 if STP is working correctly, CTP not started
 *         2 if CTP client not authenticated (at the 2nd AUTH msg)
 *         3 if CTP client unauthorized
 *         4 if CTP client authentication forbidden
 *         5 if STP not working but CTP not started either
 *         6 if CTP already active in another instance
 *         <0 if errors
 *
 * @note This thread exits only in case of:
 *   - STPThread ended succesfully (STP is working, CTP not started)
 *   - CTP client not authenticated
 *   - CTP in 'leaving state' (Client is closing CTP)
 *   - CTP started from another instance (code 6)
 * In case of socket/Server errors, the whole CTP connection is pulled down
 * and restored again in a while (after 'ctpRetry' seconds).
 */
DWORD WINAPI ctpWorker(LPVOID lpv) {

    LOG.debug("Starting ctpWorker thread");
    int ret = 0;
    HANDLE stpThread = (HANDLE)lpv;

    // Get the unique instance of CTPManager.
    CTPManager* ctpManager = CTPManager::getInstance();

    PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

    //
    // Wait for STPThread to finish.
    // - if handle is NULL, no STP has been done  -> go with CTP.
    // - if STPThread returned error              -> go with CTP.
    // - if STPThread returned ok                 -> exit now (STP is running).
    //
    int timeout = ctpManager->getConfig()->getNotifyTimeout();
    if (stpThread) {
        LOG.info("Waiting for STP notification sync to finish (timeout = %d sec)...", timeout);
        DWORD waitResult = WaitForSingleObject(stpThread, timeout*1000);
        switch (waitResult) {

            // Thread exited, get exit code.
            case WAIT_ABANDONED:
                LOG.info("STPThread abandoned");
            
            case WAIT_OBJECT_0: {
                DWORD exitcode = 0;
                GetExitCodeThread(stpThread, &exitcode);
                LOG.debug("STPThread ended with code %d", exitcode);

                if (exitcode == 0) {
                    LOG.info("STP is running correctly, close CTP if active");
                    CloseHandle(stpThread);
                    ctpManager->stopCTP();
                    return 1;
                }
                else if (exitcode == 420 || exitcode == 401 || 
                         exitcode == 402 || exitcode == 403) {
                    // Codes 401/402/403 mean that auth failed, so we don't start CTP
                    // Code '420' returned by Server means that the Server does not support CTP
                    // (CTP is supported since Funambol Server 6.5 and code returned is '421')
                    LOG.info("STP failed, CTP won't start because code returned is %d", exitcode);
                    CloseHandle(stpThread);
                    ctpManager->stopCTP();
                    return 5;
                }
                else {
                    // STP failed, go with CTP
                    LOG.info("STP failed (code %d), go with CTP", exitcode);
                    break;
                }
            }

            // Thread is still running after timeout -> kill it and continue.
            case WAIT_TIMEOUT: {
                LOG.info("Timeout - STPThread will now be terminated");
                TerminateThread(stpThread, 1);
                break;
            }

            // Some error occurred (case WAIT_FAILED)
            default: {
                LOG.info("Wait error on STPThread");
                break;
            }
        }
    CloseHandle(stpThread);
    }


    // Safe check: we could have retrieved the ctpManager instance 2 minutes ago...
    if (!ctpManager) {
        LOG.debug("error: ctpManager not instantiated, exiting.");
        ret = 5;
        goto finally;
    }

    // Refresh configuration from registry, save the ctpRetry original value in a buffer
    ctpManager->getConfig()->readCTPConfig();
    int defaultCtpRetry = ctpManager->getConfig()->getCtpRetry();


    // Start the CTP connection process.
    // *********************************
    // Infinite cycle: always restore the connection if it's lost 
    // or in case of errors. Exit only if leavingState flag is up.
    //
    bool restore = false;
    bool jump    = false;
    while (ctpManager->isLeaving() == false) {

        if (restore) {
            // Restoring from a broken connection: close socket and wait some seconds.
            LOG.debug("Restoring CTP connection...");
            ctpManager->closeConnection();

            int sleepTime = ctpManager->getConfig()->getCtpRetry();
            sleepTime = min(sleepTime, ctpManager->getConfig()->getMaxCtpRetry());
            LOG.info("CTP will be restored in %d seconds...", sleepTime);
            Sleep(sleepTime * 1000);

            // CTP could have been restarted during the sleep time!
            // So exit if the ctp is active.
            if (ctpManager->getCtpState() > CTP_STATE_DISCONNECTED) {
                LOG.debug("CTP already active -> don't restore ctp");
                ret = 6;
                goto finally;
            }

            // Save the new value to config
            sleepTime *= CTP_RETRY_INCREASE_FACTOR;     // Double the retry time
            ctpManager->getConfig()->setCtpRetry(sleepTime);
            restore = false;
        }
        if (jump) {
            // Restoring from a JUMP status: close socket and reconnect immediately.
            LOG.debug("Restoring CTP connection from a JUMP...");
            ctpManager->closeConnection();
            jump = false;
        }


        while (checkStartSync()) {
            // Wait for sync to finish: CTP AUTH phase uses the same clientNonce
            // used by sync authentication, so avoid interferences.
            LOG.debug("Waiting for sync to finish...");
            Sleep(5000);
        }

        //
        // Open socket connection
        // ----------------------
        LOG.debug("Open CTP connection...");
        if (ctpManager->openConnection()) {
            restore = true;
            continue;
        }

        //
        // Authentication
        // --------------
        LOG.debug("Sending [AUTH] message...");
        if (ctpManager->sendAuthMsg()) {
            restore = true;
            continue;
        }
        
        // Receiving AUTH status message
        CTPMessage* authStatusMsg = ctpManager->receiveStatusMsg();
        if (!authStatusMsg) {
            LOG.error("Error receiving AUTH status msg.");
            restore = true;
            continue;
        }
        char authStatus = authStatusMsg->getGenericCommand();
        list<CTPParam>::iterator param;
        char* buf = NULL;
        switch (authStatus) {

            case ST_NOT_AUTHENTICATED:
                //
                // Retry with new nonce received
                //
                LOG.info("Client not authenticated: retry with new nonce");
                if (saveNonceParam(authStatusMsg) == false) {
                    // NONCE not found -> restore connection
                    LOG.error("Error receiving NON_AUTHENTICATED Status message: NONCE param is missing");
                    restore = true;
                    continue;
                }

                // Send 2nd auth msg
                LOG.info("Sending CTP authentication message...");
                if (ctpManager->sendAuthMsg()) {
                    restore = true;
                    continue;
                }

                // Check 2nd status received, only OK allowed
                authStatusMsg = ctpManager->receiveStatusMsg();
                authStatus = authStatusMsg->getGenericCommand();
                if (authStatus == ST_OK) {
                    // *** Authentication OK! *** 
                    // Save nonce if any (go to case ST_OK)
                }
                else if (authStatus == ST_NOT_AUTHENTICATED) {
                    LOG.info("CTP error: Client not authenticated. Please check your credentials.");
                    showInvalidCredentialsMsgBox(INVALID_CREDENTIALS, 10);      // code 401
                    ret = 2;
                    goto error;
                }
                else if (authStatus == ST_UNAUTHORIZED) {
                    LOG.info("CTP error: Client unauthorized by the Server. Please check your credentials.");
                    showInvalidCredentialsMsgBox(PAYMENT_REQUIRED, 10);         // code 402
                    ret = 2;
                    goto error;
                }
                else {
                    LOG.info("CTP error: received status '0x%02x'.", authStatus);
                    ret = 2;
                    goto error;
                }
                // no 'break': need to enter into case ST_OK...


            case ST_OK:
                // *** Authentication OK! *** 
                LOG.info("Client authenticated successfully!");
                ctpManager->setCtpState(CTP_STATE_READY);
                ctpManager->getConfig()->setCtpRetry(defaultCtpRetry);     // Restore the original ctpRetry time
                // Save nonce if any
                if (saveNonceParam(authStatusMsg) == false) {
                    LOG.info("No new nonce received.");
                }
                break;


            // --- note: JUMP not implemented Server side ----
            case ST_JUMP:
                //
                // Jump to desired server 'to' and save the 'from' value
                //
                LOG.info("Server requested a JUMP");
                if (authStatusMsg->params.size() < 1) {
                    // Expected FROM and TO params -> restore connection
                    LOG.error("Error receiving JUMP Status message: some parameter is missing");
                    restore = true;
                    continue;
                }

                // Read FROM and TO parameters and update CTPConfig
                param = authStatusMsg->params.begin();
                while (param != authStatusMsg->params.end()) {
                    int valueLen = (*param).getValueLength();
                    void* value  = (*param).getValue();
                    if ((*param).getParamCode() == P_FROM) {
                        char* from = stringdup((char*)value, valueLen);
                        ctpManager->getConfig()->setUrlFrom(from);
                        delete [] from;
                    }
                    else if ((*param).getParamCode() == P_TO) {
                        char* url = stringdup((char*)value, valueLen);
                        string to = ctpManager->getConfig()->getHostName(url);
                        int port  = ctpManager->getConfig()->getHostPort(url);
                        ctpManager->getConfig()->setUrlTo(to);
                        ctpManager->getConfig()->setCtpPort(port);
                        delete [] url;
                    }
                    else {
                        // Unexpected Status param -> restore connection
                        LOG.error("Error receiving JUMP Status message: unexpected param '0x%02x'", (*param).getParamCode());
                        restore = true;
                        continue;
                    }
                    param++;
                }

                // Now restore the socket connection to the new Server address...
                LOG.debug("JUMP status received: FROM %s TO %s:%d", ctpManager->getConfig()->getUrlFrom().c_str(), 
                                                                    ctpManager->getConfig()->getUrlTo().c_str(), 
                                                                    ctpManager->getConfig()->getCtpPort() );
                jump = true;
                continue;


            case ST_UNAUTHORIZED:
                // Not authorized -> save nonce if any, exit thread
                LOG.info("Unauthorized by the Server, please check your credentials.");
                showInvalidCredentialsMsgBox(PAYMENT_REQUIRED, 10);         // code 402
                if (saveNonceParam(authStatusMsg) == false) {
                    LOG.debug("No new nonce received.");
                }
                ret = 3;
                goto error;


            case ST_FORBIDDEN:
                // Authentication forbidden -> exit thread
                LOG.info("Authentication forbidden by the Server, please check your credentials.");
                showInvalidCredentialsMsgBox(FORBIDDEN, 10);                // code 403
                ret = 4;
                goto error;

            case ST_ERROR:
                // Error -> restore connection
                LOG.info("Received ERROR status from Server: restore ctp connection");
                //printErrorStatus(authStatusMsg);
                restore = true;
                continue;

            default:
                // Unexpected status -> restore connection
                LOG.error("Unexpected status received '0x%02x' -> restore ctp connection", authStatus);
                restore = true;
                continue;
        }

        //
        // Creates the thread that will be blocked waiting for server msg
        // and waits until it ends (errors or ctpConnTimeout).
        //
        ctpManager->receive();

        // If here, connection was broken or ctpConnTimeout -> restore connection
        restore = true;
    }
    goto finally;

⌨️ 快捷键说明

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