aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-03-28 17:12:57 +0200
committerShauren <shauren.trinity@gmail.com>2016-03-28 17:12:57 +0200
commitdde620c402daf4ea8d132fb72a77eabc22f7a6d0 (patch)
tree7c12161d7a22915736b0c9a106de896eeb283399 /src/server/game
parent619669c6209441fc2fb5b483d553badee8c30ad5 (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.cpp17
-rw-r--r--src/server/game/Handlers/BattlenetHandler.cpp87
-rw-r--r--src/server/game/Server/Packets/AllPackets.h1
-rw-r--r--src/server/game/Server/Packets/BattlenetPackets.cpp89
-rw-r--r--src/server/game/Server/Packets/BattlenetPackets.h108
-rw-r--r--src/server/game/Server/Packets/QueryPackets.cpp2
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp12
-rw-r--r--src/server/game/Server/WorldSession.cpp23
-rw-r--r--src/server/game/Server/WorldSession.h36
-rw-r--r--src/server/game/Services/WorldserverService.cpp116
-rw-r--r--src/server/game/Services/WorldserverService.h71
-rw-r--r--src/server/game/Services/WorldserverServiceDispatcher.cpp49
-rw-r--r--src/server/game/Services/WorldserverServiceDispatcher.h67
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__