feat(Core): replace ACE network with Boost.Asio (#6574)

This commit is contained in:
Kargatum
2021-07-16 15:43:56 +07:00
committed by GitHub
parent 7449496bb5
commit 8568c4fb33
64 changed files with 3242 additions and 4712 deletions

View File

@@ -8,7 +8,7 @@
\ingroup u2w
*/
#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it
#include "WorldSession.h"
#include "AccountMgr.h"
#include "BattlegroundMgr.h"
#include "Common.h"
@@ -25,6 +25,7 @@
#include "PacketUtilities.h"
#include "Pet.h"
#include "Player.h"
#include "QueryHolder.h"
#include "SavingSystem.h"
#include "ScriptMgr.h"
#include "SocialMgr.h"
@@ -34,9 +35,8 @@
#include "WardenWin.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "QueryHolder.h"
#include "zlib.h"
#include "WorldSocket.h"
#include <zlib.h>
#ifdef ELUNA
#include "LuaEngine.h"
@@ -91,7 +91,8 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
}
/// WorldSession constructor
WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, bool skipQueue, uint32 TotalTime) :
WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion,
time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, bool skipQueue, uint32 TotalTime) :
m_muteTime(mute_time),
m_timeOutTime(0),
_lastAuctionListItemsMSTime(0),
@@ -103,6 +104,7 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
_security(sec),
_skipQueue(skipQueue),
_accountId(id),
_accountName(std::move(name)),
m_expansion(expansion),
m_total_time(TotalTime),
_logoutTime(0),
@@ -125,7 +127,6 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
_warden = nullptr;
_offlineTime = 0;
_kicked = false;
_shouldSetOfflineInDB = true;
@@ -135,10 +136,9 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
if (sock)
{
m_Address = sock->GetRemoteAddress();
sock->AddReference();
m_Address = sock->GetRemoteIpAddress().to_string();
ResetTimeOutTime(false);
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId());
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
}
}
@@ -154,17 +154,10 @@ WorldSession::~WorldSession()
/// - If have unclosed socket, close it
if (m_Socket)
{
m_Socket->CloseSocket("WorldSession destructor");
m_Socket->RemoveReference();
m_Socket->CloseSocket();
m_Socket = nullptr;
}
if (_warden)
{
delete _warden;
_warden = nullptr;
}
///- empty incoming packet queue
WorldPacket* packet = nullptr;
while (_recvQueue.next(packet))
@@ -257,9 +250,7 @@ void WorldSession::SendPacket(WorldPacket const* packet)
#endif
LOG_TRACE("network.opcode", "S->C: %s %s", GetPlayerInfo().c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())).c_str());
if (m_Socket->SendPacket(*packet) == -1)
m_Socket->CloseSocket("m_Socket->SendPacket(*packet) == -1");
m_Socket->SendPacket(*packet);
}
/// Add an incoming packet to the queue
@@ -290,26 +281,28 @@ void WorldSession::LogUnprocessedTail(WorldPacket* packet)
/// Update the WorldSession (triggered by World update)
bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
if (updater.ProcessUnsafe())
{
UpdateTimeOutTime(diff);
///- Before we process anything:
/// If necessary, kick the player because the client didn't send anything for too long
/// (or they've been idling in character select)
if (sWorld->getBoolConfig(CONFIG_CLOSE_IDLE_CONNECTIONS) && IsConnectionIdle() && m_Socket)
m_Socket->CloseSocket();
/// If necessary, kick the player because the client didn't send anything for too long
/// (or they've been idling in character select)
if (sWorld->getBoolConfig(CONFIG_CLOSE_IDLE_CONNECTIONS) && IsConnectionIdle() && m_Socket)
m_Socket->CloseSocket("Client didn't send anything for too long");
}
if (updater.ProcessUnsafe())
UpdateTimeOutTime(diff);
HandleTeleportTimeout(updater.ProcessUnsafe());
uint32 _startMSTime = getMSTime();
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
WorldPacket* packet = nullptr;
//! Delete packet after processing by default
bool deletePacket = true;
WorldPacket* firstDelayedPacket = nullptr;
std::vector<WorldPacket*> requeuePackets;
uint32 processedPackets = 0;
time_t currentTime = time(nullptr);
while (m_Socket && !m_Socket->IsClosed() && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater))
while (m_Socket && _recvQueue.next(packet, updater))
{
OpcodeClient opcode = static_cast<OpcodeClient>(packet->GetOpcode());
ClientOpcodeHandler const* opHandle = opcodeTable[opcode];
@@ -412,38 +405,9 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
//Any leftover will be processed in next update
if (processedPackets > MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE)
break;
if (getMSTimeDiff(_startMSTime, getMSTime()) >= 3) // limit (by time) packets processed in one update, prevent DDoS
break;
}
if (m_Socket && !m_Socket->IsClosed())
ProcessQueryCallbacks();
if (updater.ProcessUnsafe())
{
if (m_Socket && !m_Socket->IsClosed() && _warden)
{
_warden->Update(diff);
}
time_t currTime = time(nullptr);
if (ShouldLogOut(currTime) && !m_playerLoading)
{
LogoutPlayer(true);
}
if (m_Socket && m_Socket->IsClosed())
{
m_Socket->RemoveReference();
m_Socket = nullptr;
}
if (!m_Socket)
{
return false;
}
}
_recvQueue.readd(requeuePackets.begin(), requeuePackets.end());
if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
{
@@ -461,29 +425,60 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
}
}
ProcessQueryCallbacks();
//check if we are safe to proceed with logout
//logout procedure should happen only in World::UpdateSessions() method!!!
if (updater.ProcessUnsafe())
{
if (m_Socket && m_Socket->IsOpen() && _warden)
{
_warden->Update(diff);
}
if (ShouldLogOut(currentTime) && !m_playerLoading)
{
LogoutPlayer(true);
}
if (m_Socket && !m_Socket->IsOpen())
{
if (GetPlayer() && _warden)
_warden->Update(diff);
m_Socket = nullptr;
}
if (!m_Socket)
{
return false;
}
}
return true;
}
bool WorldSession::HandleSocketClosed()
{
if (m_Socket && m_Socket->IsClosed() && !IsKicked() && GetPlayer() && !PlayerLogout() && GetPlayer()->m_taxi.empty() && GetPlayer()->IsInWorld() && !World::IsStopped())
if (m_Socket && !m_Socket->IsOpen() && !IsKicked() && GetPlayer() && !PlayerLogout() && GetPlayer()->m_taxi.empty() && GetPlayer()->IsInWorld() && !World::IsStopped())
{
m_Socket->RemoveReference();
m_Socket = nullptr;
GetPlayer()->TradeCancel(false);
return true;
}
return false;
}
bool WorldSession::IsSocketClosed() const {
return !m_Socket || m_Socket->IsClosed();
bool WorldSession::IsSocketClosed() const
{
return !m_Socket || !m_Socket->IsOpen();
}
void WorldSession::HandleTeleportTimeout(bool updateInSessions)
{
// pussywizard: handle teleport ack timeout
if (m_Socket && !m_Socket->IsClosed() && GetPlayer() && GetPlayer()->IsBeingTeleported())
if (m_Socket && m_Socket->IsOpen() && GetPlayer() && GetPlayer()->IsBeingTeleported())
{
time_t currTime = time(nullptr);
if (updateInSessions) // session update from World::UpdateSessions
@@ -681,7 +676,12 @@ void WorldSession::LogoutPlayer(bool save)
void WorldSession::KickPlayer(std::string const& reason, bool setKicked)
{
if (m_Socket)
m_Socket->CloseSocket(reason);
{
LOG_INFO("network.kick", "Account: %u Character: '%s' %s kicked with reason: %s", GetAccountId(), _player ? _player->GetName().c_str() : "<none>",
_player ? _player->GetGUID().ToString().c_str() : "", reason.c_str());
m_Socket->CloseSocket();
}
if (setKicked)
SetKicked(true); // pussywizard: the session won't be left ingame for 60 seconds and to also kick offline session
@@ -947,41 +947,41 @@ void WorldSession::ReadMovementInfo(WorldPacket& data, MovementInfo* mi)
It will freeze clients that receive this player's movement info.
*/
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
MOVEMENTFLAG_ROOT);
MOVEMENTFLAG_ROOT);
//! Cannot hover without SPELL_AURA_HOVER
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
MOVEMENTFLAG_HOVER);
MOVEMENTFLAG_HOVER);
//! Cannot ascend and descend at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
//! Cannot move left and right at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
//! Cannot strafe left and right at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
//! Cannot pitch up and down at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
//! Cannot move forwards and backwards at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
//! Cannot walk on water without SPELL_AURA_WATER_WALK
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) &&
!GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK) &&
!GetPlayer()->HasAuraType(SPELL_AURA_GHOST),
MOVEMENTFLAG_WATERWALKING);
!GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK) &&
!GetPlayer()->HasAuraType(SPELL_AURA_GHOST),
MOVEMENTFLAG_WATERWALKING);
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL),
MOVEMENTFLAG_FALLING_SLOW);
MOVEMENTFLAG_FALLING_SLOW);
/*! Cannot fly if no fly auras present. Exception is being a GM.
Note that we check for account level instead of Player::IsGameMaster() because in some
@@ -990,14 +990,14 @@ void WorldSession::ReadMovementInfo(WorldPacket& data, MovementInfo* mi)
*/
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
//! Cannot fly and fall at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING),
MOVEMENTFLAG_FALLING);
MOVEMENTFLAG_FALLING);
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED) &&
(!GetPlayer()->movespline->Initialized() || GetPlayer()->movespline->Finalized()), MOVEMENTFLAG_SPLINE_ENABLED);
(!GetPlayer()->movespline->Initialized() || GetPlayer()->movespline->Finalized()), MOVEMENTFLAG_SPLINE_ENABLED);
#undef REMOVE_VIOLATING_FLAGS
}
@@ -1040,7 +1040,7 @@ void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)
*data << mi->splineElevation;
}
void WorldSession::ReadAddonsInfo(WorldPacket& data)
void WorldSession::ReadAddonsInfo(ByteBuffer& data)
{
if (data.rpos() + 4 > data.size())
return;
@@ -1218,7 +1218,7 @@ void WorldSession::InitWarden(SessionKey const& k, std::string const& os)
{
if (os == "Win")
{
_warden = new WardenWin();
_warden = std::make_unique<WardenWin>();
_warden->Init(this, k);
}
else if (os == "OSX")
@@ -1533,6 +1533,9 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
return maxPacketCounterAllowed;
}
WorldSession::DosProtection::DosProtection(WorldSession* s) :
Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) { }
void WorldSession::ResetTimeSync()
{
_timeSyncNextCounter = 0;