mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 02:25:38 +01:00
Core/PacketIO: Handle ConnectToFailed and allow the client to reconnect up to 5 times before aborting login to world
Closes #14214
This commit is contained in:
@@ -794,17 +794,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin&
|
||||
return;
|
||||
}
|
||||
|
||||
boost::system::error_code ignored_error;
|
||||
boost::asio::ip::tcp::endpoint instanceAddress = realm.GetAddressForClient(boost::asio::ip::address::from_string(GetRemoteAddress(), ignored_error));
|
||||
instanceAddress.port(sWorld->getIntConfig(CONFIG_PORT_INSTANCE));
|
||||
|
||||
WorldPackets::Auth::ConnectTo connectTo;
|
||||
connectTo.Key = MAKE_PAIR64(GetAccountId(), CONNECTION_TYPE_INSTANCE);
|
||||
connectTo.Serial = 1;
|
||||
connectTo.Payload.Where = instanceAddress;
|
||||
connectTo.Con = CONNECTION_TYPE_INSTANCE;
|
||||
|
||||
SendPacket(connectTo.Write());
|
||||
SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt1);
|
||||
}
|
||||
|
||||
void WorldSession::HandleContinuePlayerLogin()
|
||||
@@ -826,6 +816,18 @@ void WorldSession::HandleContinuePlayerLogin()
|
||||
_charLoginCallback = CharacterDatabase.DelayQueryHolder(holder);
|
||||
}
|
||||
|
||||
void WorldSession::AbortLogin(WorldPackets::Character::LoginFailureReason reason)
|
||||
{
|
||||
if (!PlayerLoading() || GetPlayer())
|
||||
{
|
||||
KickPlayer();
|
||||
return;
|
||||
}
|
||||
|
||||
m_playerLoading.Clear();
|
||||
SendPacket(WorldPackets::Character::CharacterLoginFailed(reason).Write());
|
||||
}
|
||||
|
||||
void WorldSession::HandleLoadScreenOpcode(WorldPackets::Character::LoadingScreenNotify& /*loadingScreenNotify*/)
|
||||
{
|
||||
// TODO: Do something with this packet
|
||||
|
||||
@@ -592,3 +592,9 @@ void WorldPackets::Auth::AuthContinuedSession::Read()
|
||||
_worldPacket >> Key;
|
||||
_worldPacket.read(Digest, SHA_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
void WorldPackets::Auth::ConnectToFailed::Read()
|
||||
{
|
||||
_worldPacket >> Serial;
|
||||
_worldPacket >> Con;
|
||||
}
|
||||
|
||||
@@ -138,6 +138,17 @@ namespace WorldPackets
|
||||
uint8 Result = 0; ///< the result of the authentication process, it is AUTH_OK if it succeeded and the account is ready to log in. It can also be AUTH_WAIT_QUEUE if the account entered the login queue (Queued, QueuePos), possible values are @ref ResponseCodes
|
||||
};
|
||||
|
||||
enum class ConnectToSerial : uint32
|
||||
{
|
||||
None = 0,
|
||||
Realm = 14,
|
||||
WorldAttempt1 = 17,
|
||||
WorldAttempt2 = 35,
|
||||
WorldAttempt3 = 53,
|
||||
WorldAttempt4 = 71,
|
||||
WorldAttempt5 = 89
|
||||
};
|
||||
|
||||
class ConnectTo final : public ServerPacket
|
||||
{
|
||||
static std::string const Haiku;
|
||||
@@ -157,7 +168,7 @@ namespace WorldPackets
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint64 Key = 0;
|
||||
uint32 Serial = 0;
|
||||
ConnectToSerial Serial = ConnectToSerial::None;
|
||||
ConnectPayload Payload;
|
||||
uint8 Con = 0;
|
||||
|
||||
@@ -191,6 +202,17 @@ namespace WorldPackets
|
||||
|
||||
WorldPacket const* Write() override { return &_worldPacket; }
|
||||
};
|
||||
|
||||
class ConnectToFailed final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
ConnectToFailed(WorldPacket&& packet) : ClientPacket(CMSG_CONNECT_TO_FAILED, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint32 Serial = 0;
|
||||
uint8 Con = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -357,6 +357,12 @@ WorldPacket const* WorldPackets::Character::LoginVerifyWorld::Write()
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Character::CharacterLoginFailed::Write()
|
||||
{
|
||||
_worldPacket << uint8(Code);
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Character::LogoutResponse::Write()
|
||||
{
|
||||
_worldPacket << int32(LogoutResult);
|
||||
|
||||
@@ -429,6 +429,32 @@ namespace WorldPackets
|
||||
uint32 Reason = 0;
|
||||
};
|
||||
|
||||
enum class LoginFailureReason : uint8
|
||||
{
|
||||
Failed = 0,
|
||||
NoWorld = 1,
|
||||
DuplicateCharacter = 2,
|
||||
NoInstances = 3,
|
||||
Disabled = 4,
|
||||
NoCharacter = 5,
|
||||
LockedForTransfer = 6,
|
||||
LockedByBilling = 7,
|
||||
LockedByMobileAH = 8,
|
||||
TemporaryGMLock = 9,
|
||||
LockedByCharacterUpgrade = 10,
|
||||
LockedByRevokedCharacterUpgrade = 11
|
||||
};
|
||||
|
||||
class CharacterLoginFailed final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
CharacterLoginFailed(LoginFailureReason code) : ServerPacket(SMSG_CHARACTER_LOGIN_FAILED, 1), Code(code) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
LoginFailureReason Code = LoginFailureReason::Failed;
|
||||
};
|
||||
|
||||
class LogoutRequest final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -318,7 +318,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_COMPLETE_CINEMATIC, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_COMPLETE_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_CONFIRM_RESPEC_WIPE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleConfirmRespecWipeOpcode );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_CONNECT_TO_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_CONVERSATION_UNK1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_CONVERT_RAID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_CREATE_SHIPMENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
@@ -1094,7 +1094,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY_LEFT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_OBJECT_TEST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_COMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_SPELL_TIER_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "WardenWin.h"
|
||||
#include "WardenMac.h"
|
||||
#include "BattlenetServerManager.h"
|
||||
#include "AuthenticationPackets.h"
|
||||
#include "CharacterPackets.h"
|
||||
#include "ClientConfigPackets.h"
|
||||
#include "MiscPackets.h"
|
||||
@@ -183,8 +184,10 @@ std::string WorldSession::GetPlayerInfo() const
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << "[Player: " << GetPlayerName() << " (";
|
||||
if (_player != NULL)
|
||||
if (_player)
|
||||
ss << _player->GetGUID().ToString() << ", ";
|
||||
else if (!m_playerLoading.IsEmpty())
|
||||
ss << "Logging in: " << m_playerLoading.ToString() << ", ";
|
||||
|
||||
ss << "Account: " << GetAccountId() << ")]";
|
||||
|
||||
@@ -704,6 +707,21 @@ void WorldSession::Handle_ServerSide(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::address::from_string(GetRemoteAddress(), ignored_error));
|
||||
instanceAddress.port(sWorld->getIntConfig(CONFIG_PORT_INSTANCE));
|
||||
|
||||
WorldPackets::Auth::ConnectTo connectTo;
|
||||
connectTo.Key = MAKE_PAIR64(GetAccountId(), CONNECTION_TYPE_INSTANCE);
|
||||
connectTo.Serial = serial;
|
||||
connectTo.Payload.Where = instanceAddress;
|
||||
connectTo.Con = CONNECTION_TYPE_INSTANCE;
|
||||
|
||||
SendPacket(connectTo.Write());
|
||||
}
|
||||
|
||||
void WorldSession::LoadGlobalAccountData()
|
||||
{
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA);
|
||||
|
||||
@@ -85,6 +85,11 @@ namespace WorldPackets
|
||||
class AuctionHelloRequest;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
{
|
||||
enum class ConnectToSerial : uint32;
|
||||
}
|
||||
|
||||
namespace BlackMarket
|
||||
{
|
||||
class BlackMarketOpen;
|
||||
@@ -113,6 +118,8 @@ namespace WorldPackets
|
||||
class LogoutCancel;
|
||||
class LoadingScreenNotify;
|
||||
class SetActionBarToggles;
|
||||
|
||||
enum class LoginFailureReason : uint8;
|
||||
}
|
||||
|
||||
namespace ClientConfig
|
||||
@@ -746,7 +753,10 @@ class WorldSession
|
||||
void HandleCharCreateOpcode(WorldPackets::Character::CreateChar& charCreate);
|
||||
void HandleCharCreateCallback(PreparedQueryResult result, WorldPackets::Character::CharacterCreateInfo* createInfo);
|
||||
void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& playerLogin);
|
||||
|
||||
void SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial);
|
||||
void HandleContinuePlayerLogin();
|
||||
void AbortLogin(WorldPackets::Character::LoginFailureReason reason);
|
||||
void HandleLoadScreenOpcode(WorldPackets::Character::LoadingScreenNotify& loadingScreenNotify);
|
||||
void HandlePlayerLogin(LoginQueryHolder * holder);
|
||||
void HandleCharRenameOpcode(WorldPackets::Character::CharacterRenameRequest& request);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "WorldSocket.h"
|
||||
#include "AuthenticationPackets.h"
|
||||
#include "BigNumber.h"
|
||||
#include "CharacterPackets.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
@@ -268,6 +269,13 @@ bool WorldSocket::ReadDataHandler()
|
||||
_worldSession->HandleEnableNagleAlgorithm();
|
||||
break;
|
||||
}
|
||||
case CMSG_CONNECT_TO_FAILED:
|
||||
{
|
||||
WorldPackets::Auth::ConnectToFailed connectToFailed(std::move(packet));
|
||||
connectToFailed.Read();
|
||||
HandleConnectToFailed(connectToFailed);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (!_worldSession)
|
||||
@@ -716,6 +724,45 @@ void WorldSocket::HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSe
|
||||
_worldSession->HandleContinuePlayerLogin();
|
||||
}
|
||||
|
||||
void WorldSocket::HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed)
|
||||
{
|
||||
if (_worldSession)
|
||||
{
|
||||
if (_worldSession->PlayerLoading())
|
||||
{
|
||||
switch (connectToFailed.Serial)
|
||||
{
|
||||
case WorldPackets::Auth::ConnectToSerial::WorldAttempt1:
|
||||
_worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt2);
|
||||
break;
|
||||
case WorldPackets::Auth::ConnectToSerial::WorldAttempt2:
|
||||
_worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt3);
|
||||
break;
|
||||
case WorldPackets::Auth::ConnectToSerial::WorldAttempt3:
|
||||
_worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt4);
|
||||
break;
|
||||
case WorldPackets::Auth::ConnectToSerial::WorldAttempt4:
|
||||
_worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt5);
|
||||
break;
|
||||
case WorldPackets::Auth::ConnectToSerial::WorldAttempt5:
|
||||
{
|
||||
TC_LOG_ERROR("network", "%s failed to connect 5 times to world socket, aborting login", _worldSession->GetPlayerInfo().c_str());
|
||||
_worldSession->AbortLogin(WorldPackets::Character::LoginFailureReason::NoWorld);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// transfer_aborted when/if we get map node redirection
|
||||
// SendPacket(*WorldPackets::Auth::ResumeComms().Write());
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void WorldSocket::SendAuthResponseError(uint8 code)
|
||||
{
|
||||
WorldPackets::Auth::AuthResponse response;
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace WorldPackets
|
||||
{
|
||||
class AuthSession;
|
||||
class AuthContinuedSession;
|
||||
class ConnectToFailed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +97,7 @@ private:
|
||||
void HandleSendAuthSession();
|
||||
void HandleAuthSession(WorldPackets::Auth::AuthSession& authSession);
|
||||
void HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSession& authSession);
|
||||
void HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed);
|
||||
void SendAuthResponseError(uint8 code);
|
||||
|
||||
void HandlePing(WorldPacket& recvPacket);
|
||||
|
||||
Reference in New Issue
Block a user