[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()); i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow());
if(!i_path) 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; return;
} }

View file

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

View file

@ -350,7 +350,7 @@ class World
//player Queue //player Queue
typedef std::list<WorldSession*> Queue; typedef std::list<WorldSession*> Queue;
void AddQueuedPlayer(WorldSession*); void AddQueuedPlayer(WorldSession*);
void RemoveQueuedPlayer(WorldSession*); bool RemoveQueuedPlayer(WorldSession* session);
int32 GetQueuePos(WorldSession*); int32 GetQueuePos(WorldSession*);
uint32 GetQueueSize() const { return m_QueuedPlayer.size(); } uint32 GetQueueSize() const { return m_QueuedPlayer.size(); }
@ -433,7 +433,6 @@ class World
bool KickPlayer(std::string playerName); bool KickPlayer(std::string playerName);
void KickAll(); void KickAll();
void KickAllLess(AccountTypes sec); void KickAllLess(AccountTypes sec);
void KickAllQueued();
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author);
bool RemoveBanAccount(BanMode mode, std::string nameOrIP); bool RemoveBanAccount(BanMode mode, std::string nameOrIP);
@ -491,7 +490,6 @@ class World
WeatherMap m_weathers; WeatherMap m_weathers;
typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap; typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap;
SessionMap m_sessions; SessionMap m_sessions;
std::set<WorldSession*> m_kicked_sessions;
uint32 m_maxActiveSessionCount; uint32 m_maxActiveSessionCount;
uint32 m_maxQueuedSessionCount; 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), LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time),
_player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expansion), _player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expansion),
m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)), 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) if (sock)
{ {
@ -205,6 +205,13 @@ bool WorldSession::Update(uint32 /*diff*/)
(this->*opHandle.handler)(*packet); (this->*opHandle.handler)(*packet);
break; break;
case STATUS_AUTHED: case STATUS_AUTHED:
// prevent cheating with skip queue wait
if(m_inQueue)
{
logUnexpectedOpcode(packet, "the player not pass queue yet");
break;
}
m_playerRecentlyLogout = false; m_playerRecentlyLogout = false;
(this->*opHandle.handler)(*packet); (this->*opHandle.handler)(*packet);
break; break;

View file

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

View file

@ -72,7 +72,6 @@ void WorldRunnable::run()
prevSleepTime = 0; 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.KickAll(); // save and kick all players
sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call

View file

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