notlstnr.cpp
来自「funambol window mobile客户端源代码」· C++ 代码 · 共 815 行 · 第 1/2 页
CPP
815 行
///////////////////////////////////////////////////////////////////
// Notification Listener: connection handler
///////////////////////////////////////////////////////////////////
/**
* Open the socket connection and waits for the server messages.
*/
static DWORD acceptConnection(SOCKET sock)
{
if (g_dwServiceState != SERVICE_STATE_ON) {
// Do not accept connections unless the service is on
// ALWAYS close the socket, even if you return
// FALSE. Services.exe leaves it to the
// service to close the socket in all cases.
LOG.error("S4ND: ERROR: Service Conn fails. Service State != ON. State = <%d>", g_dwServiceState);
send(sock, RESP_BUSY, strlen(RESP_BUSY),0);
closesocket(sock);
return ERROR_SERVICE_NOT_ACTIVE;
}
int ret = ERROR_EXCEPTION_IN_SERVICE;
__try {
LOG.debug("Starting worker...");
ret = startWorker(sock);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
LOG.info("Exception in Worker thread.");
}
if( ret != ERROR_SUCCESS ) {
if (ret == ERROR_BUSY ){
LOG.debug("Worker busy...");
send(sock, RESP_BUSY, strlen(RESP_BUSY),0);
}
else {
LOG.error("Worker error...");
send(sock, RESP_GENERIC, strlen(RESP_BUSY),0);
}
closesocket(sock);
}
// Worker thread will close the socket.
return ret;
}
///////////////////////////////////////////////////////////////////
// Address change handler
///////////////////////////////////////////////////////////////////
// FIXME: use the DM
/*
* Test a configuration property to understand if the client has already
* notified the server.
*/
static bool isServerNotified()
{
wchar_t buf[10];
memset(buf, 0, 10*sizeof(wchar_t));
getClientConfigurationInternal (TEXT(""), PROPERTY_SPDM_SERVER_NOTIFIED,
buf, FALSE);
return ( wcscmp(buf, TEXT("1")) == 0);
}
// FIXME: use the DM
/*
* Set a configuration property to mark the client has
* notified the server.
*/
void setServerNotified(bool val)
{
setClientConfiguration(
TEXT(""),
PROPERTY_SPDM_SERVER_NOTIFIED,
( (val) ? TEXT("1") : TEXT("0") ),
NULL);
}
/**
* Starts the STP or CTP process, based on the registry property 'push'.
* STP: Start a particular sync saying to the server the new client IP address.
* It sets the server notified parameter if succesfully finished.
* CTP: starts the CTP main thread (ctpWorker) which will connect only
* if the stpWorker ended unsuccessfully.
*/
DWORD addressChangeHandler(void)
{
LOG.debug("addressChangeHandler begin");
static wchar_t oldIP[40] = TEXT("127.0.0.1");
wchar_t newIP[40];
DWORD ret = ERROR_SUCCESS;
bool useSTP = false;
bool useCTP = false;
//MessageBox (NULL, TEXT("addressChangeHandler"), TEXT("Test"), MB_SETFOREGROUND | MB_OK);
// Reset LOG if > 100k
if (LOG.getLogSize() > NOTLSTNR_MAX_SIZE) {
LOG.reset(NOTLSTNR_LOG_TITLE);
}
// Read getPush -> switch if using STP / CTP
int pushType = getPushTypeFromRegistry();
if (pushType & 1) {
useSTP = true;
}
if (pushType & 2) {
useCTP = true;
}
if (!useSTP && !useCTP) {
// Nothing to do
setServerNotified(false);
return 0;
}
LOG.debug("useSTP = %d, useCTP = %d", useSTP, useCTP);
try {
if (checkNetwork()) {
LOG.debug("Connected to network, getting IP address...");
getIPAddress(newIP);
LOG.info("Current IP: %ls", newIP);
if (wcscmp(newIP, TEXT("192.168.55.101"))==0 ||
wcsstr(newIP, TEXT("169.254.2.")) ) {
LOG.info("Device is using ActiveSync -> use only CTP");
wcscpy(oldIP, newIP);
setServerNotified(false);
useSTP = false; // Because it would fail.
}
// The server is already notified and the IP is
// the same of the current, do not send a new notification.
if ( isServerNotified() && (wcscmp(oldIP, newIP)==0) ) {
LOG.info("Server already notified.");
return ret;
}
// Save the IP
wcscpy(oldIP, newIP);
HANDLE stpThread = NULL;
CTPManager* ctpManager = CTPManager::getInstance();
// ----------- STP -----------
if (useSTP) {
// create STP thread, get handle of stpThread
stpThread = CreateThread(NULL, 0, stpWorker, NULL, 0, NULL);
if (!stpThread) {
LOG.error("Error creating STP thread: code 0x%08x", GetLastError());
}
}
// ----------- CTP -----------
if (useCTP) {
// create CTP thread, passing handle stpThread (NULL if not created)
ctpManager->startCTP(stpThread);
}
}
else {
LOG.debug("Not connected to network: close CTP if active and try to restart connection.");
CTPManager* ctpManager = CTPManager::getInstance();
ctpManager->setLeaving(true);
ctpManager->closeConnection();
setServerNotified(false);
CreateThread(NULL, 0, establishConnectionWorker, NULL, 0, NULL);
}
}
catch (...) {
DWORD errorCode = GetLastError();
LOG.error("Unexpected exception in addressChangeHandler: code %d", errorCode);
}
LOG.debug("Exiting addressChangeHandler");
return ret;
}
/**
* Reads the 'push' registry value from CTPConfig, possible values:
* 0 -> None
* 1 -> STP
* 2 -> CTP
* 3 -> STP with fallback to CTP
*/
int getPushTypeFromRegistry() {
CTPConfig config(APPLICATION_URI);
config.readCTPConfig();
return config.getPush();
}
/**
* Starts the program "startsync.exe" with params:
* "manual <sourcename1, sourcename2,...>" where sourcenames are
* retrieved from the SyncNotification passed.
* @note the process is started and then the control is returned
* immediately to the caller (no wait on the process started)
* @param sn pointer to the SyncNotification object to read
* @return the PID of process started, a value < 0 in case of errors
*/
int startSyncFromSAN(SyncNotification* sn) {
if (!sn) {
LOG.error("CTP notification error: SyncNotification is NULL");
return -1;
}
// Get number of sources to sync
int n = sn->getNumSyncs();
if (!n) {
LOG.error("CTP notification error: no sources to sync from server");
return -2;
}
//
// Call "startsync.exe" with command-line parameters (sequence of source names)
//
wstring app = L"startsync.exe";
wstring cmdLine = L"tcpip";
int count = 0;
for (int i=0; i<n; i++) {
SyncAlert* sync = sn->getSyncAlert(i);
if(!sync) {
LOG.error("CTP notification error: no SyncAlert in SyncNotification");
return -3;
}
WCHAR* srcname = getSSourceName(APPLICATION_URI, sync->getServerURI());
if (srcname) {
if (count == 0) { cmdLine += L" "; }
else { cmdLine += L","; }
cmdLine += srcname;
delete [] srcname;
count++;
}
else {
LOG.error("CTP notification error: no source found from server notification request: %s", sync->getServerURI());
continue;
}
}
if (count == 0) {
// 0 sources to sync -> out
LOG.info("No sources to sync");
return NULL;
}
//
// Start the sync process: "startsync.exe tcpip <sourcename1, sourcename2,...>"
//
int pid = 0;
if (askConfirm()) {
LOG.info("Starting sync: '%ls %ls'", app.c_str(), cmdLine.c_str());
pid = startProgram(app.c_str(), cmdLine.c_str());
}
return pid;
}
/**
* Utility to extract the nonce parameter from CTPMessage passed and
* save it to 'CTPConfig::ctpNonce'.
* The configuration (CTPConfig) is also saved to registry.
* The nonce is expected to be the first parameter of the message.
* @param authStatusMsg the CTPMessage to analyze
* @return true if the nonce has been saved,
* false if nonce not found
*/
bool saveNonceParam(CTPMessage* authStatusMsg) {
if (authStatusMsg->params.size() == 0) {
return false;
}
// Get nonce param
int nonceLen = 0;
void* nonce = NULL;
list<CTPParam>::iterator param = authStatusMsg->params.begin();
if ((*param).getParamCode() == P_NONCE) {
nonceLen = (*param).getValueLength();
nonce = (*param).getValue();
}
else {
return false;
}
if (!nonce || nonceLen==0) {
return false;
}
// Nonce is encoded in b64.
char* b64Nonce = new char[((nonceLen/3+1)<<2) + 32];
int len = b64_encode(b64Nonce, nonce, nonceLen);
b64Nonce[len] = 0;
//LOG.debug("New nonce received:");
//hexDump((char*)nonce, nonceLen);
LOG.debug("New nonce received: '%s'", b64Nonce);
// Save new nonce to config, and save config to registry!
CTPManager* ctpManager = CTPManager::getInstance();
ctpManager->getConfig()->setCtpNonce(b64Nonce);
ctpManager->getConfig()->saveCTPConfig();
delete [] b64Nonce;
return true;
}
/**
* Utility to print the error message which is the first (and only)
* param of the passed statusMsg.
* @param statusMsg the CTPMessage to analyze
* @return 0 if the error param has been found
* 1 if the error param not found
*/
int printErrorStatus(CTPMessage* statusMsg) {
if (statusMsg->params.size() == 0) {
return 1;
}
// Get error param
int errorLen = 0;
void* error = NULL;
list<CTPParam>::iterator param = statusMsg->params.begin();
errorLen = (*param).getValueLength();
error = (*param).getValue();
if (!error || errorLen<=0) {
return 1;
}
char* buf = NULL;
strncpy(buf, (char*)error, errorLen);
LOG.info("Error message received: '%s'", buf);
return 0;
}
/**
* Utility to extract the message length from a CTP package.
* The message length is stored in the first 2 bytes of the CTP package.
* @param package the input package
* @param packageLen the length of the passed package
* @return the message length
*/
int extractMsgLength(const char* package, int packageLen) {
if (packageLen < 2) {
LOG.error("Unable to read the package length: not enough bytes received (%d)", packageLen);
return 0;
}
int messageLen = (int)((unsigned char)package[0]);
int messageLen1 = (int)((unsigned char)package[1]);
messageLen <<= 8;
messageLen = messageLen | messageLen1;
//LOG.debug("messageLen = %d", messageLen);
return messageLen;
}
/**
* Print the message written in exadecimal code.
*/
void hexDump(char *buf, int len){
if (LOG.getLevel() < LOG_LEVEL_DEBUG) {
return;
}
//int i=0, byte;
//for(i=0;i<len;i++){
// if(i%8==0){
// LOG.debug("%08x: ", i);
// }
// byte = buf[i];
// LOG.debug("%02x%s", byte & 0xFF, (i%2)? " ":"");
//}
char* tmp = new char[len*8 + 3];
tmp[0] = '[';
int pos = 1;
for (int i=0; i<len; i++) {
sprintf(&tmp[pos], "%02x ", buf[i]);
pos += 3;
}
tmp[pos-1] = ']';
tmp[pos] = 0;
LOG.debug("%s", tmp);
delete [] tmp;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?