void Connector::run (void)
{
    int rc;
    started();
    _pPDS->_bConnectedToServer = false;
    Socket *pSocketToServer = new TCPSocket();
    if (0 != (rc = ((TCPSocket*)pSocketToServer)->connect (_pPDS->_proxyServerAddr.getIPAsString(), _pPDS->_proxyServerAddr.getPort()))) {
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_Warning,
                        "failed to connect to proxy server at %s:%d\n",
                        _pPDS->_proxyServerAddr.getIPAsString(), (int) _pPDS->_proxyServerAddr.getPort());
        delete pSocketToServer;
        setTerminatingResultCode (-1);
        terminating();
        return;
    }
    checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_Info,
                    "connected to proxy server; LP:%d-RP:%d\n", pSocketToServer->getLocalPort(), pSocketToServer->getRemotePort());
    pSocketToServer->bufferingMode (0);
    CommHelper2 *pchToServer = new CommHelper2();
    if (0 != (rc = pchToServer->init (pSocketToServer))) {
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_MildError,
                        "failed to initialize CommHelper; rc = %d\n", rc);
        delete pchToServer;
        delete pSocketToServer;
        setTerminatingResultCode (-2);
        terminating();
        return;
    }
    InetAddr localAddr;
    uint16 ui16AssignedPort;
    uint16 ui16MTU;
    try {
        uint8 aui8Buf [ProxyDatagramSocket::MAXIMUM_PROXY_PACKET_SIZE];

        // Receive the Welcome message
        uint32 ui32PacketSize = pchToServer->receiveBlock (aui8Buf, ProxyDatagramSocket::MAXIMUM_PROXY_PACKET_SIZE);
        if ((ui32PacketSize < 1) || (aui8Buf[0] != 'w')) {
            throw ProtocolException ("expecting but did not receive a welcome message from server");
        }
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_MediumDetailDebug,
                        "connected to proxy server at %s:%d\n",
                        _pPDS->_proxyServerAddr.getIPAsString(), (int) _pPDS->_proxyServerAddr.getPort());
        if (ui32PacketSize > 2) {
            aui8Buf[ui32PacketSize] = '\0';      // Just for safety
            checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_MediumDetailDebug,
                            "proxy server identification string is <%s>\n",
                            (char*) aui8Buf+2);
        }

        // Receive the Address message
        ui32PacketSize = pchToServer->receiveBlock (aui8Buf, ProxyDatagramSocket::MAXIMUM_PROXY_PACKET_SIZE);
        if ((ui32PacketSize < 6) || (aui8Buf[0] != 'a')) {
            throw ProtocolException ("expecting but did not receive an address message from server");
        }
        if (aui8Buf[1] != 0) {
            if (aui8Buf[1] == 4) {
                // Received a 4-byte address - store it as the local address
                localAddr = InetAddr (*((uint32*)(aui8Buf+2)));
                checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_LowDetailDebug,
                                "set local address to %s (%x)\n",
                                localAddr.getIPAsString(), localAddr.getIPAddress());
            }
            else {
                checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_Warning,
                                "received a local address of length %d - ignoring since it is not a 4 byte address\n",
                                (int) aui8Buf[1]);
            }
        }

        // Receive the MTU message
        ui32PacketSize = pchToServer->receiveBlock (aui8Buf, ProxyDatagramSocket::MAXIMUM_PROXY_PACKET_SIZE);
        if ((ui32PacketSize < 3) || (aui8Buf[0] != 'm')) {
            throw ProtocolException ("expecting but did not receive an MTU message from server");
        }
        ui16MTU = EndianHelper::ntohs (*((uint16*)(aui8Buf+1)));
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_LowDetailDebug,
                        "set MTU to %d\n", (int) ui16MTU);

        // Send the bind message
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_LowDetailDebug,
                        "sending a bind message; local port = %d\n", _pPDS->_ui16LocalPort);
        aui8Buf[0] = 'B';
        (*((uint16*)(aui8Buf+1))) = EndianHelper::htons (_pPDS->_ui16LocalPort);
        pchToServer->sendBlock (aui8Buf, 3);

        // Receive the reply
        ui32PacketSize = pchToServer->receiveBlock (aui8Buf, ProxyDatagramSocket::MAXIMUM_PROXY_PACKET_SIZE);
        if ((ui32PacketSize < 3) || (aui8Buf[0] != 'b')) {
            throw ProtocolException ("expecting but did not receive a bind reply message from server");
        }
        ui16AssignedPort = EndianHelper::ntohs (*((uint16*)(aui8Buf+1)));

        if (ui16AssignedPort == 0) {
            throw ProtocolException ("server failed to assign a port");
        }

        _pPDS->_ui16LocalPort = ui16AssignedPort;
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_MediumDetailDebug,
                        "bound socket to local port <%d>\n",
                        (int) _pPDS->_ui16LocalPort);
    }
    catch (Exception e) {
        checkAndLogMsg ("[ProxyDatagramSocket]Connector::run", Logger::L_MildError,
                        "exception when establishing connection to proxy server; message = <%s>\n",
                        e.getMsg());
        delete pchToServer;
        delete pSocketToServer;
        this->setTerminatingResultCode (-3);
        terminating();
        return;
    }
    _pPDS->_pchToServer = pchToServer;
    _pPDS->_pSocketToServer = pSocketToServer;
    _pPDS->_ui16MTU = ui16MTU;
    _pPDS->_ui32LocalAddr = localAddr.getIPAddress();
    _pPDS->_ui16LocalPort = ui16AssignedPort;
    _pPDS->_bConnectedToServer = true;
    setTerminatingResultCode (0);
    terminating();
    return;
}
Example #2
0
bool NodeInfo::setIPAddress (uint32 ui32IpAddress)
{
    InetAddr addr (ui32IpAddress);
    return setIPAddress (addr.getIPAsString());
}
int ProxyDatagramSocket::sendTo (uint32 ui32IPAddr, uint16 ui16Port, const void *pBuf, int iBufSize, const char *pszHints)
{
    int rc;
    if (_bConnectedToServer) {
        if (iBufSize < 0) {
            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                            "packet size cannot be negative\n");
            return -1;
        }
        if (iBufSize > (MAXIMUM_PROXY_PACKET_SIZE - 17)) {
            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                            "packet too large to be sent - maximum size is <%d>\n",
                            (int) (MAXIMUM_PROXY_PACKET_SIZE - 17));
            return -2;
        }
        try {
            bool bExcludeAddr = false;
            bool bIncludeAddr = false;
            InetAddr excludeAddr;
            InetAddr includeAddr;
            if (pszHints != NULL) {
                // Check to see if we can handle the hints
                StringTokenizer st (pszHints, ';');
                const char *pszHint = NULL;
                while ((pszHint = st.getNextToken()) != NULL) {
                    StringTokenizer st2 (pszHint, '=');
                    const char *pszAttr = st2.getNextToken();
                    const char *pszValue = st2.getNextToken();
                    if ((pszAttr == NULL) || (pszValue == NULL)) {
                        checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                        "could not parse hint <%s> - ignoring\n", pszHint);
                    }
                    // Check to see if an exclude address has been specified in the hints
                    else if (0 == stricmp (pszAttr, "exclude")) {
                        if (InetAddr::isIPv4Addr (pszValue)) {
                            excludeAddr.setIPAddress (pszValue);
                            bExcludeAddr = true;
                        }
                        else {
                            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                            "could not parse exclude address <%s> - ignoring\n", pszValue);
                        }
                    }
                    // Check to see if an include address has been specified in the hints
                    else if (0 == stricmp (pszAttr, "include")) {
                        if (InetAddr::isIPv4Addr (pszValue)) {
                            includeAddr.setIPAddress (pszValue);
                            bIncludeAddr = true;
                        }
                        else {
                            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                            "could not parse include address <%s> - ignoring\n", pszValue);
                        }
                    }
                    // Check to see if we are doing a forced unicast
                    else if (0 == stricmp (pszAttr, "unicast")) {
                        if (InetAddr::isIPv4Addr (pszValue)) {
                            InetAddr unicastAddr (pszValue);
                            ui32IPAddr = unicastAddr.getIPAddress();
                            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Info,
                                            "overwrote destination address with unicast address %s\n", unicastAddr.getIPAsString());
                        }
                    }
                    else {
                        checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                        "unknown hint attribute <%s> - ignoring\n", pszAttr);
                    }
                }
            }
            /*!!*/ // Improve the efficiency of this by implementing a two-argument sendBlock() method
                   // so that a memcpy is not needed
            uint8 aui8Buf [MAXIMUM_PROXY_PACKET_SIZE];
            uint8 ui8Offset = 0;
            if (bIncludeAddr) {
                aui8Buf[ui8Offset] = 'I';
            }
            else if (bExcludeAddr) {
                aui8Buf[ui8Offset] = 'X';
            }
            else {
                aui8Buf[ui8Offset] = 'D';
            }
            ui8Offset += 1;
            (*((uint32*)(aui8Buf+ui8Offset))) = _ui32LocalAddr;
            ui8Offset += 4;
            (*((uint16*)(aui8Buf+ui8Offset))) = EndianHelper::htons (_ui16LocalPort);
            ui8Offset += 2;
            (*((uint32*)(aui8Buf+ui8Offset))) = ui32IPAddr;
            ui8Offset += 4;
            if (bIncludeAddr) {
                (*((uint32*)(aui8Buf+ui8Offset))) = includeAddr.getIPAddress();
                ui8Offset += 4;
            }
            else if (bExcludeAddr) {
                (*((uint32*)(aui8Buf+ui8Offset))) = excludeAddr.getIPAddress();
                ui8Offset += 4;
            }
            (*((uint16*)(aui8Buf+ui8Offset))) = EndianHelper::htons (ui16Port);
            ui8Offset += 2;
            memcpy (aui8Buf+ui8Offset, pBuf, iBufSize);
            _pchToServer->sendBlock (aui8Buf, iBufSize + ui8Offset);
            _ui32SentPacketCount++;
            return iBufSize;
        }
        catch (Exception e) {
            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                            "exception occurred when sending data to proxy server; message = <%s>\n",
                            e.getMsg());
            close();
            rc = -3;
        }
    }
    else {
        checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                        "cannot send - not connected to the proxy server\n");
        rc = -4;
    }
    connectToProxyServer();
    return rc;
}