//////////////////////////////////////////////////// // setCache // adds current packet to specified cache void EQPacketStream::setCache(uint16_t serverArqSeq, EQProtocolPacket& packet) { // check if the entry already exists in the cache EQPacketMap::iterator it = m_cache.find(serverArqSeq); if (it == m_cache.end()) { // entry doesn't exist, so insert an entry into the cache #ifdef PACKET_PROCESS_DIAG seqDebug("SEQ: Insert arq (%04x) stream %d into cache", serverArqSeq, m_streamid); #endif m_cache.insert(EQPacketMap::value_type(serverArqSeq, new EQProtocolPacket(packet, true))); emit cacheSize(m_cache.size(), (int)m_streamid); } else { // replacing an existing entry, make sure the new data is valid #ifdef APPLY_CRC_CHECK if (! packet.hasCRC() || calculateCRC(packet) == packet.crc()) #endif { #ifdef PACKET_PROCESS_DIAG seqDebug("SEQ: Update arq (%04x) stream %d in cache", serverArqSeq, m_streamid); #endif // Free the old packet at this place and replace with the new one. delete it->second; it->second = new EQProtocolPacket(packet, true); } #if defined(PACKET_PROCESS_DIAG) && defined(APPLY_CRC_CHECK) else seqDebug("SEQ: Not Updating arq (%04x) stream %d into cache, CRC error!", serverArqSeq, m_streamid); #endif } #ifdef PACKET_CACHE_DIAG if (m_cache.size() > m_maxCacheCount) m_maxCacheCount = m_cache.size(); #endif // PACKET_CACHE_DIAG }
//////////////////////////////////////////////////// // Cache processing void EQPacketStream::processCache() { #if defined(PACKET_CACHE_DIAG) seqDebug("SEQ: START checking stream %s cache, arq %04x, cache count %04d", EQStreamStr[m_streamid], m_arqSeqExp, m_cache.size()); #endif EQPacketMap::iterator it; EQPacketMap::iterator eraseIt; EQProtocolPacket* packet; // check if the cache has grown large enough that we should give up // on seeing the current serverArqSeqExp // // If people see this a lot, they either have pathetic network cards, or // are having problems keeping up with packets (slow computer? Too much // net traffic?). Some possible solutions to this are to turn on session // tracking to filter out more PF_PACKET packets from getting passed out of // the kernel and to up the socket receive buffer sizes. See FAQ for // more information. if (m_cache.size() >= m_arqSeqGiveUp) { // ok, if the expected server arq sequence isn't here yet, give up // attempt to find the current expencted arq seq it = m_cache.find(m_arqSeqExp); // keep trying to find a new serverArqSeqExp if we haven't found a good // one yet... while(it == m_cache.end()) { seqWarn("SEQ: Giving up on finding arq %04x in stream %s cache, skipping!", m_arqSeqExp, EQStreamStr[m_streamid]); // incremente the expected arq sequence number m_arqSeqExp++; emit seqExpect(m_arqSeqExp, (int)m_streamid); // attempt to find the new current expencted arq seq it = m_cache.find(m_arqSeqExp); } } else { // haven't given up yet, just try to find the current serverArqSeqExp // attempt to find the current expected ARQ seq it = m_cache.find(m_arqSeqExp); } // iterate over cache until we reach the end or run out of // immediate followers while (it != m_cache.end()) { // get the PacketFormat for the iterator packet = it->second; // make sure this is the expected packet // (we might have incremented to the one after the one returned // by find above). if (packet->arqSeq() != m_arqSeqExp) break; #ifdef PACKET_CACHE_DIAG seqDebug("SEQ: found next arq %04x in stream %s cache, cache count %04d", m_arqSeqExp, EQStreamStr[m_streamid], m_cache.size()); #endif // validate the packet with a crc check. If the packet is for an old // session, we probably shouldn't be using it! #ifdef APPLY_CRC_CHECK if (packet->hasCRC() && packet->crc() != calculateCRC(*packet)) { #if defined (PACKET_CACHE_DIAG) // Something's screwed up seqDebug("SEQ: INVALID PACKET: Bad CRC in packet in stream %s cache with arq %04x! Droping it, but leaving expected seq as %04x", EQStreamStr[m_streamid], packet->arqSeq(), m_arqSeqExp); #endif // Need to drop from the cache eraseIt = it; // increment the current position iterator it++; // erase the packet from the cache m_cache.erase(eraseIt); emit cacheSize(m_cache.size(), (int)m_streamid); #ifdef PACKET_CACHE_DIAG seqDebug("SEQ: REMOVING arq %04x from stream %s cache, cache count %04d", packet->arqSeq(), EQStreamStr[m_streamid], m_cache.size()); #endif // delete the packet delete packet; // No sense looping some more. break; } else #endif /* APPLY_CRC_CHECK */ { #if defined (PACKET_CACHE_DIAG) && (PACKET_CACHE_DIAG > 2) seqDebug("SEQ: Found next arq in stream %s cache, incrementing arq seq, %04x", EQStreamStr[m_streamid], packet->arqSeq()); #endif // Process the packet since it's next in the sequence and was just // received out of order processPacket(*packet, packet->isSubpacket()); // Need to drop from the cache eraseIt = it; // increment the current position iterator it++; // erase the packet from the cache m_cache.erase(eraseIt); emit cacheSize(m_cache.size(), (int)m_streamid); #ifdef PACKET_CACHE_DIAG seqDebug("SEQ: REMOVING arq %04x from stream %s cache, cache count %04d", packet->arqSeq(), EQStreamStr[m_streamid], m_cache.size()); #endif // delete the packet delete packet; if (m_arqSeqExp == 0) it = m_cache.begin(); } } #ifdef PACKET_CACHE_DIAG seqDebug("SEQ: FINISHED checking stream %s cache, arq %04x, cache count %04d", EQStreamStr[m_streamid], m_arqSeqExp, m_cache.size()); #endif }