Core/NetworkIO: implement 2nd connection

This commit is contained in:
Ovahlord committed 2019-10-03 22:32:24 +02:00
1 parent 0299e10945
commit 8bec6af24a
28 files changed
+2049 -1000

No files matched your search

+96 -38
View File
@@ -23,6 +23,7 @@
#include "WorldSession.h"
#include "AccountMgr.h"
#include "AddonMgr.h"
#include "AuthenticationPackets.h"
#include "BattlegroundMgr.h"
#include "BattlenetServerManager.h"
#include "Common.h"
@@ -110,7 +111,6 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
AntiDOS(this),
m_GUIDLow(0),
_player(nullptr),
m_Socket(sock),
_security(sec),
_accountId(id),
_accountName(std::move(name)),
@@ -119,7 +119,6 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
_warden(nullptr),
_logoutTime(0),
m_inQueue(false),
m_playerLoading(false),
m_playerLogout(false),
m_playerRecentlyLogout(false),
m_playerSave(false),
@@ -150,15 +149,8 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
}
_compressionStream = new z_stream();
_compressionStream->zalloc = (alloc_func)nullptr;
_compressionStream->zfree = (free_func)nullptr;
_compressionStream->opaque = (voidpf)nullptr;
_compressionStream->avail_in = 0;
_compressionStream->next_in = nullptr;
int32 z_res = deflateInit(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION));
if (z_res != Z_OK)
TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
m_Socket[CONNECTION_TYPE_REALM] = sock;
_instanceConnectKey.Raw = UI64LIT(0);
}
/// WorldSession destructor
@@ -166,13 +158,16 @@ WorldSession::~WorldSession()
{
///- unload player if not unloaded
if (_player)
LogoutPlayer (true);
LogoutPlayer(true);
/// - If have unclosed socket, close it
if (m_Socket)
for (uint8 i = 0; i < 2; ++i)
{
m_Socket->CloseSocket();
m_Socket = nullptr;
if (m_Socket[i])
{
m_Socket[i]->CloseSocket();
m_Socket[i].reset();
}
}
delete _warden;
@@ -184,12 +179,12 @@ WorldSession::~WorldSession()
delete packet;
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query
}
int32 z_res = deflateEnd(_compressionStream);
if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY
TC_LOG_ERROR("network", "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
delete _compressionStream;
bool WorldSession::PlayerDisconnected() const
{
return !(m_Socket[CONNECTION_TYPE_REALM] && m_Socket[CONNECTION_TYPE_REALM]->IsOpen() &&
m_Socket[CONNECTION_TYPE_INSTANCE] && m_Socket[CONNECTION_TYPE_INSTANCE]->IsOpen());
}
std::string const & WorldSession::GetPlayerName() const
@@ -219,9 +214,6 @@ ObjectGuid::LowType WorldSession::GetGUIDLow() const
/// Send a packet to the client
void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/)
{
if (!m_Socket)
return;
if (packet->GetOpcode() == NULL_OPCODE)
{
TC_LOG_ERROR("network.opcode", "Prevented sending of NULL_OPCODE to %s", GetPlayerInfo().c_str());
@@ -233,12 +225,41 @@ void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/
return;
}
ServerOpcodeHandler const* handler = opcodeTable[static_cast<OpcodeServer>(packet->GetOpcode())];
if (!handler)
{
TC_LOG_ERROR("network.opcode", "Prevented sending of opcode %u with non existing handler to %s", packet->GetOpcode(), GetPlayerInfo().c_str());
return;
}
// Default connection index defined in Opcodes.cpp table
ConnectionType conIdx = handler->ConnectionIndex;
// Override connection index
if (packet->GetConnection() != CONNECTION_TYPE_DEFAULT)
{
if (packet->GetConnection() != CONNECTION_TYPE_INSTANCE && IsInstanceOnlyOpcode(packet->GetOpcode()))
{
TC_LOG_ERROR("network.opcode", "Prevented sending of instance only opcode %u with connection type %u to %s", packet->GetOpcode(), packet->GetConnection(), GetPlayerInfo().c_str());
return;
}
conIdx = packet->GetConnection();
}
if (!m_Socket[conIdx])
{
TC_LOG_ERROR("network.opcode", "Prevented sending of %s to non existent socket %u to %s", GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())).c_str(), conIdx, GetPlayerInfo().c_str());
return;
}
if (!forced)
{
OpcodeHandler const* handler = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
OpcodeHandler const* handler = opcodeTable[static_cast<OpcodeServer>(packet->GetOpcode())];
if (!handler || handler->Status == STATUS_UNHANDLED)
{
TC_LOG_ERROR("network.opcode", "Prevented sending disabled opcode %s to %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str(), GetPlayerInfo().c_str());
TC_LOG_ERROR("network.opcode", "Prevented sending disabled opcode %s to %s", GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())).c_str(), GetPlayerInfo().c_str());
return;
}
}
@@ -280,7 +301,7 @@ void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/
sScriptMgr->OnPacketSend(this, *packet);
TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetPlayerInfo().c_str(), GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str());
m_Socket->SendPacket(*packet);
m_Socket[conIdx]->SendPacket(*packet);
}
/// Add an incoming packet to the queue
@@ -316,7 +337,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Before we process anything:
/// If necessary, kick the player from the character select screen
if (IsConnectionIdle() && !HasPermission(rbac::RBAC_PERM_IGNORE_IDLE_CONNECTION))
m_Socket->CloseSocket();
m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
@@ -327,7 +348,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
uint32 processedPackets = 0;
time_t currentTime = time(nullptr);
while (m_Socket && _recvQueue.next(packet, updater))
while (m_Socket[CONNECTION_TYPE_REALM] && _recvQueue.next(packet, updater))
{
ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
try
@@ -440,7 +461,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
_recvQueue.readd(requeuePackets.begin(), requeuePackets.end());
if (m_Socket && m_Socket->IsOpen() && _warden)
if (m_Socket[0] && m_Socket[0]->IsOpen() && _warden)
_warden->Update();
if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
@@ -463,23 +484,32 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
time_t currTime = time(nullptr);
///- If necessary, log the player out
if (ShouldLogOut(currTime) && !m_playerLoading)
if (ShouldLogOut(currTime) && m_playerLoading.IsEmpty())
LogoutPlayer(true);
if (m_Socket && GetPlayer() && _warden)
if (m_Socket[CONNECTION_TYPE_REALM] && GetPlayer() && _warden)
_warden->Update();
///- Cleanup socket pointer if need
if (m_Socket && !m_Socket->IsOpen())
if ((m_Socket[0] && !m_Socket[0]->IsOpen()) || (m_Socket[1] && !m_Socket[1]->IsOpen()))
{
expireTime -= expireTime > diff ? diff : expireTime;
if (expireTime < diff || forceExit || !GetPlayer())
{
m_Socket = nullptr;
if (m_Socket[CONNECTION_TYPE_REALM])
{
m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
m_Socket[CONNECTION_TYPE_REALM].reset();
}
if (m_Socket[CONNECTION_TYPE_INSTANCE])
{
m_Socket[CONNECTION_TYPE_INSTANCE]->CloseSocket();
m_Socket[CONNECTION_TYPE_INSTANCE].reset();
}
}
}
if (!m_Socket)
if (!m_Socket[CONNECTION_TYPE_REALM])
return false; //Will remove this session from the world session map
}
@@ -589,7 +619,7 @@ void WorldSession::LogoutPlayer(bool save)
// remove player from the group if he is:
// a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket[CONNECTION_TYPE_REALM])
_player->RemoveFromGroup();
//! Send update to group and reset stored max enchanting level
@@ -635,6 +665,12 @@ void WorldSession::LogoutPlayer(bool save)
CharacterDatabase.Execute(stmt);
}
if (m_Socket[CONNECTION_TYPE_INSTANCE])
{
m_Socket[CONNECTION_TYPE_INSTANCE]->CloseSocket();
m_Socket[CONNECTION_TYPE_INSTANCE].reset();
}
m_playerLogout = false;
m_playerSave = false;
m_playerRecentlyLogout = true;
@@ -644,10 +680,13 @@ void WorldSession::LogoutPlayer(bool save)
/// Kick a player out of the World
void WorldSession::KickPlayer()
{
if (m_Socket)
for (uint8 i = 0; i < 2; ++i)
{
m_Socket->CloseSocket();
forceExit = true;
if (m_Socket[i])
{
m_Socket[i]->CloseSocket();
forceExit = true;
}
}
}
@@ -726,6 +765,25 @@ void WorldSession::Handle_Deprecated(WorldPacket& recvPacket)
, GetOpcodeNameForLogging(static_cast<OpcodeClient>(recvPacket.GetOpcode())).c_str(), GetPlayerInfo().c_str());
}
void WorldSession::SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial)
{
boost::system::error_code ignored_error;
boost::asio::ip::tcp::endpoint instanceAddress = realm.GetAddressForClient(boost::asio::ip::make_address(GetRemoteAddress(), ignored_error));
instanceAddress.port(sWorld->getIntConfig(CONFIG_PORT_INSTANCE));
_instanceConnectKey.Fields.AccountId = GetAccountId();
_instanceConnectKey.Fields.ConnectionType = CONNECTION_TYPE_INSTANCE;
_instanceConnectKey.Fields.Key = urand(0, 0x7FFFFFFF);
WorldPackets::Auth::ConnectTo connectTo;
connectTo.Key = _instanceConnectKey.Raw;
connectTo.Serial = serial;
connectTo.Payload.Where = instanceAddress;
connectTo.Con = CONNECTION_TYPE_INSTANCE;
SendPacket(connectTo.Write());
}
void WorldSession::SendAuthWaitQue(uint32 position)
{
if (position == 0)