[svn] Merge from Mangos:
3c7ac5bd3e20c33a22ac57c5c3bac23a0798dc9e 2008-10-23 19:06:27 Some endianess related fixes and cleanups. By VladimirMangos. --HG-- branch : trunk
This commit is contained in:
@@ -10,12 +10,12 @@
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_BYTECONVERTER_H
|
||||
@@ -48,12 +48,18 @@ namespace ByteConverter
|
||||
|
||||
#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
|
||||
template<typename T> inline void EndianConvert(T& val) { ByteConverter::apply<T>(&val); }
|
||||
template<typename T> inline void EndianConvertReverse(T&) { }
|
||||
#else
|
||||
template<typename T> inline void EndianConvert(T&) { }
|
||||
template<typename T> inline void EndianConvertReverse(T& val) { ByteConverter::apply<T>(&val); }
|
||||
#endif
|
||||
|
||||
template<typename T> inline void EndianConvert(T*) { }
|
||||
template<typename T> void EndianConvert(T*); // will generate link error
|
||||
template<typename T> void EndianConvertReverse(T*); // will generate link error
|
||||
|
||||
inline void EndianConvert(uint8&) { }
|
||||
inline void EndianConvert( int8&) { }
|
||||
inline void EndianConvertReverse(uint8&) { }
|
||||
inline void EndianConvertReverse( int8&) { }
|
||||
|
||||
#endif
|
||||
|
||||
+90
-89
@@ -128,7 +128,7 @@ World::~World()
|
||||
VMAP::VMapFactory::clear();
|
||||
|
||||
if(m_resultQueue) delete m_resultQueue;
|
||||
|
||||
|
||||
//TODO free addSessQueue
|
||||
}
|
||||
|
||||
@@ -182,67 +182,67 @@ bool World::RemoveSession(uint32 id)
|
||||
|
||||
void World::AddSession(WorldSession* s)
|
||||
{
|
||||
addSessQueue.add(s);
|
||||
addSessQueue.add(s);
|
||||
}
|
||||
|
||||
void
|
||||
World::AddSession_ (WorldSession* s)
|
||||
{
|
||||
ASSERT (s);
|
||||
ASSERT (s);
|
||||
|
||||
//NOTE - Still there is race condition in WorldSession* being used in the Sockets
|
||||
//NOTE - Still there is race condition in WorldSession* being used in the Sockets
|
||||
|
||||
///- kick already loaded player with same account (if any) and remove session
|
||||
///- if player is in loading and want to load again, return
|
||||
if (!RemoveSession (s->GetAccountId ()))
|
||||
///- kick already loaded player with same account (if any) and remove session
|
||||
///- if player is in loading and want to load again, return
|
||||
if (!RemoveSession (s->GetAccountId ()))
|
||||
{
|
||||
s->KickPlayer ();
|
||||
m_kicked_sessions.insert (s);
|
||||
return;
|
||||
s->KickPlayer ();
|
||||
m_kicked_sessions.insert (s);
|
||||
return;
|
||||
}
|
||||
|
||||
WorldSession* old = m_sessions[s->GetAccountId ()];
|
||||
m_sessions[s->GetAccountId ()] = s;
|
||||
WorldSession* old = m_sessions[s->GetAccountId ()];
|
||||
m_sessions[s->GetAccountId ()] = s;
|
||||
|
||||
// if session already exist, prepare to it deleting at next world update
|
||||
// NOTE - KickPlayer() should be called on "old" in RemoveSession()
|
||||
if (old)
|
||||
m_kicked_sessions.insert (old);
|
||||
// if session already exist, prepare to it deleting at next world update
|
||||
// NOTE - KickPlayer() should be called on "old" in RemoveSession()
|
||||
if (old)
|
||||
m_kicked_sessions.insert (old);
|
||||
|
||||
uint32 Sessions = GetActiveAndQueuedSessionCount ();
|
||||
uint32 pLimit = GetPlayerAmountLimit ();
|
||||
uint32 QueueSize = GetQueueSize (); //number of players in the queue
|
||||
bool inQueue = false;
|
||||
//so we don't count the user trying to
|
||||
//login as a session and queue the socket that we are using
|
||||
--Sessions;
|
||||
uint32 Sessions = GetActiveAndQueuedSessionCount ();
|
||||
uint32 pLimit = GetPlayerAmountLimit ();
|
||||
uint32 QueueSize = GetQueueSize (); //number of players in the queue
|
||||
bool inQueue = false;
|
||||
//so we don't count the user trying to
|
||||
//login as a session and queue the socket that we are using
|
||||
--Sessions;
|
||||
|
||||
if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
|
||||
if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
|
||||
{
|
||||
AddQueuedPlayer (s);
|
||||
UpdateMaxSessionCounters ();
|
||||
sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
|
||||
return;
|
||||
AddQueuedPlayer (s);
|
||||
UpdateMaxSessionCounters ();
|
||||
sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
|
||||
packet << uint8 (AUTH_OK);
|
||||
packet << uint32 (0); // unknown random value...
|
||||
packet << uint8 (0);
|
||||
packet << uint32 (0);
|
||||
packet << uint8 (s->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
|
||||
s->SendPacket (&packet);
|
||||
|
||||
UpdateMaxSessionCounters ();
|
||||
WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
|
||||
packet << uint8 (AUTH_OK);
|
||||
packet << uint32 (0); // unknown random value...
|
||||
packet << uint8 (0);
|
||||
packet << uint32 (0);
|
||||
packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
|
||||
s->SendPacket (&packet);
|
||||
|
||||
// Updates the population
|
||||
if (pLimit > 0)
|
||||
UpdateMaxSessionCounters ();
|
||||
|
||||
// Updates the population
|
||||
if (pLimit > 0)
|
||||
{
|
||||
float popu = GetActiveSessionCount (); //updated number of users on the server
|
||||
popu /= pLimit;
|
||||
popu *= 2;
|
||||
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
sLog.outDetail ("Server Population (%f).", popu);
|
||||
float popu = GetActiveSessionCount (); //updated number of users on the server
|
||||
popu /= pLimit;
|
||||
popu *= 2;
|
||||
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
sLog.outDetail ("Server Population (%f).", popu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ int32 World::GetQueuePos(WorldSession* sess)
|
||||
void World::AddQueuedPlayer(WorldSession* sess)
|
||||
{
|
||||
m_QueuedPlayer.push_back (sess);
|
||||
|
||||
|
||||
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
|
||||
WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
|
||||
packet << uint8 (AUTH_WAIT_QUEUE);
|
||||
@@ -270,7 +270,7 @@ void World::AddQueuedPlayer(WorldSession* sess)
|
||||
packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
|
||||
packet << uint32(GetQueuePos (sess));
|
||||
sess->SendPacket (&packet);
|
||||
|
||||
|
||||
//sess->SendAuthWaitQue (GetQueuePos (sess));
|
||||
}
|
||||
|
||||
@@ -2282,32 +2282,32 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura
|
||||
QueryResult *resultAccounts = NULL; //used for kicking
|
||||
|
||||
///- Update the database with ban information
|
||||
switch(mode)
|
||||
switch(mode)
|
||||
{
|
||||
case BAN_IP:
|
||||
//No SQL injection as strings are escaped
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
|
||||
loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
|
||||
break;
|
||||
case BAN_ACCOUNT:
|
||||
//No SQL injection as string is escaped
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
|
||||
break;
|
||||
case BAN_CHARACTER:
|
||||
//No SQL injection as string is escaped
|
||||
resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str());
|
||||
break;
|
||||
default:
|
||||
return BAN_SYNTAX_ERROR;
|
||||
//No SQL injection as strings are escaped
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
|
||||
loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
|
||||
break;
|
||||
case BAN_ACCOUNT:
|
||||
//No SQL injection as string is escaped
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
|
||||
break;
|
||||
case BAN_CHARACTER:
|
||||
//No SQL injection as string is escaped
|
||||
resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str());
|
||||
break;
|
||||
default:
|
||||
return BAN_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if(!resultAccounts)
|
||||
{
|
||||
if(mode==BAN_IP)
|
||||
return BAN_SUCCESS; // ip correctly banned but nobody affected (yet)
|
||||
else
|
||||
return BAN_NOTFOUND; // Nobody to ban
|
||||
}
|
||||
|
||||
if(!resultAccounts)
|
||||
{
|
||||
if(mode==BAN_IP)
|
||||
return BAN_SUCCESS;
|
||||
else
|
||||
return BAN_NOTFOUND; // Nobody to ban
|
||||
}
|
||||
|
||||
///- Disconnect all affected players (for IP it can be several)
|
||||
do
|
||||
@@ -2316,11 +2316,11 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura
|
||||
uint32 account = fieldsAccount->GetUInt32();
|
||||
|
||||
if(mode!=BAN_IP)
|
||||
{
|
||||
{
|
||||
//No SQL injection as strings are escaped
|
||||
loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
|
||||
account,duration_secs,safe_author.c_str(),reason.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (WorldSession* sess = FindSession(account))
|
||||
if(std::string(sess->GetPlayerName()) != author)
|
||||
@@ -2342,15 +2342,15 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 account=0;
|
||||
uint32 account = 0;
|
||||
if (mode == BAN_ACCOUNT)
|
||||
account = accmgr.GetId (nameOrIP);
|
||||
else if (mode == BAN_CHARACTER)
|
||||
account = objmgr.GetPlayerAccountIdByPlayerName (nameOrIP);
|
||||
|
||||
if(!account)
|
||||
if (!account)
|
||||
return false;
|
||||
|
||||
|
||||
//NO SQL injection as account is uint32
|
||||
loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account);
|
||||
}
|
||||
@@ -2433,7 +2433,7 @@ void World::ShutdownMsg(bool show, Player* player)
|
||||
uint32 msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME;
|
||||
|
||||
SendServerMessage(msgid,str.c_str(),player);
|
||||
outstring_log("Server will %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutdown"), str.c_str());
|
||||
DEBUG_LOG("Server is %s in %s",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"),str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2473,10 +2473,10 @@ void World::UpdateSessions( time_t diff )
|
||||
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;
|
||||
}
|
||||
@@ -2504,17 +2504,18 @@ void World::UpdateSessions( time_t diff )
|
||||
void World::ProcessCliCommands()
|
||||
{
|
||||
if (cliCmdQueue.empty())
|
||||
return;
|
||||
return;
|
||||
|
||||
CliCommandHolder::Print* zprint;
|
||||
|
||||
while (!cliCmdQueue.empty())
|
||||
{
|
||||
sLog.outDebug("CLI command under processing...");
|
||||
CliCommandHolder *command = cliCmdQueue.next();
|
||||
|
||||
zprint = command->m_print;
|
||||
zprint = command->m_print;
|
||||
|
||||
CliHandler(zprint).ParseCommands(command->m_command);
|
||||
CliHandler(zprint).ParseCommands(command->m_command);
|
||||
|
||||
delete command;
|
||||
}
|
||||
@@ -2622,14 +2623,14 @@ void World::UpdateMaxSessionCounters()
|
||||
|
||||
void World::LoadDBVersion()
|
||||
{
|
||||
QueryResult* result = WorldDatabase.Query("SELECT version FROM db_version LIMIT 1");
|
||||
if(result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
QueryResult* result = WorldDatabase.Query("SELECT version FROM db_version LIMIT 1");
|
||||
if(result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
m_DBVersion = fields[0].GetString();
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
m_DBVersion = "unknown world database";
|
||||
m_DBVersion = fields[0].GetString();
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
m_DBVersion = "unknown world database";
|
||||
}
|
||||
|
||||
+26
-31
@@ -10,12 +10,12 @@
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/** \file
|
||||
@@ -50,35 +50,34 @@ _player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expans
|
||||
m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)),
|
||||
_logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0)
|
||||
{
|
||||
if (sock)
|
||||
{
|
||||
m_Address = sock->GetRemoteAddress ();
|
||||
sock->AddReference ();
|
||||
}
|
||||
if (sock)
|
||||
{
|
||||
m_Address = sock->GetRemoteAddress ();
|
||||
sock->AddReference ();
|
||||
}
|
||||
}
|
||||
|
||||
/// WorldSession destructor
|
||||
WorldSession::~WorldSession()
|
||||
{
|
||||
///- unload player if not unloaded
|
||||
if(_player)
|
||||
LogoutPlayer(true);
|
||||
if (_player)
|
||||
LogoutPlayer (true);
|
||||
|
||||
/// - If have unclosed socket, close it
|
||||
if (m_Socket)
|
||||
if (m_Socket)
|
||||
{
|
||||
m_Socket->CloseSocket ();
|
||||
m_Socket->RemoveReference ();
|
||||
m_Socket = NULL;
|
||||
m_Socket->CloseSocket ();
|
||||
m_Socket->RemoveReference ();
|
||||
m_Socket = NULL;
|
||||
}
|
||||
|
||||
///- empty incoming packet queue
|
||||
while(!_recvQueue.empty())
|
||||
{
|
||||
WorldPacket *packet = _recvQueue.next();
|
||||
WorldPacket *packet = _recvQueue.next ();
|
||||
delete packet;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const
|
||||
@@ -133,10 +132,10 @@ void WorldSession::SendPacket(WorldPacket const* packet)
|
||||
sendLastPacketBytes = packet->wpos(); // wpos is real written size
|
||||
}
|
||||
|
||||
#endif // !TRINITY_DEBUG
|
||||
#endif // !MANGOS_DEBUG
|
||||
|
||||
if (m_Socket->SendPacket (*packet) == -1)
|
||||
m_Socket->CloseSocket ();
|
||||
if (m_Socket->SendPacket (*packet) == -1)
|
||||
m_Socket->CloseSocket ();
|
||||
}
|
||||
|
||||
/// Add an incoming packet to the queue
|
||||
@@ -157,12 +156,12 @@ void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason)
|
||||
/// Update the WorldSession (triggered by World update)
|
||||
bool WorldSession::Update(uint32 /*diff*/)
|
||||
{
|
||||
if (m_Socket && m_Socket->IsClosed ())
|
||||
{
|
||||
if (m_Socket && m_Socket->IsClosed ())
|
||||
{
|
||||
m_Socket->RemoveReference ();
|
||||
m_Socket = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WorldPacket *packet;
|
||||
|
||||
///- Retrieve packets from the receive queue and call the appropriate handlers
|
||||
@@ -247,7 +246,7 @@ void WorldSession::LogoutPlayer(bool Save)
|
||||
{
|
||||
if (uint64 lguid = GetPlayer()->GetLootGUID())
|
||||
DoLootRelease(lguid);
|
||||
|
||||
|
||||
///- If the player just died before logging out, make him appear as a ghost
|
||||
//FIXME: logout must be delayed in case lost connection with client in time of combat
|
||||
if (_player->GetDeathTimer())
|
||||
@@ -284,7 +283,7 @@ void WorldSession::LogoutPlayer(bool Save)
|
||||
|
||||
// give honor to all attackers from set like group case
|
||||
for(std::set<Player*>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr)
|
||||
(*itr)->RewardHonor(_player, aset.size(), -1, true);
|
||||
(*itr)->RewardHonor(_player,aset.size());
|
||||
|
||||
// give bg rewards and update counters like kill by first from attackers
|
||||
// this can't be called for all attackers.
|
||||
@@ -402,7 +401,7 @@ void WorldSession::LogoutPlayer(bool Save)
|
||||
///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline
|
||||
//No SQL injection as AccountId is uint32
|
||||
CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'",
|
||||
GetAccountId());
|
||||
GetAccountId());
|
||||
sLog.outDebug( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" );
|
||||
}
|
||||
|
||||
@@ -414,8 +413,8 @@ void WorldSession::LogoutPlayer(bool Save)
|
||||
/// Kick a player out of the World
|
||||
void WorldSession::KickPlayer()
|
||||
{
|
||||
if (m_Socket)
|
||||
m_Socket->CloseSocket ();
|
||||
if (m_Socket)
|
||||
m_Socket->CloseSocket ();
|
||||
}
|
||||
|
||||
/// Cancel channeling handler
|
||||
@@ -521,7 +520,3 @@ void WorldSession::SendAuthWaitQue(uint32 position)
|
||||
SendPacket(&packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+650
-694
File diff suppressed because it is too large
Load Diff
+131
-131
@@ -10,12 +10,12 @@
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/** \addtogroup u2w User to World Communication
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#ifndef _WORLDSOCKET_H
|
||||
#define _WORLDSOCKET_H
|
||||
#define _WORLDSOCKET_H
|
||||
|
||||
#include <ace/Basic_Types.h>
|
||||
#include <ace/Synch_Traits.h>
|
||||
@@ -43,7 +43,7 @@
|
||||
#endif /* ACE_LACKS_PRAGMA_ONCE */
|
||||
|
||||
#include "Common.h"
|
||||
#include "Auth/AuthCrypt.h"
|
||||
#include "Auth/AuthCrypt.h"
|
||||
|
||||
class ACE_Message_Block;
|
||||
class WorldPacket;
|
||||
@@ -54,182 +54,182 @@ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> WorldHandler;
|
||||
|
||||
/**
|
||||
* WorldSocket.
|
||||
*
|
||||
* This class is responsible for the comunication with
|
||||
*
|
||||
* This class is responsible for the comunication with
|
||||
* remote clients.
|
||||
* Most methods return -1 on failure.
|
||||
* Most methods return -1 on failure.
|
||||
* The class uses refferece counting.
|
||||
*
|
||||
* For output the class uses one buffer (64K usually) and
|
||||
* a queue where it stores packet if there is no place on
|
||||
* the queue. The reason this is done, is because the server
|
||||
* does realy a lot of small-size writes to it, and it doesn't
|
||||
* scale well to allocate memory for every. When something is
|
||||
* writen to the output buffer the socket is not immideately
|
||||
* activated for output (again for the same reason), there
|
||||
* is 10ms celling (thats why there is Update() method).
|
||||
* This concept is simmilar to TCP_CORK, but TCP_CORK
|
||||
* usses 200ms celling. As result overhead generated by
|
||||
* sending packets from "producer" threads is minimal,
|
||||
* For output the class uses one buffer (64K usually) and
|
||||
* a queue where it stores packet if there is no place on
|
||||
* the queue. The reason this is done, is because the server
|
||||
* does realy a lot of small-size writes to it, and it doesn't
|
||||
* scale well to allocate memory for every. When something is
|
||||
* writen to the output buffer the socket is not immideately
|
||||
* activated for output (again for the same reason), there
|
||||
* is 10ms celling (thats why there is Update() method).
|
||||
* This concept is simmilar to TCP_CORK, but TCP_CORK
|
||||
* usses 200ms celling. As result overhead generated by
|
||||
* sending packets from "producer" threads is minimal,
|
||||
* and doing a lot of writes with small size is tollerated.
|
||||
*
|
||||
*
|
||||
* The calls to Upate () method are managed by WorldSocketMgr
|
||||
* and ReactorRunnable.
|
||||
*
|
||||
* For input ,the class uses one 1024 bytes buffer on stack
|
||||
* to which it does recv() calls. And then recieved data is
|
||||
* distributed where its needed. 1024 matches pritey well the
|
||||
*
|
||||
* For input ,the class uses one 1024 bytes buffer on stack
|
||||
* to which it does recv() calls. And then recieved data is
|
||||
* distributed where its needed. 1024 matches pritey well the
|
||||
* traffic generated by client for now.
|
||||
*
|
||||
* The input/output do speculative reads/writes (AKA it tryes
|
||||
* to read all data avaible in the kernel buffer or tryes to
|
||||
* write everything avaible in userspace buffer),
|
||||
* which is ok for using with Level and Edge Trigered IO
|
||||
*
|
||||
* The input/output do speculative reads/writes (AKA it tryes
|
||||
* to read all data avaible in the kernel buffer or tryes to
|
||||
* write everything avaible in userspace buffer),
|
||||
* which is ok for using with Level and Edge Trigered IO
|
||||
* notification.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class WorldSocket : protected WorldHandler
|
||||
{
|
||||
public:
|
||||
/// Declare some friends
|
||||
friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >;
|
||||
friend class WorldSocketMgr;
|
||||
friend class ReactorRunnable;
|
||||
public:
|
||||
/// Declare some friends
|
||||
friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >;
|
||||
friend class WorldSocketMgr;
|
||||
friend class ReactorRunnable;
|
||||
|
||||
/// Declare the acceptor for this class
|
||||
typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor;
|
||||
/// Declare the acceptor for this class
|
||||
typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor;
|
||||
|
||||
/// Mutex type used for various syncronizations.
|
||||
typedef ACE_Thread_Mutex LockType;
|
||||
typedef ACE_Guard<LockType> GuardType;
|
||||
/// Mutex type used for various syncronizations.
|
||||
typedef ACE_Thread_Mutex LockType;
|
||||
typedef ACE_Guard<LockType> GuardType;
|
||||
|
||||
/// Queue for storing packets for which there is no space.
|
||||
typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT;
|
||||
/// Queue for storing packets for which there is no space.
|
||||
typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT;
|
||||
|
||||
/// Check if socket is closed.
|
||||
bool IsClosed (void) const;
|
||||
/// Check if socket is closed.
|
||||
bool IsClosed (void) const;
|
||||
|
||||
/// Close the socket.
|
||||
void CloseSocket (void);
|
||||
/// Close the socket.
|
||||
void CloseSocket (void);
|
||||
|
||||
/// Get address of connected peer.
|
||||
const std::string& GetRemoteAddress (void) const;
|
||||
/// Get address of connected peer.
|
||||
const std::string& GetRemoteAddress (void) const;
|
||||
|
||||
/// Send A packet on the socket, this function is reentrant.
|
||||
/// @param pct packet to send
|
||||
/// @return -1 of failure
|
||||
int SendPacket (const WorldPacket& pct);
|
||||
/// Send A packet on the socket, this function is reentrant.
|
||||
/// @param pct packet to send
|
||||
/// @return -1 of failure
|
||||
int SendPacket (const WorldPacket& pct);
|
||||
|
||||
/// Add refference to this object.
|
||||
long AddReference (void);
|
||||
/// Add refference to this object.
|
||||
long AddReference (void);
|
||||
|
||||
/// Remove refference to this object.
|
||||
long RemoveReference (void);
|
||||
/// Remove refference to this object.
|
||||
long RemoveReference (void);
|
||||
|
||||
protected:
|
||||
/// things called by ACE framework.
|
||||
WorldSocket (void);
|
||||
virtual ~WorldSocket (void);
|
||||
protected:
|
||||
/// things called by ACE framework.
|
||||
WorldSocket (void);
|
||||
virtual ~WorldSocket (void);
|
||||
|
||||
/// Called on open ,the void* is the acceptor.
|
||||
virtual int open (void *);
|
||||
/// Called on open ,the void* is the acceptor.
|
||||
virtual int open (void *);
|
||||
|
||||
/// Called on failures inside of the acceptor, don't call from your code.
|
||||
virtual int close (int);
|
||||
/// Called on failures inside of the acceptor, don't call from your code.
|
||||
virtual int close (int);
|
||||
|
||||
/// Called when we can read from the socket.
|
||||
virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
|
||||
/// Called when we can read from the socket.
|
||||
virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
|
||||
|
||||
/// Called when the socket can write.
|
||||
virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE);
|
||||
/// Called when the socket can write.
|
||||
virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE);
|
||||
|
||||
/// Called when connection is closed or error happens.
|
||||
virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
|
||||
ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
|
||||
/// Called when connection is closed or error happens.
|
||||
virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
|
||||
ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
|
||||
|
||||
/// Called by WorldSocketMgr/ReactorRunnable.
|
||||
int Update (void);
|
||||
/// Called by WorldSocketMgr/ReactorRunnable.
|
||||
int Update (void);
|
||||
|
||||
private:
|
||||
/// Helper functions for processing incoming data.
|
||||
int handle_input_header (void);
|
||||
int handle_input_payload (void);
|
||||
int handle_input_missing_data (void);
|
||||
private:
|
||||
/// Helper functions for processing incoming data.
|
||||
int handle_input_header (void);
|
||||
int handle_input_payload (void);
|
||||
int handle_input_missing_data (void);
|
||||
|
||||
/// Help functions to mark/unmark the socket for output.
|
||||
/// @param g the guard is for m_OutBufferLock, the function will release it
|
||||
int cancel_wakeup_output (GuardType& g);
|
||||
int schedule_wakeup_output (GuardType& g);
|
||||
/// Help functions to mark/unmark the socket for output.
|
||||
/// @param g the guard is for m_OutBufferLock, the function will release it
|
||||
int cancel_wakeup_output (GuardType& g);
|
||||
int schedule_wakeup_output (GuardType& g);
|
||||
|
||||
/// process one incoming packet.
|
||||
/// @param new_pct received packet ,note that you need to delete it.
|
||||
int ProcessIncoming (WorldPacket* new_pct);
|
||||
/// process one incoming packet.
|
||||
/// @param new_pct received packet ,note that you need to delete it.
|
||||
int ProcessIncoming (WorldPacket* new_pct);
|
||||
|
||||
/// Called by ProcessIncoming() on CMSG_AUTH_SESSION.
|
||||
int HandleAuthSession (WorldPacket& recvPacket);
|
||||
/// Called by ProcessIncoming() on CMSG_AUTH_SESSION.
|
||||
int HandleAuthSession (WorldPacket& recvPacket);
|
||||
|
||||
/// Called by ProcessIncoming() on CMSG_PING.
|
||||
int HandlePing (WorldPacket& recvPacket);
|
||||
/// Called by ProcessIncoming() on CMSG_PING.
|
||||
int HandlePing (WorldPacket& recvPacket);
|
||||
|
||||
/// Try to write WorldPacket to m_OutBuffer ,return -1 if no space
|
||||
/// Need to be called with m_OutBufferLock lock held
|
||||
int iSendPacket (const WorldPacket& pct);
|
||||
/// Try to write WorldPacket to m_OutBuffer ,return -1 if no space
|
||||
/// Need to be called with m_OutBufferLock lock held
|
||||
int iSendPacket (const WorldPacket& pct);
|
||||
|
||||
/// Flush m_PacketQueue if there are packets in it
|
||||
/// Need to be called with m_OutBufferLock lock held
|
||||
/// @return true if it wrote to the buffer ( AKA you need
|
||||
/// to mark the socket for output ).
|
||||
bool iFlushPacketQueue ();
|
||||
/// Flush m_PacketQueue if there are packets in it
|
||||
/// Need to be called with m_OutBufferLock lock held
|
||||
/// @return true if it wrote to the buffer ( AKA you need
|
||||
/// to mark the socket for output ).
|
||||
bool iFlushPacketQueue ();
|
||||
|
||||
private:
|
||||
/// Time in which the last ping was received
|
||||
ACE_Time_Value m_LastPingTime;
|
||||
|
||||
/// Keep track of overspeed pings ,to prevent ping flood.
|
||||
uint32 m_OverSpeedPings;
|
||||
private:
|
||||
/// Time in which the last ping was received
|
||||
ACE_Time_Value m_LastPingTime;
|
||||
|
||||
/// Address of the remote peer
|
||||
std::string m_Address;
|
||||
/// Keep track of overspeed pings ,to prevent ping flood.
|
||||
uint32 m_OverSpeedPings;
|
||||
|
||||
/// Class used for managing encryption of the headers
|
||||
AuthCrypt m_Crypt;
|
||||
/// Address of the remote peer
|
||||
std::string m_Address;
|
||||
|
||||
/// Mutex lock to protect m_Session
|
||||
LockType m_SessionLock;
|
||||
/// Class used for managing encryption of the headers
|
||||
AuthCrypt m_Crypt;
|
||||
|
||||
/// Session to which recieved packets are routed
|
||||
WorldSession* m_Session;
|
||||
/// Mutex lock to protect m_Session
|
||||
LockType m_SessionLock;
|
||||
|
||||
/// here are stored the fragmens of the recieved data
|
||||
WorldPacket* m_RecvWPct;
|
||||
/// Session to which recieved packets are routed
|
||||
WorldSession* m_Session;
|
||||
|
||||
/// This block actually refers to m_RecvWPct contents,
|
||||
/// which alows easy and safe writing to it.
|
||||
/// It wont free memory when its deleted. m_RecvWPct takes care of freeing.
|
||||
ACE_Message_Block m_RecvPct;
|
||||
/// here are stored the fragmens of the recieved data
|
||||
WorldPacket* m_RecvWPct;
|
||||
|
||||
/// Fragment of the recieved header.
|
||||
ACE_Message_Block m_Header;
|
||||
/// This block actually refers to m_RecvWPct contents,
|
||||
/// which alows easy and safe writing to it.
|
||||
/// It wont free memory when its deleted. m_RecvWPct takes care of freeing.
|
||||
ACE_Message_Block m_RecvPct;
|
||||
|
||||
/// Mutex for protecting otuput related data.
|
||||
LockType m_OutBufferLock;
|
||||
/// Fragment of the recieved header.
|
||||
ACE_Message_Block m_Header;
|
||||
|
||||
/// Buffer used for writing output.
|
||||
ACE_Message_Block *m_OutBuffer;
|
||||
/// Mutex for protecting otuput related data.
|
||||
LockType m_OutBufferLock;
|
||||
|
||||
/// Size of the m_OutBuffer.
|
||||
size_t m_OutBufferSize;
|
||||
/// Buffer used for writing output.
|
||||
ACE_Message_Block *m_OutBuffer;
|
||||
|
||||
/// Here are stored packets for which there was no space on m_OutBuffer,
|
||||
/// this alows not-to kick player if its buffer is overflowed.
|
||||
PacketQueueT m_PacketQueue;
|
||||
/// Size of the m_OutBuffer.
|
||||
size_t m_OutBufferSize;
|
||||
|
||||
/// True if the socket is registered with the reactor for output
|
||||
bool m_OutActive;
|
||||
/// Here are stored packets for which there was no space on m_OutBuffer,
|
||||
/// this alows not-to kick player if its buffer is overflowed.
|
||||
PacketQueueT m_PacketQueue;
|
||||
|
||||
uint32 m_Seed;
|
||||
/// True if the socket is registered with the reactor for output
|
||||
bool m_OutActive;
|
||||
|
||||
uint32 m_Seed;
|
||||
};
|
||||
|
||||
#endif /* _WORLDSOCKET_H */
|
||||
#endif /* _WORLDSOCKET_H */
|
||||
|
||||
/// @}
|
||||
|
||||
Reference in New Issue
Block a user