diff options
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 24 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.h | 24 | ||||
-rw-r--r-- | src/server/game/Server/Packets/CharacterPackets.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Server/Packets/CharacterPackets.h | 26 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.cpp | 20 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 10 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 47 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocket.h | 2 |
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); |