diff options
| author | Shauren <shauren.trinity@gmail.com> | 2016-03-28 17:12:57 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2016-03-28 17:12:57 +0200 |
| commit | dde620c402daf4ea8d132fb72a77eabc22f7a6d0 (patch) | |
| tree | 7c12161d7a22915736b0c9a106de896eeb283399 /src/server/game | |
| parent | 619669c6209441fc2fb5b483d553badee8c30ad5 (diff) | |
Core: Updated to 6.2.4
* Rewrite bnetserver for new authentication protocol
Diffstat (limited to 'src/server/game')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 17 | ||||
| -rw-r--r-- | src/server/game/Handlers/BattlenetHandler.cpp | 87 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/AllPackets.h | 1 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/BattlenetPackets.cpp | 89 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/BattlenetPackets.h | 108 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/QueryPackets.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 12 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 23 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 36 | ||||
| -rw-r--r-- | src/server/game/Services/WorldserverService.cpp | 116 | ||||
| -rw-r--r-- | src/server/game/Services/WorldserverService.h | 71 | ||||
| -rw-r--r-- | src/server/game/Services/WorldserverServiceDispatcher.cpp | 49 | ||||
| -rw-r--r-- | src/server/game/Services/WorldserverServiceDispatcher.h | 67 |
13 files changed, 669 insertions, 9 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 950a1ff0841..ee63999802a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -18869,6 +18869,23 @@ void Player::SaveToDB(bool create /*=false*/) GetSession()->GetCollectionMgr()->SaveAccountToys(trans); GetSession()->GetBattlePetMgr()->SaveToDB(trans); GetSession()->GetCollectionMgr()->SaveAccountHeirlooms(trans); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS); + stmt->setUInt32(0, GetSession()->GetAccountId()); + stmt->setUInt8(1, realm.Id.Region); + stmt->setUInt8(2, realm.Id.Site); + trans->Append(stmt); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_LAST_PLAYER_CHARACTERS); + stmt->setUInt32(0, GetSession()->GetAccountId()); + stmt->setUInt8(1, realm.Id.Region); + stmt->setUInt8(2, realm.Id.Site); + stmt->setUInt32(3, realm.Id.Realm); + stmt->setString(4, GetName()); + stmt->setUInt64(5, GetGUID().GetCounter()); + stmt->setUInt32(6, time(nullptr)); + trans->Append(stmt); + LoginDatabase.CommitTransaction(trans); // save pet (hunter pet level and experience and all type pets health/mana). diff --git a/src/server/game/Handlers/BattlenetHandler.cpp b/src/server/game/Handlers/BattlenetHandler.cpp new file mode 100644 index 00000000000..1f968c3b423 --- /dev/null +++ b/src/server/game/Handlers/BattlenetHandler.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "WorldSession.h" +#include "BattlenetPackets.h" +#include "WorldserverServiceDispatcher.h" +#include "ObjectDefines.h" + +void WorldSession::HandleBattlenetRequest(WorldPackets::Battlenet::Request& request) +{ + sServiceDispatcher.Dispatch(this, request.Method.GetServiceHash(), request.Method.Token, request.Method.GetMethodId(), std::move(request.Data)); +} + +void WorldSession::HandleBattlenetRequestRealmListTicket(WorldPackets::Battlenet::RequestRealmListTicket& requestRealmListTicket) +{ + SetRealmListSecret(requestRealmListTicket.Secret); + + WorldPackets::Battlenet::RealmListTicket realmListTicket; + realmListTicket.Token = requestRealmListTicket.Token; + realmListTicket.Ticket << "WorldserverRealmListTicket"; + + SendPacket(realmListTicket.Write()); +} + +void WorldSession::SendBattlenetResponse(uint32 serviceHash, uint32 methodId, uint32 token, pb::Message const* response) +{ + WorldPackets::Battlenet::Response bnetResponse; + bnetResponse.BnetStatus = ERROR_OK; + bnetResponse.Method.Type = MAKE_PAIR64(methodId, serviceHash); + bnetResponse.Method.ObjectId = 1; + bnetResponse.Method.Token = token; + + if (response->ByteSize()) + { + bnetResponse.Data.resize(response->ByteSize()); + response->SerializePartialToArray(bnetResponse.Data.contents(), response->ByteSize()); + } + + SendPacket(bnetResponse.Write()); +} + +void WorldSession::SendBattlenetResponse(uint32 serviceHash, uint32 methodId, uint32 token, uint32 status) +{ + WorldPackets::Battlenet::Response bnetResponse; + bnetResponse.BnetStatus = BattlenetRpcErrorCode(status); + bnetResponse.Method.Type = MAKE_PAIR64(methodId, serviceHash); + bnetResponse.Method.ObjectId = 1; + bnetResponse.Method.Token = token; + + SendPacket(bnetResponse.Write()); +} + +void WorldSession::SendBattlenetRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request, std::function<void(MessageBuffer)> callback) +{ + _battlenetResponseCallbacks[_battlenetRequestToken] = std::move(callback); + SendBattlenetRequest(serviceHash, methodId, request); +} + +void WorldSession::SendBattlenetRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request) +{ + WorldPackets::Battlenet::Notification notification; + notification.Method.Type = MAKE_PAIR64(methodId, serviceHash); + notification.Method.ObjectId = 1; + notification.Method.Token = _battlenetRequestToken++; + + if (request->ByteSize()) + { + notification.Data.resize(request->ByteSize()); + request->SerializePartialToArray(notification.Data.contents(), request->ByteSize()); + } + + SendPacket(notification.Write()); +} diff --git a/src/server/game/Server/Packets/AllPackets.h b/src/server/game/Server/Packets/AllPackets.h index 60dd2493b12..0d6d28446bc 100644 --- a/src/server/game/Server/Packets/AllPackets.h +++ b/src/server/game/Server/Packets/AllPackets.h @@ -24,6 +24,7 @@ #include "BankPackets.h" #include "BattlefieldPackets.h" #include "BattlegroundPackets.h" +#include "BattlenetPackets.h" #include "BattlePetPackets.h" #include "BlackMarketPackets.h" #include "CalendarPackets.h" diff --git a/src/server/game/Server/Packets/BattlenetPackets.cpp b/src/server/game/Server/Packets/BattlenetPackets.cpp new file mode 100644 index 00000000000..de3d6ab3010 --- /dev/null +++ b/src/server/game/Server/Packets/BattlenetPackets.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "BattlenetPackets.h" + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Battlenet::MethodCall const& method) +{ + data << uint64(method.Type); + data << uint64(method.ObjectId); + data << uint32(method.Token); + return data; +} + +ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Battlenet::MethodCall& method) +{ + data >> method.Type; + data >> method.ObjectId; + data >> method.Token; + return data; +} + +WorldPacket const* WorldPackets::Battlenet::Notification::Write() +{ + _worldPacket << Method; + _worldPacket << uint32(Data.size()); + _worldPacket.append(Data); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Battlenet::Response::Write() +{ + _worldPacket << uint32(BnetStatus); + _worldPacket << Method; + _worldPacket << uint32(Data.size()); + _worldPacket.append(Data); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Battlenet::SetSessionState::Write() +{ + _worldPacket.WriteBits(State, 2); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Battlenet::RealmListTicket::Write() +{ + _worldPacket << uint32(Token); + _worldPacket.WriteBit(Allow); + _worldPacket << uint32(Ticket.size()); + _worldPacket.append(Ticket); + + return &_worldPacket; +} + +void WorldPackets::Battlenet::Request::Read() +{ + uint32 protoSize; + + _worldPacket >> Method; + _worldPacket >> protoSize; + + Data.Resize(protoSize); + _worldPacket.read(Data.GetWritePointer(), Data.GetRemainingSpace()); + Data.WriteCompleted(protoSize); +} + +void WorldPackets::Battlenet::RequestRealmListTicket::Read() +{ + _worldPacket >> Token; + _worldPacket.read(Secret.data(), Secret.size()); +} diff --git a/src/server/game/Server/Packets/BattlenetPackets.h b/src/server/game/Server/Packets/BattlenetPackets.h new file mode 100644 index 00000000000..f059b39b75f --- /dev/null +++ b/src/server/game/Server/Packets/BattlenetPackets.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef BattlenetPackets_h__ +#define BattlenetPackets_h__ + +#include "Packet.h" +#include "MessageBuffer.h" +#include "BattlenetRpcErrorCodes.h" + +namespace WorldPackets +{ + namespace Battlenet + { + struct MethodCall + { + uint64 Type = 0; + uint64 ObjectId = 0; + uint32 Token = 0; + + uint32 GetServiceHash() const { return uint32(Type >> 32); } + uint32 GetMethodId() const { return uint32(Type & 0xFFFFFFFF); } + }; + + class Notification final : public ServerPacket + { + public: + Notification() : ServerPacket(SMSG_BATTLENET_NOTIFICATION, 8 + 8 + 4 + 4) { } + + WorldPacket const* Write() override; + + MethodCall Method; + ByteBuffer Data; + }; + + class Response final : public ServerPacket + { + public: + Response() : ServerPacket(SMSG_BATTLENET_RESPONSE, 4 + 8 + 8 + 4 + 4) { } + + WorldPacket const* Write() override; + + BattlenetRpcErrorCode BnetStatus = ERROR_OK; + MethodCall Method; + ByteBuffer Data; + }; + + class SetSessionState final : public ServerPacket + { + public: + SetSessionState() : ServerPacket(SMSG_BATTLENET_SET_SESSION_STATE, 1) { } + + WorldPacket const* Write() override; + + uint8 State = 0; + }; + + class RealmListTicket final : public ServerPacket + { + public: + RealmListTicket() : ServerPacket(SMSG_BATTLENET_REALM_LIST_TICKET) { } + + WorldPacket const* Write() override; + + uint32 Token; + bool Allow; + ByteBuffer Ticket; + }; + + class Request final : public ClientPacket + { + public: + Request(WorldPacket&& packet) : ClientPacket(CMSG_BATTLENET_REQUEST, std::move(packet)) { } + + void Read() override; + + MethodCall Method; + MessageBuffer Data; + }; + + class RequestRealmListTicket final : public ClientPacket + { + public: + RequestRealmListTicket(WorldPacket&& packet) : ClientPacket(CMSG_BATTLENET_REQUEST_REALM_LIST_TICKET, std::move(packet)) { } + + void Read() override; + + uint32 Token = 0; + std::array<uint8, 32> Secret; + }; + } +} + +#endif // BattlenetPackets_h__ diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index ca37b04f484..aeaf43e6e8a 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -137,7 +137,7 @@ bool WorldPackets::Query::PlayerGuidLookupData::Initialize(ObjectGuid const& gui else { uint32 accountId = ObjectMgr::GetPlayerAccountIdByGUID(guid); - uint32 bnetAccountId = Battlenet::AccountMgr::GetIdByGameAccount(accountId); + uint32 bnetAccountId = ::Battlenet::AccountMgr::GetIdByGameAccount(accountId); AccountID = ObjectGuid::Create<HighGuid::WowAccount>(accountId); BnetAccountID = ObjectGuid::Create<HighGuid::BNetAccount>(bnetAccountId); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 19aff2468a9..931b74dd234 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -159,8 +159,8 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Battleground::BattlemasterJoinArena, &WorldSession::HandleBattlemasterJoinArena); DEFINE_HANDLER(CMSG_BATTLEMASTER_JOIN_SKIRMISH, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLENET_CHALLENGE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_BATTLENET_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_BATTLENET_REQUEST_REALM_LIST_TICKET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_BATTLENET_REQUEST, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Battlenet::Request, &WorldSession::HandleBattlenetRequest); + DEFINE_HANDLER(CMSG_BATTLENET_REQUEST_REALM_LIST_TICKET, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Battlenet::RequestRealmListTicket, &WorldSession::HandleBattlenetRequestRealmListTicket); DEFINE_HANDLER(CMSG_BATTLE_PAY_ACK_FAILED_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLE_PAY_CONFIRM_PURCHASE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BATTLE_PAY_DISTRIBUTION_ASSIGN_TO_TARGET, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -867,10 +867,10 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_POINTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_CHALLENGE_ABORT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_CHALLENGE_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_REALM_LIST_TICKET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_SET_SESSION_STATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_REALM_LIST_TICKET, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLENET_SET_SESSION_STATE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_ACK_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_CONFIRM_PURCHASE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_DELIVERY_ENDED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 44bfa90589c..aa2b2c28ede 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -43,7 +43,7 @@ #include "ScriptMgr.h" #include "WardenWin.h" #include "AuthenticationPackets.h" -#include "BattlenetRpcErrorCodes.h" +#include "BattlenetPackets.h" #include "CharacterPackets.h" #include "ClientConfigPackets.h" #include "MiscPackets.h" @@ -1151,13 +1151,14 @@ public: BATTLE_PETS, BATTLE_PET_SLOTS, GLOBAL_ACCOUNT_HEIRLOOMS, + GLOBAL_REALM_CHARACTER_COUNTS, MAX_QUERIES }; AccountInfoQueryHolder() { SetSize(MAX_QUERIES); } - bool Initialize(uint32 /*accountId*/, uint32 battlenetAccountId) + bool Initialize(uint32 accountId, uint32 battlenetAccountId) { bool ok = true; @@ -1177,6 +1178,10 @@ public: stmt->setUInt32(0, battlenetAccountId); ok = SetPreparedQuery(GLOBAL_ACCOUNT_HEIRLOOMS, stmt) && ok; + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID); + stmt->setUInt32(0, accountId); + ok = SetPreparedQuery(GLOBAL_REALM_CHARACTER_COUNTS, stmt) && ok; + return ok; } }; @@ -1225,6 +1230,20 @@ void WorldSession::InitializeSessionCallback(SQLQueryHolder* realmHolder, SQLQue SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION)); SendTutorialsData(); + if (PreparedQueryResult characterCountsResult = holder->GetPreparedResult(AccountInfoQueryHolder::GLOBAL_REALM_CHARACTER_COUNTS)) + { + do + { + Field* fields = characterCountsResult->Fetch(); + _realmCharacterCounts[Battlenet::RealmHandle{ fields[3].GetUInt8(), fields[4].GetUInt8(), fields[2].GetUInt32() }.GetAddress()] = fields[1].GetUInt8(); + + } while (characterCountsResult->NextRow()); + } + + WorldPackets::Battlenet::SetSessionState bnetConnected; + bnetConnected.State = 1; + SendPacket(bnetConnected.Write()); + _battlePetMgr->LoadFromDB(holder->GetPreparedResult(AccountInfoQueryHolder::BATTLE_PETS), holder->GetPreparedResult(AccountInfoQueryHolder::BATTLE_PET_SLOTS)); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 0b23e0ac71b..35ce9c7026f 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -129,6 +129,12 @@ namespace WorldPackets class RequestRatedBattlefieldInfo; } + namespace Battlenet + { + class Request; + class RequestRealmListTicket; + } + namespace BattlePet { class BattlePetRequestJournal; @@ -704,6 +710,16 @@ namespace WorldPackets }; } +namespace google +{ + namespace protobuf + { + class Message; + } +} + +namespace pb = google::protobuf; + enum AccountDataType { GLOBAL_CONFIG_CACHE = 0, // 0x01 g @@ -916,6 +932,7 @@ class TC_GAME_API WorldSession std::string const& GetRemoteAddress() const { return m_Address; } void SetPlayer(Player* player); uint8 GetExpansion() const { return m_expansion; } + std::string const& GetOS() const { return _os; } void InitWarden(BigNumber* k); @@ -1678,6 +1695,20 @@ class TC_GAME_API WorldSession // Warden void HandleWardenData(WorldPackets::Warden::WardenData& packet); + // Battlenet + void HandleBattlenetRequest(WorldPackets::Battlenet::Request& request); + void HandleBattlenetRequestRealmListTicket(WorldPackets::Battlenet::RequestRealmListTicket& requestRealmListTicket); + + void SendBattlenetResponse(uint32 serviceHash, uint32 methodId, uint32 token, pb::Message const* response); + void SendBattlenetResponse(uint32 serviceHash, uint32 methodId, uint32 token, uint32 status); + void SendBattlenetRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request, std::function<void(MessageBuffer)> callback); + void SendBattlenetRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request); + + std::array<uint8, 32> const& GetRealmListSecret() const { return _realmListSecret; } + void SetRealmListSecret(std::array<uint8, 32> const& secret) { memcpy(_realmListSecret.data(), secret.data(), secret.size()); } + + std::unordered_map<uint32, uint8> const& GetRealmCharacterCounts() const { return _realmCharacterCounts; } + union ConnectToKey { struct @@ -1775,6 +1806,11 @@ class TC_GAME_API WorldSession uint8 m_expansion; std::string _os; + std::array<uint8, 32> _realmListSecret; + std::unordered_map<uint32 /*realmAddress*/, uint8> _realmCharacterCounts; + std::unordered_map<uint32, std::function<void(MessageBuffer)>> _battlenetResponseCallbacks; + uint32 _battlenetRequestToken; + typedef std::list<AddonInfo> AddonsList; // Warden diff --git a/src/server/game/Services/WorldserverService.cpp b/src/server/game/Services/WorldserverService.cpp new file mode 100644 index 00000000000..9859d7cfaa4 --- /dev/null +++ b/src/server/game/Services/WorldserverService.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "WorldserverService.h" +#include "Log.h" +#include "RealmList.h" +#include "RealmList.pb.h" +#include "BattlenetRpcErrorCodes.h" +#include "ProtobufJSON.h" +#include <zlib.h> + +Battlenet::GameUtilitiesService::GameUtilitiesService(WorldSession* session) : BaseService(session) +{ +} + +uint32 Battlenet::GameUtilitiesService::HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response) +{ + Attribute const* command = nullptr; + std::unordered_map<std::string, Variant const*> params; + + for (int32 i = 0; i < request->attribute_size(); ++i) + { + Attribute const& attr = request->attribute(i); + params[attr.name()] = &attr.value(); + if (strstr(attr.name().c_str(), "Command_") == attr.name().c_str()) + command = &attr; + } + + if (!command) + { + TC_LOG_ERROR("session.rpc", "%s sent ClientRequest with no command.", GetCallerInfo().c_str()); + return ERROR_RPC_MALFORMED_REQUEST; + } + + if (command->name() == "Command_RealmListRequest_v1_b9") + return HandleRealmListRequest(params, response); + else if (command->name() == "Command_RealmJoinRequest_v1_b9") + return HandleRealmJoinRequest(params, response); + + return ERROR_RPC_NOT_IMPLEMENTED; +} + +uint32 Battlenet::GameUtilitiesService::HandleRealmListRequest(std::unordered_map<std::string, Variant const*> params, game_utilities::v1::ClientResponse* response) +{ + std::string subRegionId; + auto subRegion = params.find("Command_RealmListRequest_v1_b9"); + if (subRegion != params.end()) + subRegionId = subRegion->second->string_value(); + + std::vector<uint8> compressed = sRealmList->GetRealmList(realm.Build, subRegionId); + + if (compressed.empty()) + return ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE; + + Attribute* attribute = response->add_attribute(); + attribute->set_name("Param_RealmList"); + attribute->mutable_value()->set_blob_value(compressed.data(), compressed.size()); + + JSON::RealmList::RealmCharacterCountList realmCharacterCounts; + for (auto const& characterCount : _session->GetRealmCharacterCounts()) + { + ::JSON::RealmList::RealmCharacterCountEntry* countEntry = realmCharacterCounts.add_counts(); + countEntry->set_wowrealmaddress(characterCount.first); + countEntry->set_count(characterCount.second); + } + + std::string json = "JSONRealmCharacterCountList:" + JSON::Serialize(realmCharacterCounts); + + uLongf compressedLength = compressBound(json.length()); + compressed.resize(4 + compressedLength); + *reinterpret_cast<uint32*>(compressed.data()) = json.length() + 1; + + if (compress(compressed.data() + 4, &compressedLength, reinterpret_cast<uint8 const*>(json.c_str()), json.length() + 1) != Z_OK) + return ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE; + + attribute = response->add_attribute(); + attribute->set_name("Param_CharacterCountList"); + attribute->mutable_value()->set_blob_value(compressed.data(), compressedLength + 4); + + return ERROR_OK; +} + +uint32 Battlenet::GameUtilitiesService::HandleRealmJoinRequest(std::unordered_map<std::string, Variant const*> params, game_utilities::v1::ClientResponse* response) +{ + auto realmAddress = params.find("Param_RealmAddress"); + if (realmAddress != params.end()) + return sRealmList->JoinRealm(realmAddress->second->uint_value(), realm.Build, boost::asio::ip::address::from_string(_session->GetRemoteAddress()), _session->GetRealmListSecret(), + _session->GetSessionDbcLocale(), _session->GetOS(), _session->GetAccountName(), response); + + return ERROR_WOW_SERVICES_INVALID_JOIN_TICKET; +} + +uint32 Battlenet::GameUtilitiesService::HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response) +{ + if (request->attribute_key() == "Command_RealmListRequest_v1_b9") + { + sRealmList->WriteSubRegions(response); + return ERROR_OK; + } + + return ERROR_RPC_NOT_IMPLEMENTED; +} diff --git a/src/server/game/Services/WorldserverService.h b/src/server/game/Services/WorldserverService.h new file mode 100644 index 00000000000..768fb164c13 --- /dev/null +++ b/src/server/game/Services/WorldserverService.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WorldserverService_h__ +#define WorldserverService_h__ + +#include "WorldSession.h" +#include "account_service.pb.h" +#include "authentication_service.pb.h" +#include "challenge_service.pb.h" +#include "channel_service.pb.h" +#include "connection_service.pb.h" +#include "friends_service.pb.h" +#include "game_utilities_service.pb.h" +#include "presence_service.pb.h" +#include "report_service.pb.h" +#include "resource_service.pb.h" +#include "user_manager_service.pb.h" + +namespace bgs { namespace protocol { } } +using namespace bgs::protocol; + +namespace Battlenet +{ + template<class T> + class WorldserverService : public T + { + public: + WorldserverService(WorldSession* session) : T(false), _session(session) { } + + protected: + void SendRequest(uint32 serviceHash, uint32 methodId, google::protobuf::Message const* request, std::function<void(MessageBuffer)> callback) override { _session->SendBattlenetRequest(serviceHash, methodId, request, std::move(callback)); } + void SendRequest(uint32 serviceHash, uint32 methodId, google::protobuf::Message const* request) override { _session->SendBattlenetRequest(serviceHash, methodId, request); } + void SendResponse(uint32 serviceHash, uint32 methodId, uint32 token, uint32 status) { _session->SendBattlenetResponse(serviceHash, methodId, token, status); } + void SendResponse(uint32 serviceHash, uint32 methodId, uint32 token, google::protobuf::Message const* response) override { _session->SendBattlenetResponse(serviceHash, methodId, token, response); } + std::string GetCallerInfo() const override { return _session->GetPlayerInfo(); } + + WorldSession* _session; + }; + + class GameUtilitiesService : public WorldserverService<game_utilities::v1::GameUtilitiesService> + { + typedef WorldserverService<game_utilities::v1::GameUtilitiesService> BaseService; + + public: + GameUtilitiesService(WorldSession* session); + + uint32 HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response) override; + uint32 HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response) override; + + private: + uint32 HandleRealmListRequest(std::unordered_map<std::string, Variant const*> params, game_utilities::v1::ClientResponse* response); + uint32 HandleRealmJoinRequest(std::unordered_map<std::string, Variant const*> params, game_utilities::v1::ClientResponse* response); + }; +} + +#endif // WorldserverService_h__ diff --git a/src/server/game/Services/WorldserverServiceDispatcher.cpp b/src/server/game/Services/WorldserverServiceDispatcher.cpp new file mode 100644 index 00000000000..402a4386786 --- /dev/null +++ b/src/server/game/Services/WorldserverServiceDispatcher.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "WorldserverServiceDispatcher.h" +#include "WorldserverService.h" + +Battlenet::WorldserverServiceDispatcher::WorldserverServiceDispatcher() +{ + AddService<WorldserverService<account::v1::AccountService>>(); + AddService<WorldserverService<authentication::v1::AuthenticationService>>(); + AddService<WorldserverService<challenge::v1::ChallengeService>>(); + AddService<WorldserverService<channel::v1::ChannelService>>(); + AddService<WorldserverService<connection::v1::ConnectionService>>(); + AddService<WorldserverService<friends::v1::FriendsService>>(); + AddService<GameUtilitiesService>(); + AddService<WorldserverService<presence::v1::PresenceService>>(); + AddService<WorldserverService<report::v1::ReportService>>(); + AddService<WorldserverService<resources::v1::ResourcesService>>(); + AddService<WorldserverService<user_manager::v1::UserManagerService>>(); +} + +void Battlenet::WorldserverServiceDispatcher::Dispatch(WorldSession* session, uint32 serviceHash, uint32 token, uint32 methodId, MessageBuffer buffer) +{ + auto itr = _dispatchers.find(serviceHash); + if (itr != _dispatchers.end()) + itr->second(session, token, methodId, std::forward<MessageBuffer>(buffer)); + else + TC_LOG_DEBUG("session.rpc", "%s tried to call invalid service 0x%X", session->GetPlayerInfo().c_str(), serviceHash); +} + +Battlenet::WorldserverServiceDispatcher& Battlenet::WorldserverServiceDispatcher::Instance() +{ + static WorldserverServiceDispatcher instance; + return instance; +} diff --git a/src/server/game/Services/WorldserverServiceDispatcher.h b/src/server/game/Services/WorldserverServiceDispatcher.h new file mode 100644 index 00000000000..c2e9c9fb131 --- /dev/null +++ b/src/server/game/Services/WorldserverServiceDispatcher.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ServiceRegistry_h__ +#define ServiceRegistry_h__ + +#include "WorldSession.h" +#include "MessageBuffer.h" +#include "Log.h" +#include "Common.h" +#include "account_service.pb.h" +#include "authentication_service.pb.h" +#include "challenge_service.pb.h" +#include "channel_service.pb.h" +#include "connection_service.pb.h" +#include "friends_service.pb.h" +#include "game_utilities_service.pb.h" +#include "presence_service.pb.h" +#include "report_service.pb.h" +#include "resource_service.pb.h" +#include "user_manager_service.pb.h" + +namespace Battlenet +{ + class WorldserverServiceDispatcher + { + public: + void Dispatch(WorldSession* session, uint32 serviceHash, uint32 token, uint32 methodId, MessageBuffer buffer); + + static WorldserverServiceDispatcher& Instance(); + + private: + WorldserverServiceDispatcher(); + + template<class Service> + void AddService() + { + _dispatchers[Service::NameHash::value] = &WorldserverServiceDispatcher::Dispatch<Service>; + } + + template<class Service> + static void Dispatch(WorldSession* session, uint32 token, uint32 methodId, MessageBuffer buffer) + { + Service(session).CallServerMethod(token, methodId, std::forward<MessageBuffer>(buffer)); + } + + std::unordered_map<uint32, std::function<void(WorldSession*, uint32, uint32, MessageBuffer)>> _dispatchers; + }; +} + +#define sServiceDispatcher Battlenet::WorldserverServiceDispatcher::Instance() + +#endif // ServiceRegistry_h__ |
