Esempio n. 1
0
char *readStreamUpToTagAndGetToken( InputStream *inInputStream,
                                    char *inTag, int inMaxCharsToRead,
                                    int inTokenNumber ) {

    // read the string
    char *readString = readStreamUpToTag( inInputStream,
                                          inTag,
                                          inMaxCharsToRead );

    if( readString == NULL ) {
        return NULL;
        }

    SimpleVector<char *> *readTokens =
        tokenizeString( readString );

    delete [] readString;

    
    // second token should be their key
    char *selectedToken = NULL;

    int numTokens = readTokens->size(); 
    if( numTokens > inTokenNumber ) {
        selectedToken =
            stringDuplicate( *( readTokens->getElement( inTokenNumber ) ) );
        }
    else {
        char *message = autoSprintf(
            "Looking for token %d, but only %d tokens available\n",
            inTokenNumber, numTokens );
        
        AppLog::error( "readStreamUpToTagAndGetToken", message );
        }

    
    for( int i=0; i<numTokens; i++ ) {
        delete [] *( readTokens->getElement( i ) );
        }
    delete readTokens;


    // will be NULL if not enough tokens read
    return selectedToken;
    }
Esempio n. 2
0
void ChannelReceivingThread::run ()
{
    AppLog::detail (mLoggerName, "Starting up.");
    
    char correctMessageReceived = true;
    
    // first, receive the incoming host list
    // read up to the first occurrence of "EndHostList", allowing 10,000
    // characters
    char *readListBuffer = readStreamUpToTag (mInputStream,
                                              "EndHostList", 10000);
    if (readListBuffer != NULL)
    {
        
        AppLog::trace (mLoggerName, readListBuffer);
        
        // tokenize it
        SimpleVector < char *>*tokenVector;

        if(settings->getAcceptSeedNodes()) {
            tokenVector = tokenizeString (readListBuffer);
        }
        else {
            AppLog::detail(mLoggerName, "Host List received is ignored for user settings");
            tokenVector= new SimpleVector<char *>();
        }
        
        
        delete[]readListBuffer;
        
        
        int numTokens = tokenVector->size ();
        
        // count should be second token, so skip first two
        
        int i;
        for (i = 2; i < numTokens - 1; i += 2)
        {
            
            char *addressString = *(tokenVector->getElement (i));
            char *portString = *(tokenVector->getElement (i + 1));
            
            int port;
            
            int numRead = sscanf (portString, "%d", &port);
            
            if (numRead == 1)
            {
                HostAddress *address =
                        new HostAddress (stringDuplicate (addressString), port);
                mHostCatcher->addHost (address);
                delete address;
            }
        }
        
        for (i = 0; i < numTokens; i++)
        {
            delete[] * (tokenVector->getElement (i));
        }
        
        delete tokenVector;
    }
    else
    {
        AppLog::error (mLoggerName, "Failed to receive host list.");
        correctMessageReceived = false;
    }
    
    
    // check for an accpeted connection status
    
    char connectionAccepted = false;
    
    if (correctMessageReceived)
    {
        correctMessageReceived = false;
        
        // next, receive the connection status
        char *readStatusBuffer =
                readStreamUpToTag (mInputStream, "EndConnectionStatus", 1000);
        
        if (readStatusBuffer != NULL)
        {
            AppLog::trace (mLoggerName, readStatusBuffer);
            
            // tokenize it
            SimpleVector < char *>*tokenVector =
                    tokenizeString (readStatusBuffer);
            
            delete[]readStatusBuffer;
            

            int numTokens = tokenVector->size ();
            
            if (numTokens > 2)
            {
                // second token is status
                char *status = *(tokenVector->getElement (1));
                
                if (strcmp (status, "Accepted") == 0)
                {
                    connectionAccepted = true;
                    correctMessageReceived = true;
                    // we are actually connected now
                    AppLog::info (mLoggerName,
                                  "Connection accepted by remote host.");
                    
                    // log it, if needed
                    int logConnectionsFlag = settings->getLogConnectionsSetting();
                    
                    if (logConnectionsFlag == 1)
                    {
                        FILE *connectionLogFILE =
                                fopen ("connectionHistory.log", "a");
                        
                        if (connectionLogFILE != NULL)
                        {
                            
                            fprintf (connectionLogFILE, "%s : %d\n",
                                     mRemoteAddress, mRemotePort);
                            
                            fclose (connectionLogFILE);
                        }
                    }
                    
                }
                else if (strcmp (status, "Rejected") == 0)
                {
                    connectionAccepted = false;
                    correctMessageReceived = true;
                    
                    AppLog::info (mLoggerName,
                                  "Connection rejected by remote host.");
                }
            }
            
            for (int i = 0; i < numTokens; i++)
            {
                delete[] * (tokenVector->getElement (i));
            }
            delete tokenVector;
        }
        
        if (!correctMessageReceived)
        {
            AppLog::error (mLoggerName, "Failed to receive connection status.");
        }
    }
    
    
    
    
    // now read a series of MUTE messages
    
    mLock->lock ();
    char stopped = mStopSignal;
    mLock->unlock ();
    int badMessageReceived=0;
    while (!stopped && badMessageReceived<3 && connectionAccepted)
    {
        
        // read a message
        correctMessageReceived = false;
        
        
        
        // read up to the first occurrence of "Body:"
        char *readCharBuffer = readStreamUpToTag (mInputStream,
                                                  "Body:", 5000);
        
        if (readCharBuffer != NULL)
        {
	    const char *posBody=strstr("Body:",readCharBuffer);
	    int lenHeader;
	    if(posBody)
		lenHeader = posBody-readCharBuffer+5;
	    else
		lenHeader = strlen(readCharBuffer);
	    TotBytesReceived += lenHeader;
            mLimiter->bytesTransmitted (lenHeader);
            // buffer ends with "Body:" plus terminating character
            
            AppLog::detail (mLoggerName, "Got header");
            AppLog::trace (mLoggerName, readCharBuffer);
            
            // tokenize it
            SimpleVector < char *>*tokenVector =
                    tokenizeString (readCharBuffer);
            
            char *messageID = NULL;
            char *fromAddress = NULL;
            char *toAddress = NULL;
            char *flags = NULL;
            int utilityCounter = 0;
            int payloadLength = -1;
            char *dataPayload = NULL;
            
            int numTokens = tokenVector->size ();
            
            int i;
            for (i = 0; i < numTokens - 1; i++)
            {
                char *currentToken = *(tokenVector->getElement (i));
                char *nextToken = *(tokenVector->getElement (i + 1));
                
                if (strcmp (currentToken, "UniqueID:") == 0)
                {
                    messageID = stringDuplicate (nextToken);
                }
                else if (strcmp (currentToken, "From:") == 0)
                {
                    fromAddress = stringDuplicate (nextToken);
                }
                else if (strcmp (currentToken, "To:") == 0)
                {
                    toAddress = stringDuplicate (nextToken);
                }
                else if (strcmp (currentToken, "Flags:") == 0)
                {
                    flags = stringDuplicate (nextToken);
                }
                else if (strcmp (currentToken, "UtilityCounter:") == 0)
                {
                    sscanf (nextToken, "%d", &utilityCounter);
                }
                else if (strcmp (currentToken, "Length:") == 0)
                {
                    sscanf (nextToken, "%d", &payloadLength);
                }
            }
            
            // destroy vector
            for (i = 0; i < numTokens; i++)
            {
                delete[] * (tokenVector->getElement (i));
            }
            delete tokenVector;
            
            
            if (messageID != NULL &&
                fromAddress != NULL &&
                toAddress != NULL && flags != NULL && payloadLength > 0)
            {
                
                // all header items read correctly
                
                // make sure payload not too big
                if (payloadLength <= 32768)
                {
                    
                    dataPayload = new char[payloadLength + 1];
                    
                    int numRead =
                            mInputStream->read ((unsigned char *) dataPayload,
                                                payloadLength);
                    
		    TotBytesReceived += numRead;
                    // terminate payload string
                    if (numRead > 0 && numRead <= payloadLength)
                    {
                        dataPayload[numRead] = '\0';
                    }
                    else
                    {
                        dataPayload[payloadLength] = '\0';
                    }
                    
                    if (numRead == payloadLength)
                    {
                        // we've already traced the header
                        AppLog::trace (mLoggerName, dataPayload);
                        
                        correctMessageReceived = true;
			TotMessagesReceived ++;
                        if (strcmp (toAddress, "ALL") == 0) TotMessagesToAll++;
                        // message formatted correctly,
                        // so process it
                        
                        // obey the limit
                        // we will block here if message rate is too high
                        mLimiter->bytesTransmitted (numRead);
                        
                        
                        
                        
                        // process the message
                        //printf( "Registering received ID %s\n", messageID );
                        char fresh =
                                mMessageIDTracker->checkIfIDFresh (messageID);
                        
                        if (fresh)
                        {
                            AppLog::detail (mLoggerName, "Message fresh.");
                        }
                        else
                        {
                            AppLog::detail (mLoggerName, "Message stale.");
                        }
                        
                        // only do work of processing flags for fresh
                        // messages
                        
                        // we might drop a fresh message based on flags
                        
                        char ignoreUC = false;
                        char dropMessage = false;
                        
                        
                        if (fresh)
                        {
                            char *newFlags = processFlags (messageID,
                                                           fromAddress,
                                                           flags,
                                                           &ignoreUC,
                                                           &dropMessage,
                                                           mLoggerName);
                            
                            delete[]flags;
                            flags = newFlags;
                            
                            if (dropMessage)
                            {
                                AppLog::detail (mLoggerName,
                                                "Dropping message based on flags.");
                            }
                        }
                        
                        
                        // ignore messages that are not fresh
                        // or that should be dropped according to flags.
                        if (fresh && !dropMessage)
                        {
                            
                            
                            if (strstr (flags, "FRESH_ROUTE") != NULL)
                            {
                                // clear the routing information in both
                                // directions
                                mOutboundChannelManager->
                                        clearRoutingInformation (fromAddress);
                                mOutboundChannelManager->
                                        clearRoutingInformation (toAddress);
                            }
                            
                            // add new back-routing information
                            mOutboundChannelManager->
                                    addRoutingInformation (fromAddress,
                                                           mOutboundChannel);
                            
                            int generatedUtility = 0;
                            char receivedLocally;
                            
                            if (strstr (flags, "DROP_TTL") != NULL)
                            {
                                // don't locally-process DROP_TTL messages
                                receivedLocally = false;
                            }
                            else
                            {
                                receivedLocally =
                                        mReceiver->messageReceived (fromAddress,
                                                                    toAddress,
                                                                    dataPayload,
                                                                    &generatedUtility);
                            }
                            
                            if (receivedLocally)
                            {
                                AppLog::detail (mLoggerName,
                                                "Message consumed locally.");
                            }
                            
                            
                            // check this even if ignoring UCs
                            if (utilityCounter < -mMaxUtilityCounter)
                            {
                                // correct negative utility counters
                                utilityCounter = -mMaxUtilityCounter +
                                                 mRandSource->getRandomBoundedInt (0, 6);
                            }
                            
                            // we might generate utility for any message
                            // type, either routed or broadcast (ALL),
                            // that we do not consume locally
                            
                            if (!ignoreUC)
                            {
                                // add in our weighted, generated utility
                                utilityCounter +=
                                        mUtilityAlpha * generatedUtility;
                            }
                            
                            
                            // if we didn't consume message locally
                            // or if message is a broadcast
                            if (!receivedLocally ||
                                strcmp (toAddress, "ALL") == 0)
                            {
                                
                                
                                if (strcmp (toAddress, "ALL") == 0)
                                {
                                    
                                    if (!ignoreUC)
                                    {
                                        // for ALL messages, also add in
                                        // the weighted (beta) branching
                                        // factor at this node and the
                                        // (gamma) constant factor
                                        
                                        int numNeighbors =
                                                mOutboundChannelManager->
                                                getConnectionCount ();
                                        
                                        // we won't send to the neighbor that
                                        // sent the message to us
                                        int branchFactor = numNeighbors - 1;
                                        int deltaUtility =
                                                mUtilityBeta * branchFactor +
                                                mUtilityGamma +
                                                mRandSource->getRandomBoundedInt (-6,
                                                                                  0);
                                        if (deltaUtility < 1)
                                            deltaUtility = 1;
                                        
                                        utilityCounter += deltaUtility;
                                    }
                                }
                                
                                if (!ignoreUC &&
                                    utilityCounter > mMaxUtilityCounter)
                                {
                                    
                                    // we have pushed the UC over the top
                                    
                                    // switch the message into DROP_CHAIN
                                    // mode to start the drop tail
                                    // the OutboundChannelManager will handle
                                    // the chaining and the side DROP_TTL
                                    // trees when it sees the DROP_CHAIN flag
                                    
                                    char *tempFlags = muteAddFlag (flags,
                                                                   "DROP_CHAIN");
                                    delete[]flags;
                                    flags = tempFlags;
                                    
                                    AppLog::detail (mLoggerName,
                                                    "Message switched into DROP_CHAIN "
                                                    " mode because its"
                                                    " utility is too high.");
                                    
                                    // if we switch a message into DROP_CHAIN
                                    // mode, we should pass it to the
                                    // OutboundChannelManager even if
                                    // the number of neighbors that we send
                                    // DROP_CHAIN messages to is 0.
                                    // In these cases, we will be sending
                                    // DROP_TTL messages to all neighbors.
                                    // We must do this because we have
                                    // already processed the message above
                                    // before we decide to change it into
                                    // DROP_CHAIN mode.  If we simply
                                    // drop it at this point, our neighbors
                                    // could tell that we didn't send out
                                    // any DROP_TTL message (and therefore
                                    // that we weren't passing the DROP_CHAIN
                                    // message on to any neighbors).  They
                                    // could be sure the results they see
                                    // are coming from us.
                                }
                                
                                if (!dropMessage)
                                {
                                    // route it
                                    // this manager will pay attention
                                    // to flags when routing.
                                    mOutboundChannelManager->
                                            routeMessage (messageID, fromAddress,
                                                          toAddress, flags,
                                                          utilityCounter, dataPayload,
                                                          mOutboundChannel);
                                    
                                    AppLog::detail (mLoggerName,
                                                    "Message routed onward.");
                                }
                            }
                        }
                    }
                    else
                    {
                        AppLog::error (mLoggerName,
                                       "Failed to read message data payload");
                    }
                }
                else
                {
                    AppLog::error (mLoggerName,
                                   "Failed to read message payload too long");
                }
            }
            else
            {
              if (messageID == NULL )
                AppLog::error (mLoggerName, "No Message ID");
              else if ( fromAddress == NULL )
                AppLog::error (mLoggerName, "No From Address");
              else if ( toAddress == NULL )
                AppLog::error (mLoggerName, "No To Address");
	      else if ( flags == NULL )
                AppLog::error (mLoggerName, "No Flags");
	      else
                AppLog::error (mLoggerName, "Payload length negative");
            }
            
            
            
            // clean up, whether correct message was received or not
            if (messageID != NULL)
            {
                delete[]messageID;
            }
            if (fromAddress != NULL)
            {
                delete[]fromAddress;
            }
            if (toAddress != NULL)
            {
                delete[]toAddress;
            }
            if (flags != NULL)
            {
                delete[]flags;
            }
            if (dataPayload != NULL)
            {
                delete[]dataPayload;
            }
            
            delete[]readCharBuffer;
        }
        
        
        if (correctMessageReceived)
        {
//            AppLog::detail (mLoggerName, "Correct message received");
            badMessageReceived=0;
        }
        else
        {
            AppLog::warning (mLoggerName, "Bad message received");
            badMessageReceived++;
        }
        
        mLock->lock ();
        stopped = mStopSignal;
        mLock->unlock ();
        
    }
    
    
    // TODO
    // however we got here, we should perhaps remove the host from the catcher
    // (rejected our connection, broke the connection, sent a bad message,
    //  dropped too many messages)
    // or immediately retry connect if it was a good host....
    // HostAddress *remoteHost = new HostAddress (stringDuplicate (mRemoteAddress),
    //                                           mRemotePort);
    // mHostCatcher->noteHostBad (remoteHost);
    // delete remoteHost;
    
    
    // let channel manager know that channel has been broken
    mOutboundChannelManager->channelBroken (mOutboundChannel);
    
    // cast to true type
    ConnectionMaintainer *maintainer =
            (ConnectionMaintainer *) mConnectionMaintainer;
    maintainer->connectionBroken ();
    
    // destroy the socket using the manager
    SocketManager::destroySocket (mSocket);
    
    
    mLock->lock ();
    mFinished = true;
    mLock->unlock ();
}