[6858] Prevent cheating with ignore waiting in login queue.

Cheating preventing at reconect for queued session and sending unexpected packets to server.
Removed unneeded after ACE related changes kicked sessions list.
This commit is contained in:
VladimirMangos 2008-11-29 08:00:27 +03:00
parent 874339ecee
commit 51546c7ab7
7 changed files with 56 additions and 47 deletions

View file

@ -50,7 +50,8 @@ WaypointMovementGenerator<Creature>::LoadPath(Creature &c)
i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow());
if(!i_path)
{
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s(%d) doesn't have waypoint path", c.GetName(), c.GetDBTableGUIDLow());
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %d) doesn't have waypoint path",
c.GetName(), c.GetEntry(), c.GetDBTableGUIDLow());
return;
}

View file

@ -112,10 +112,12 @@ World::World()
World::~World()
{
///- Empty the kicked session set
for (std::set<WorldSession*>::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr)
delete *itr;
m_kicked_sessions.clear();
while (!m_sessions.empty())
{
// not remove from queue, prevent loading new sessions
delete m_sessions.begin()->second;
m_sessions.erase(m_sessions.begin());
}
///- Empty the WeatherMap
for (WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr)
@ -195,17 +197,26 @@ World::AddSession_ (WorldSession* s)
if (!RemoveSession (s->GetAccountId ()))
{
s->KickPlayer ();
m_kicked_sessions.insert (s);
delete s; // session not added yet in session list, so not listed in queue
return;
}
// decrease session counts only at not reconnection case
bool decrease_session = true;
// if session already exist, prepare to it deleting at next world update
// NOTE - KickPlayer() should be called on "old" in RemoveSession()
{
SessionMap::const_iterator old = m_sessions.find(s->GetAccountId ());
SessionMap::const_iterator old = m_sessions.find(s->GetAccountId ());
if(old != m_sessions.end())
m_kicked_sessions.insert (old->second);
if(old != m_sessions.end())
{
// prevent decrease sessions count if session queued
if(RemoveQueuedPlayer(old->second))
decrease_session = false;
// not remove replaced session form queue if listed
delete old->second;
}
}
m_sessions[s->GetAccountId ()] = s;
@ -213,9 +224,11 @@ World::AddSession_ (WorldSession* s)
uint32 Sessions = GetActiveAndQueuedSessionCount ();
uint32 pLimit = GetPlayerAmountLimit ();
uint32 QueueSize = GetQueueSize (); //number of players in the queue
//so we don't count the user trying to
//login as a session and queue the socket that we are using
--Sessions;
if(decrease_session)
--Sessions;
if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
{
@ -259,6 +272,7 @@ int32 World::GetQueuePos(WorldSession* sess)
void World::AddQueuedPlayer(WorldSession* sess)
{
sess->SetInQueue(true);
m_QueuedPlayer.push_back (sess);
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
@ -274,7 +288,7 @@ void World::AddQueuedPlayer(WorldSession* sess)
//sess->SendAuthWaitQue (GetQueuePos (sess));
}
void World::RemoveQueuedPlayer(WorldSession* sess)
bool World::RemoveQueuedPlayer(WorldSession* sess)
{
// sessions count including queued to remove (if removed_session set)
uint32 sessions = GetActiveSessionCount();
@ -282,16 +296,16 @@ void World::RemoveQueuedPlayer(WorldSession* sess)
uint32 position = 1;
Queue::iterator iter = m_QueuedPlayer.begin();
// if session not queued then we need decrease sessions count (Remove socked callet before session removing from session list)
bool decrease_session = true;
// search to remove and count skipped positions
bool found = false;
for(;iter != m_QueuedPlayer.end(); ++iter, ++position)
{
if(*iter==sess)
{
sess->SetInQueue(false);
iter = m_QueuedPlayer.erase(iter);
decrease_session = false; // removing queued session
found = true; // removing queued session
break;
}
}
@ -299,15 +313,16 @@ void World::RemoveQueuedPlayer(WorldSession* sess)
// iter point to next socked after removed or end()
// position store position of removed socket and then new position next socket after removed
// decrease for case session queued for removing
if(decrease_session && sessions)
// if session not queued then we need decrease sessions count
if(!found && sessions)
--sessions;
// accept first in queue
if( (!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty() )
{
WorldSession * socket = m_QueuedPlayer.front();
socket->SendAuthWaitQue(0);
WorldSession* pop_sess = m_QueuedPlayer.front();
pop_sess->SetInQueue(false);
pop_sess->SendAuthWaitQue(0);
m_QueuedPlayer.pop_front();
// update iter to point first queued socket or end() if queue is empty now
@ -319,6 +334,8 @@ void World::RemoveQueuedPlayer(WorldSession* sess)
// iter point to first not updated socket, position store new position
for(; iter != m_QueuedPlayer.end(); ++iter, ++position)
(*iter)->SendAuthWaitQue(position);
return found;
}
/// Find a Weather object by the given zoneid
@ -2170,6 +2187,8 @@ void World::SendZoneText(uint32 zone, const char* text, WorldSession *self, uint
/// Kick (and save) all players
void World::KickAll()
{
m_QueuedPlayer.clear(); // prevent send queue update packet and login queued sessions
// session not removed at kick and will removed in next update tick
for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
itr->second->KickPlayer();
@ -2184,18 +2203,6 @@ void World::KickAllLess(AccountTypes sec)
itr->second->KickPlayer();
}
/// Kick all queued players
void World::KickAllQueued()
{
// session not removed at kick and will removed in next update tick
//TODO here
// for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr)
// if(WorldSession* session = (*itr)->GetSession())
// session->KickPlayer();
m_QueuedPlayer.empty();
}
/// Kick (and save) the designated player
bool World::KickPlayer(std::string playerName)
{
@ -2426,20 +2433,13 @@ void World::SendServerMessage(uint32 type, const char *text, Player* player)
void World::UpdateSessions( time_t diff )
{
///- Add new sessions
while(!addSessQueue.empty())
{
WorldSession* sess = addSessQueue.next ();
AddSession_ (sess);
WorldSession* sess = addSessQueue.next ();
AddSession_ (sess);
}
///- Delete kicked sessions at add new session
for (std::set<WorldSession*>::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr)
{
RemoveQueuedPlayer (*itr);
delete *itr;
}
m_kicked_sessions.clear();
///- Then send an update signal to remaining ones
for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
{

View file

@ -350,7 +350,7 @@ class World
//player Queue
typedef std::list<WorldSession*> Queue;
void AddQueuedPlayer(WorldSession*);
void RemoveQueuedPlayer(WorldSession*);
bool RemoveQueuedPlayer(WorldSession* session);
int32 GetQueuePos(WorldSession*);
uint32 GetQueueSize() const { return m_QueuedPlayer.size(); }
@ -433,7 +433,6 @@ class World
bool KickPlayer(std::string playerName);
void KickAll();
void KickAllLess(AccountTypes sec);
void KickAllQueued();
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author);
bool RemoveBanAccount(BanMode mode, std::string nameOrIP);
@ -491,7 +490,6 @@ class World
WeatherMap m_weathers;
typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap;
SessionMap m_sessions;
std::set<WorldSession*> m_kicked_sessions;
uint32 m_maxActiveSessionCount;
uint32 m_maxQueuedSessionCount;

View file

@ -45,7 +45,7 @@ WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, uint8 expan
LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time),
_player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expansion),
m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)),
_logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0)
_logoutTime(0), m_inQueue(false), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0)
{
if (sock)
{
@ -205,6 +205,13 @@ bool WorldSession::Update(uint32 /*diff*/)
(this->*opHandle.handler)(*packet);
break;
case STATUS_AUTHED:
// prevent cheating with skip queue wait
if(m_inQueue)
{
logUnexpectedOpcode(packet, "the player not pass queue yet");
break;
}
m_playerRecentlyLogout = false;
(this->*opHandle.handler)(*packet);
break;

View file

@ -95,6 +95,9 @@ class MANGOS_DLL_SPEC WorldSession
void SetPlayer(Player *plr) { _player = plr; }
uint8 Expansion() const { return m_expansion; }
/// Session in auth.queue currently
void SetInQueue(bool state) { m_inQueue = state; }
/// Is the user engaged in a log out process?
bool isLogingOut() const { return _logoutTime || m_playerLogout; }
@ -635,6 +638,7 @@ class MANGOS_DLL_SPEC WorldSession
uint8 m_expansion;
time_t _logoutTime;
bool m_inQueue; // session wait in auth.queue
bool m_playerLoading; // code processed in LoginPlayer
bool m_playerLogout; // code processed in LogoutPlayer
bool m_playerRecentlyLogout;

View file

@ -72,7 +72,6 @@ void WorldRunnable::run()
prevSleepTime = 0;
}
sWorld.KickAllQueued(); // kick all queued players (and prevent its login at kick in game players)
sWorld.KickAll(); // save and kick all players
sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "6857"
#define REVISION_NR "6858"
#endif // __REVISION_NR_H__