⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctpmanager.cpp

📁 funambol windows mobile plugin source code, the source code is taken from the funambol site
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) 2003-2007 Funambol, Inc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307  USA
 */

#include <winsock2.h>
#include "Ws2tcpip.h"
#include "base/Log.h"
#include "base/util/utils.h"
#include "CTPManager.h"
#include "CTPParam.h"




// Init static pointer.
CTPManager* CTPManager::pinstance = NULL;


/**
 * Method to create the sole instance of CTPManager
 */
CTPManager* CTPManager::getInstance() {

    if (pinstance == NULL) {
        pinstance = new CTPManager;
    }
    return pinstance;
}


/**
 * Constructor: reads the CTPConfig from registry and init members.
 */
CTPManager::CTPManager() : config(APPLICATION_URI) {

    // Read config from registry
    config.readCTPConfig();
    LOG.debug("CTP config read");

    ctpSocket       = NULL;
    ctpThread       = NULL;
    receiveThread   = NULL;
    heartbeatThread = NULL;
    receivedMsg     = NULL;
}


CTPManager::~CTPManager() {
    
    stopThread(ctpThread);
    stopThread(receiveThread);
    stopThread(heartbeatThread);
    closeConnection();

    if (receivedMsg) {
        delete receivedMsg;
    }
}


/**
 * Creates the mai CTP thread, passing handle stpThread (NULL if not created)
 */
HANDLE CTPManager::startCTP(HANDLE stpThread) {

    if (ctpThread) {
        stopThread(ctpThread);
    }
    config.setLeavingState(false);

    ctpThread = CreateThread(NULL, 0, ctpWorker, (LPVOID*)stpThread, 0, NULL);
    if (!ctpThread) {
        LOG.error("Error creating CTP thread: code 0x%08x", GetLastError());
    }
    return ctpThread;
}




int CTPManager::stopCTP() {

    if (!ctpThread) {
        LOG.debug("No CTP thread available -> exiting.");
        return 1;
    }
    if (!ctpSocket) {
        LOG.debug("No socket connection -> exiting.");
        return 2;
    }

    int ret = 0;
    LOG.debug("Closing CTP connection...");


    // Terminate immediately the heartbeat thread to avoid sending 
    // any READY msg now. Keep receiveThread alive, to receive the last OK msg.
    if (stopThread(heartbeatThread)) {
        LOG.debug("heartbeatThread killed");
    }


    // Start thread to receive messages from Server if not running
    // If client authenticated, receiveThread is already running
    if (!receiveThread) {
        receiveThread = CreateThread(NULL, 0, receiveWorker, (LPVOID*)ctpSocket, 0, NULL);
        if (!receiveThread) {
            LOG.error("Error creating receive thread: code 0x%08x", GetLastError());
            return -1;
        }
        // Just to be sure the receiveWorker has reached the 'recv' state
        Sleep(1000);
    }


    // Set flag of leaving state, so receive thread will exit after the OK msg.
    config.setLeavingState(true);


    //
    // Send the BYE message
    //
    LOG.info("Sending [BYE] message...");
    if (sendByeMsg()) {
        LOG.error("Error sending the BYE message");
        goto finally;
    }


    //
    // Wait for OK msg: receive thread should exit after the last OK
    // message sent by Server.
    //
    DWORD waitResult = WaitForSingleObject(receiveThread, LEAVING_STATE_TIMEOUT * 1000);
    switch (waitResult) {

        // Thread exited normally or abandoned -> ok
        case WAIT_ABANDONED:
            LOG.debug("receiveThread abandoned");
        case WAIT_OBJECT_0: {
            DWORD exitcode = 0;
            GetExitCodeThread(receiveThread, &exitcode);
            LOG.debug("receiveThread ended with code %d", exitcode);
            ret = exitcode;
            break;
        }

        // Timeout: kill thread -> out.
        case WAIT_TIMEOUT: {
            LOG.debug("Timeout - receiveThread will now be terminated");
            TerminateThread(receiveThread, 1);
            ret = 1;
            break;
        }

        // Some error occurred (case WAIT_FAILED)
        default: {
            LOG.debug("Wait error on receiveThread");
            TerminateThread(receiveThread, 1);
            ret = 2;
            break;
        }
    }
    CloseHandle(receiveThread);
    receiveThread = NULL;


finally:

    // Close them if still running...
    if (stopThread(receiveThread)) {
        LOG.debug("receiveThread killed");
    }
    if (stopThread(ctpThread)) {
        LOG.debug("ctpThread killed");
    }

    //
    // Close socket connection
    //
    closeConnection();

    return ret;
}







