void AvatarManager::RemoveOldAvatarCacheEntries() { string cacheDir; { boost::mutex::scoped_lock lock(m_cacheDirMutex); cacheDir = m_cacheDir; } try { path cachePath(cacheDir); cacheDir = cachePath.directory_string(); // Never delete anything if we do not have a special cache dir set. if (!cacheDir.empty()) { boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); // First pass: Remove files which no longer exist. // Count files and record age. AvatarList removeList; TimeAvatarMap timeMap; { AvatarMap::const_iterator i = m_cachedAvatars.begin(); AvatarMap::const_iterator end = m_cachedAvatars.end(); while (i != end) { bool keepFile = false; path filePath(i->second); string fileString(filePath.file_string()); // Only consider files which are definitely in the cache dir. if (fileString.size() > cacheDir.size() && fileString.substr(0, cacheDir.size()) == cacheDir) { // Only consider files with MD5 as file name. MD5Buf tmpBuf; if (exists(filePath) && tmpBuf.FromString(basename(filePath))) { timeMap.insert(TimeAvatarMap::value_type(last_write_time(filePath), i->first)); keepFile = true; } } if (!keepFile) removeList.push_back(i->first); ++i; } } { AvatarList::const_iterator i = removeList.begin(); AvatarList::const_iterator end = removeList.end(); while (i != end) { m_cachedAvatars.erase(*i); ++i; } removeList.clear(); } // Remove and physically delete files in one of the // following cases: // 1. More than MAX_NUMBER_OF_FILES files are present // - delete until only MAX_NUMBER_OF_FILES/2 are left. // 2. Files are older than 30 days. if (m_cachedAvatars.size() > MAX_NUMBER_OF_FILES) { while (!timeMap.empty() && m_cachedAvatars.size() > MAX_NUMBER_OF_FILES / 2) { TimeAvatarMap::iterator i = timeMap.begin(); AvatarMap::iterator pos = m_cachedAvatars.find(i->second); if (pos != m_cachedAvatars.end()) { path tmpPath(pos->second); remove(tmpPath); m_cachedAvatars.erase(pos); } timeMap.erase(i); } } // Get reference time. time_t curTime = time(NULL); while (!timeMap.empty() && !m_cachedAvatars.empty()) { TimeAvatarMap::iterator i = timeMap.begin(); if (curTime - i->first < (int)MAX_AVATAR_CACHE_AGE) break; AvatarMap::iterator pos = m_cachedAvatars.find(i->second); if (pos != m_cachedAvatars.end()) { path tmpPath(pos->second); remove(tmpPath); m_cachedAvatars.erase(pos); } timeMap.erase(i); } } } catch (...) { LOG_ERROR("Exception caught while cleaning up cache."); } }
void CentralServerConnection::onReceive(const Archive::ByteStream & message) { Archive::ReadIterator ri = message.begin(); GameNetworkMessage msg(ri); ri = message.begin(); if(msg.isType("ConGenericMessage")) { // dispatch to CentralCommandParser ConGenericMessage con(ri); Unicode::String wideResult; m_centralCommandParser->parse(NetworkId(static_cast<NetworkId::NetworkIdType>(con.getMsgId())), Unicode::narrowToWide(con.getMsg()), wideResult); ConGenericMessage response(Unicode::wideToNarrow(wideResult), con.getMsgId()); send(response, true); } else if(msg.isType("CharacterTransferStatusMessage")) { CharacterTransferStatusMessage c(ri); CreatureObject * character = safe_cast<CreatureObject *>(NetworkIdManager::getObjectById(c.getToCharacterId())); if(character) { if(character->getClient()) { character->receiveCharacterTransferStatusMessage(c.getStatusMessage()); } } } else if(msg.isType("TransferRequestNameValidation")) { const GenericValueTypeMessage<TransferCharacterData> requestNameValidation(ri); LOG("CustomerService", ("CharacterTransfer: Received TransferRequestNameValidation from CentralServer : %s", requestNameValidation.getValue().toString().c_str())); std::string name = requestNameValidation.getValue().getDestinationCharacterName(); if(name.empty()) { name = requestNameValidation.getValue().getSourceCharacterName(); } // call the same name validation code that gets called for normal character creation std::string templateName = requestNameValidation.getValue().getObjectTemplateName(); if (templateName.empty()) { uint32 const templateCrc = requestNameValidation.getValue().getObjectTemplateCrc(); if (templateCrc != 0) { templateName = ObjectTemplateList::lookUp(templateCrc).getString(); } } VerifyAndLockNameRequest const verifyRequest(requestNameValidation.getValue().getDestinationStationId(), NetworkId::cms_invalid, templateName, Unicode::narrowToWide(name), 0xFFFFFFFF); StringId const verifyResult = GameServer::getInstance().handleVerifyAndLockNameRequest(verifyRequest, false, false); TransferCharacterData replyData(requestNameValidation.getValue()); replyData.setIsValidName(verifyResult == NameErrors::nameApproved); GenericValueTypeMessage<std::pair<std::string, TransferCharacterData> > reply("TransferReplyNameValidation", std::make_pair(std::string("@") + verifyResult.getCanonicalRepresentation(), replyData)); send(reply, true); } else if(msg.isType("TransferReplyCharacterList")) { const TransferReplyCharacterList reply(ri); const AvatarList & oldAl = reply.getAvatarList(); // remove any characters from the list that would qualify for free CTS; characters that // qualify for free CTS should/must use the in-game free CTS to transfer the character; AvatarList newAl; std::string const & clusterName = GameServer::getInstance().getClusterName(); for (AvatarList::const_iterator iter = oldAl.begin(); iter != oldAl.end(); ++iter) { if (!FreeCtsDataTable::getFreeCtsInfoForCharacter(static_cast<time_t>(NameManager::getInstance().getPlayerCreateTime(iter->m_networkId)), clusterName, false)) newAl.push_back(*iter); else LOG("CustomerService", ("CharacterTransfer: removing (%s, %s, %s) from paid CTS character list for station id %u because the character qualifies for free CTS", clusterName.c_str(), Unicode::wideToNarrow(iter->m_name).c_str(), iter->m_networkId.getValueString().c_str(), reply.getStationId())); } // send updated character list back to CentralServer const TransferReplyCharacterList updatedReply(reply.getTrack(), reply.getStationId(), newAl); send(updatedReply, true); } else if(msg.isType("CtsCompletedForcharacter")) { const GenericValueTypeMessage<std::pair<std::string, NetworkId> > msg(ri); MessageToQueue::getInstance().sendMessageToJava(msg.getValue().second, "ctsCompletedForCharacter", std::vector<int8>(), 0, false); } else if( msg.isType( "GameServerCSRequest" ) ) { GameServerCSRequestMessage request( ri ); GameServer::getInstance().handleCSRequest( request ); } else if( msg.isType( "CSFindAuthObject" ) ) { // see if we have the object. GenericValueTypeMessage< std::pair<NetworkId, unsigned int> > msg( ri ); ServerObject * object = safe_cast<ServerObject *>( NetworkIdManager::getObjectById( msg.getValue().first ) ); // return an appropriate response. if( object && object->isAuthoritative() ) { GenericValueTypeMessage< std::pair< unsigned int, bool > > rmsg( "CSFindAuthObjectReply", std::make_pair( msg.getValue().second, true ) ); GameServer::getInstance().sendToCentralServer( rmsg ); } else { GenericValueTypeMessage< std::pair< unsigned int, bool > > rmsg( "CSFindAuthObjectReply", std::make_pair( msg.getValue().second, false ) ); GameServer::getInstance().sendToCentralServer( rmsg ); } } else { ServerConnection::onReceive(message); } }