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:
Shauren
2015-02-23 22:35:26 +01:00
parent 880be1bc63
commit 3fcea2e9d4
10 changed files with 154 additions and 15 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
};
}
}

View File

@@ -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);

View File

@@ -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:

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);