PtrLList<String> * TopologyWorldState::getInterestedRemoteNodes (DisServiceDataMsg *pDSDMsg)
{
    // Returns a list with the remote nodes interested in pDSDMsg
    _m.lock(143);
    PtrLList<String> *pInterestedRemoteNodes = NULL;
    // Alive nodes
    for (StringHashtable<Thing>::Iterator iNeighbors = _pLocalNodeInfo->getAllElements(); !iNeighbors.end(); iNeighbors.nextElement()) {
        RemoteNodeInfo *pRNI = (RemoteNodeInfo *) iNeighbors.getValue();
        if (pRNI->isNodeInterested (pDSDMsg)) {
            if (pInterestedRemoteNodes == NULL) {
                pInterestedRemoteNodes = new PtrLList<String>();
            }
            pInterestedRemoteNodes->insert (new String (pRNI->getNodeId()));
        }
    }
    // Dead peers
    for (StringHashtable<RemoteNodeInfo>::Iterator iDead = _deadPeers.getAllElements(); !iDead.end(); iDead.nextElement()) {
        RemoteNodeInfo *pRNI = (RemoteNodeInfo *) iDead.getValue();
        if (pRNI->isNodeInterested (pDSDMsg)) {
            if (pInterestedRemoteNodes == NULL) {
                pInterestedRemoteNodes = new PtrLList<String>();
            }
            pInterestedRemoteNodes->insert (new String (pRNI->getNodeId()));
        }
    }
    _m.unlock(143);
    return pInterestedRemoteNodes;
}
PtrLList<String> * TopologyWorldState::getTargetNodes (DisServiceDataMsg *pDSDMsg)
{
    // Returns a list with the target nodes for pDSDMsg
    _m.lock (145);
    PtrLList<String> *pInterestedNodes = getInterestedRemoteNodes (pDSDMsg);
    PtrLList<String> *pTargetNodes = NULL;
    if (pInterestedNodes) {
        for (String *pSubNode = pInterestedNodes->getFirst(); pSubNode; pSubNode = pInterestedNodes->getNext()) {
            bool bActiveTarget = isActiveNeighbor (pSubNode->c_str());
            const char *pszBestGW = NULL;
            if (bActiveTarget) {
                pszBestGW = pSubNode->c_str();
            } else {
                pszBestGW = getBestGateway (pSubNode->c_str());
            }
            if (pszBestGW) {
                if (pTargetNodes == NULL) {
                    pTargetNodes = new PtrLList<String>();
                }
                if (pTargetNodes->search (new String (pszBestGW)) == NULL) {
                    pTargetNodes->insert (new String (pszBestGW));
                }
            }
        }
    }
    _m.unlock (145);
    return pTargetNodes;
}
PtrLList<Message> * NetworkTrafficMemory::filterRecentlySent (Message *pMsg, int64 i64RequestArrivalTime)
{
    _m.lock (186);
    MessageHeader *pMH = pMsg->getMessageHeader();
    if (pMH == NULL) {
        checkAndLogMsg ("NetworkTrafficMemory::filterRecentlySent", Logger::L_Warning,
                        "Message object does not contain message header.\n");
    }

    PtrLList<Message> *pRet = new PtrLList<Message>();
    if (pRet == NULL) {
        checkAndLogMsg ("NetworkTrafficMemory::filterRecentlySent", memoryExhausted);
        _m.unlock (186);
        return NULL;
    }

    if (_ui16IgnoreRequestTime == 0) {
        pRet->insert (new Message (pMH->clone(), pMsg->getData()));
         _m.unlock (186);
        return pRet;
    }

    MessagesByGroup *pBG = _messageByGroup.get (pMH->getGroupName());
    if (pBG == NULL) {
        pRet->insert (new Message (pMH->clone(), pMsg->getData()));
         _m.unlock (186);
        return pRet;
    }

    MessagesBySender *pMS = pBG->messageBySender.get (pMH->getPublisherNodeId());
    if (pMS == NULL) {
        pRet->insert (new Message (pMH->clone(), pMsg->getData()));
         _m.unlock (186);
        return pRet;
    }

    FragmentedMessageHeader *pFMH = pMS->messageBySeqId.get (pMH->getMsgSeqId());
    if (pFMH == NULL) {
        pRet->insert (new Message (pMH->clone(), pMsg->getData()));
         _m.unlock (186);
        return pRet;
    }

    if (pMH->isChunk()) {
        FragmentedChunk *pFC = ((FragmentedMessage *) pFMH)->chunksByChunkId.get (pMsg->getChunkMsgInfo()->getChunkId());
        if (pFC == NULL) {
            pRet->insert (new Message (pMH->clone(), pMsg->getData()));
            _m.unlock (186);
            return pRet;
        }
        else {
            pFMH = pFC;
        }
    }

    char *psFragToSendData;
    psFragToSendData = (char *) pMsg->getData();
    uint32 ui32FragToSendStart = pMH->getFragmentOffset();
    uint32 ui32FragToSendEnd = ui32FragToSendStart + pMH->getFragmentLength();

    MessageHeader *pTmpMI;

    for (FragmentWrapper *pFW = pFMH->fragments.getFirst(); (pFW != NULL) && (ui32FragToSendEnd > pFW->ui32Offset); pFW = pFMH->fragments.getNext()) {
        if (pFW->overlaps (ui32FragToSendStart, ui32FragToSendEnd)) {
            if ((i64RequestArrivalTime - pFW->i64LastServingTime) < _ui16IgnoreRequestTime) {
                // I need to split
                // write everything before pFW->ui32Offset
                uint32 ui32TmpFragLength = (ui32FragToSendStart < pFW->ui32Offset ? pFW->ui32Offset - ui32FragToSendStart : (uint32) 0);
                if (ui32TmpFragLength > 0) {
                    pTmpMI = pMH->clone();
                    pTmpMI->setFragmentOffset (ui32FragToSendStart);
                    pTmpMI->setFragmentLength (ui32TmpFragLength);
                    pRet->insert (new Message (pTmpMI, psFragToSendData));
                }
                // ui32FragToSendStart = pFW->ui32End;
                // psFragToSendData = psFragToSendData + ui32TmpFragLength;
                ui32TmpFragLength = minimum (pFW->ui32End, ui32FragToSendEnd) - ui32FragToSendStart;
                ui32FragToSendStart += ui32TmpFragLength;
                psFragToSendData += ui32TmpFragLength;
            }
        }
    }
    // Add the remaining part
    if (ui32FragToSendStart < ui32FragToSendEnd) {
        pTmpMI = pMH->clone();
        pTmpMI->setFragmentOffset (ui32FragToSendStart);
        pTmpMI->setFragmentLength (ui32FragToSendEnd - ui32FragToSendStart);
        pRet->insert (new Message (pTmpMI, psFragToSendData));
    }
    _m.unlock (186);
    return pRet;
}