aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp24
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp6
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.h24
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp6
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.h26
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp4
-rw-r--r--src/server/game/Server/WorldSession.cpp20
-rw-r--r--src/server/game/Server/WorldSession.h10
-rw-r--r--src/server/game/Server/WorldSocket.cpp47
-rw-r--r--src/server/game/Server/WorldSocket.h2
10 files changed, 154 insertions, 15 deletions
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 0385b8f1a39..4333ec5ba1e 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -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
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp
index 97f68e676a6..14f5de79e2c 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.cpp
+++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp
@@ -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;
+}
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h
index 09b528910cd..ecb6061db2c 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.h
+++ b/src/server/game/Server/Packets/AuthenticationPackets.h
@@ -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;
+ };
}
}
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index 0eabb1ee351..f69cdee736c 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -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);
diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h
index 7784ffee417..b398af0b04b 100644
--- a/src/server/game/Server/Packets/CharacterPackets.h
+++ b/src/server/game/Server/Packets/CharacterPackets.h
@@ -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:
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 08c17622bf8..3bc5526f36b 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -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);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index c4794b9050a..727d1e078e4 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -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"
@@ -184,8 +185,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() << ")]";
@@ -695,6 +698,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);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 0cab4b9bf7a..9c3daa319f8 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -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);
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 9b485462ad4..9783f7ae0ff 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -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;
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 94662a616b1..a0304468682 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -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);