Esempio n. 1
0
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);
	}
}