TrinityCore
WorldserverService.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldserverService.h"
20#include "IpAddress.h"
21#include "Log.h"
22#include "ProtobufJSON.h"
23#include "Realm.h"
24#include "RealmList.h"
25#include "RealmList.pb.h"
26#include "World.h"
27#include <zlib.h>
28
29std::unordered_map<std::string, Battlenet::GameUtilitiesService::ClientRequestHandler> const Battlenet::GameUtilitiesService::ClientRequestHandlers =
30{
31 { "Command_RealmListRequest_v1", &GameUtilitiesService::HandleRealmListRequest },
32 { "Command_RealmJoinRequest_v1", &GameUtilitiesService::HandleRealmJoinRequest }
33};
34
36{
37}
38
39uint32 Battlenet::GameUtilitiesService::HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response, std::function<void(ServiceBase*, uint32, ::google::protobuf::Message const*)>& /*continuation*/)
40{
41 Attribute const* command = nullptr;
42 std::unordered_map<std::string, Variant const*> params;
43 auto removeSuffix = [](std::string const& string) -> std::string
44 {
45 size_t pos = string.rfind('_');
46 if (pos != std::string::npos)
47 return string.substr(0, pos);
48
49 return string;
50 };
51
52 for (int32 i = 0; i < request->attribute_size(); ++i)
53 {
54 Attribute const& attr = request->attribute(i);
55 if (strstr(attr.name().c_str(), "Command_") == attr.name().c_str())
56 {
57 command = &attr;
58 params[removeSuffix(attr.name())] = &attr.value();
59 }
60 else
61 params[attr.name()] = &attr.value();
62 }
63
64 if (!command)
65 {
66 TC_LOG_ERROR("session.rpc", "{} sent ClientRequest with no command.", GetCallerInfo());
68 }
69
70 auto itr = ClientRequestHandlers.find(removeSuffix(command->name()));
71 if (itr == ClientRequestHandlers.end())
72 {
73 TC_LOG_ERROR("session.rpc", "{} sent ClientRequest with unknown command {}.", GetCallerInfo(), removeSuffix(command->name()));
75 }
76
77 return (this->*itr->second)(params, response);
78}
79
80static Variant const* GetParam(std::unordered_map<std::string, Variant const*> const& params, char const* paramName)
81{
82 auto itr = params.find(paramName);
83 return itr != params.end() ? itr->second : nullptr;
84}
85
86uint32 Battlenet::GameUtilitiesService::HandleRealmListRequest(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response)
87{
88 std::string subRegionId;
89 if (Variant const* subRegion = GetParam(params, "Command_RealmListRequest_v1"))
90 subRegionId = subRegion->string_value();
91
92 std::vector<uint8> compressed = sRealmList->GetRealmList(realm.Build, subRegionId);
93
94 if (compressed.empty())
96
97 Attribute* attribute = response->add_attribute();
98 attribute->set_name("Param_RealmList");
99 attribute->mutable_value()->set_blob_value(compressed.data(), compressed.size());
100
101 JSON::RealmList::RealmCharacterCountList realmCharacterCounts;
102 for (auto const& characterCount : _session->GetRealmCharacterCounts())
103 {
104 ::JSON::RealmList::RealmCharacterCountEntry* countEntry = realmCharacterCounts.add_counts();
105 countEntry->set_wowrealmaddress(characterCount.first);
106 countEntry->set_count(characterCount.second);
107 }
108
109 std::string json = "JSONRealmCharacterCountList:" + JSON::Serialize(realmCharacterCounts);
110
111 uLongf compressedLength = compressBound(json.length());
112 compressed.resize(4 + compressedLength);
113 *reinterpret_cast<uint32*>(compressed.data()) = json.length() + 1;
114
115 if (compress(compressed.data() + 4, &compressedLength, reinterpret_cast<uint8 const*>(json.c_str()), json.length() + 1) != Z_OK)
117
118 attribute = response->add_attribute();
119 attribute->set_name("Param_CharacterCountList");
120 attribute->mutable_value()->set_blob_value(compressed.data(), compressedLength + 4);
121
122 return ERROR_OK;
123}
124
125uint32 Battlenet::GameUtilitiesService::HandleRealmJoinRequest(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response)
126{
127 if (Variant const* realmAddress = GetParam(params, "Param_RealmAddress"))
128 return sRealmList->JoinRealm(uint32(realmAddress->uint_value()), realm.Build, Trinity::Net::make_address(_session->GetRemoteAddress()), _session->GetRealmListSecret(),
129 _session->GetSessionDbcLocale(), _session->GetOS(), _session->GetTimezoneOffset(), _session->GetAccountName(), response);
130
132}
133
135{
136 if (request->attribute_key().find("Command_RealmListRequest_v1") == 0)
137 {
138 sRealmList->WriteSubRegions(response);
139 return ERROR_OK;
140 }
141
143}
@ ERROR_RPC_NOT_IMPLEMENTED
@ ERROR_RPC_MALFORMED_REQUEST
@ ERROR_WOW_SERVICES_INVALID_JOIN_TICKET
@ ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE
uint8_t uint8
Definition: Define.h:145
int32_t int32
Definition: Define.h:139
uint32_t uint32
Definition: Define.h:143
std::unordered_set< uint32 > params[2]
Definition: DisableMgr.cpp:50
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define sRealmList
Definition: RealmList.h:96
static Variant const * GetParam(std::unordered_map< std::string, Variant const * > const &params, char const *paramName)
uint32 HandleRealmJoinRequest(std::unordered_map< std::string, Variant const * > const &params, game_utilities::v1::ClientResponse *response)
GameUtilitiesService(WorldSession *session)
static std::unordered_map< std::string, ClientRequestHandler > const ClientRequestHandlers
uint32 HandleProcessClientRequest(game_utilities::v1::ClientRequest const *request, game_utilities::v1::ClientResponse *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
uint32 HandleRealmListRequest(std::unordered_map< std::string, Variant const * > const &params, game_utilities::v1::ClientResponse *response)
uint32 HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const *request, game_utilities::v1::GetAllValuesForAttributeResponse *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
void set_wowrealmaddress(::google::protobuf::uint32 value)
void set_count(::google::protobuf::uint32 value)
inline ::JSON::RealmList::RealmCharacterCountEntry * add_counts()
Player session in the World.
Definition: WorldSession.h:961
const ::bgs::protocol::Variant & value() const
const ::std::string & name() const
inline ::bgs::protocol::Variant * mutable_value()
void set_name(const ::std::string &value)
void set_blob_value(const ::std::string &value)
Realm realm
Definition: World.cpp:3984
TC_SHARED_API std::string Serialize(google::protobuf::Message const &message)
uint32 Build
Definition: Realm.h:83