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 + -
显示快捷键?