int CTPManager::openConnection(){

    DWORD errorCode = 0;
    int ret = 0;

    if (ctpSocket) {
        closeConnection();
    }
    LOG.debug("--- Starting a new SOCKET connection ---");

    //
    // Initialize Winsock
    //
    WORD versionRequested = MAKEWORD(1, 1);
	WSADATA wsaData;
    ret = WSAStartup(versionRequested, &wsaData);
    if (ret != NO_ERROR) {
        errorCode = WSAGetLastError();
        LOG.error("SOCKET WSAStartup() error %d: %s", errorCode, createErrorMsg(errorCode));
        return -1;
    }

    // Check if version is correct 
    if (wsaData.wVersion != versionRequested) {
        LOG.error("WinSock version not supported: %d (%d expected)", wsaData.wVersion, versionRequested);
        return -1;
	}


    //
    // Find the server
    //
    LOG.debug("Find the server address...");
    struct addrinfo aiHints;
    struct addrinfo *aiList = NULL;
    
    // Setup the hints address info structure
    // which is passed to the getaddrinfo() function
    memset(&aiHints, 0, sizeof(aiHints));
    aiHints.ai_family   = AF_INET;				// Address family
    aiHints.ai_socktype = SOCK_STREAM;			// Socket type
    aiHints.ai_protocol = IPPROTO_TCP;		    // Protocol
    aiHints.ai_flags    = AI_CANONNAME;         // To get the canonical name

    const char* hostName = config.getUrlTo().c_str();
    char port[10];
    sprintf(port, "%d", config.getCtpPort());
    LOG.info("HOSTNAME = '%s'  PORT = '%s'", hostName, port);

    // Resolve the host name.
    ret = getaddrinfo(hostName, port, &aiHints, &aiList);
    if (ret) {
		lastErrorCode = ERR_HOST_NOT_FOUND;
        LOG.error("getaddrinfo() failed: %s", gai_strerror(ret));
        ret = -2;
        goto finally;
    }

    struct addrinfo *addr = aiList;

    // Loop on possible addresses
    while (addr != NULL) {
        //
        // Create a TCP/IP stream socket
        //
        LOG.debug("Create SOCKET connection...");
        ctpSocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (ctpSocket == INVALID_SOCKET) {
            if (addr->ai_next != NULL) {
                addr=addr->ai_next;        // take next address
                continue;
            }
            else {
                errorCode = WSAGetLastError();
                LOG.error("SOCKET socket() error %d: %s", errorCode, createErrorMsg(errorCode));
                ret = -3;
                goto finally;
            }
        }

        //
        // Connect to the server
        //
        LOG.debug("Connecting to '%s'...", hostName);
        ret = connect(ctpSocket, addr->ai_addr, addr->ai_addrlen);
        if (ret == SOCKET_ERROR) {
            if (addr->ai_next != NULL) {
                addr=addr->ai_next;        // take next address
                closesocket(ctpSocket);
                continue;
            }
            else {
                errorCode = WSAGetLastError();
                if (errorCode == WSAECONNREFUSED) {
                    LOG.error("SOCKET connect() error: Server not responding at %s:%s", hostName, port);
                }
                else {
                    LOG.error("SOCKET connect() error %d: %s", errorCode, createErrorMsg(errorCode));
                }
                ret = -4;
                goto finally;
            }
        }
        LOG.info("Succesfully connected to %s!", addr->ai_canonname);
        break;
    }

finally:
    if (aiList) {
        freeaddrinfo(aiList);
    }
    return ret;
}




int CTPManager::closeConnection(){

    int ret = 0;

⌨️ 快捷键说明

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