26#include "RealmList.pb.h"
37 if (command.starts_with(
"Command_"sv))
39 size_t pos = command.rfind(
'_');
40 if (pos != std::string_view::npos)
41 command.remove_suffix(command.length() - pos);
50 return itr !=
params.end() ? &itr->second :
nullptr;
55 uLong uncompressedLength = uLong(json.length() + 1);
56 uLong compressedLength = compressBound(uLong(json.length()));
57 std::vector<uint8> compressed(compressedLength + 4);
58 memcpy(compressed.data(), &uncompressedLength,
sizeof(uncompressedLength));
60 if (compress(compressed.data() + 4, &compressedLength,
reinterpret_cast<uint8 const*
>(json.data()), uncompressedLength) != Z_OK)
66 compressed.resize(compressedLength + 4);
71 std::vector<std::pair<std::string_view, Variant>>&
params,
72 std::vector<std::pair<std::string_view, Variant>>& responseValues)
74 auto command = std::ranges::find_if(
params,
75 [](std::string_view paramName) {
return paramName.starts_with(
"Command_"sv); },
78 if (command ==
params.end())
112 for (std::string& subRegion :
sRealmList->GetSubRegions())
113 responseValues.emplace_back(std::move(subRegion));
119 TC_LOG_ERROR(
"session.rpc",
"{} sent GetAllValuesForAttributeRequest with unknown command {}.", session->
GetClientInfo(), command);
124 std::vector<std::pair<std::string_view, Variant>>&
params,
125 std::vector<std::pair<std::string_view, Variant>>& responseValues)
128 if (!subRegion || !std::holds_alternative<std::string>(*subRegion))
134 if (realmEntryJson.empty())
137 std::vector<uint8> guidData(
sizeof(lastPlayerChar->CharacterGUID));
138 std::memcpy(guidData.data(), &lastPlayerChar->CharacterGUID,
sizeof(lastPlayerChar->CharacterGUID));
140 ::JSON::RealmList::UtilityInfo utilityInfo;
141 utilityInfo.set_realmpermissions(0x200);
145 responseValues.emplace_back(
"Param_RealmEntry"sv,
CompressJson(
"JamJSONRealmEntry:" + realmEntryJson));
146 responseValues.emplace_back(
"Param_CharacterName"sv, lastPlayerChar->CharacterName);
147 responseValues.emplace_back(
"Param_CharacterGUID"sv, std::move(guidData));
148 responseValues.emplace_back(
"Param_LastPlayedTime"sv,
int64(lastPlayerChar->LastPlayedTime));
149 responseValues.emplace_back(
"Param_UtilityInfo"sv, std::move(utilityInfoJson));
156 std::vector<std::pair<std::string_view, Variant>>&
params,
157 std::vector<std::pair<std::string_view, Variant>>& responseValues)
161 if (
Variant const* identity =
FindParamValue(
params,
"Param_Identity"); identity && std::holds_alternative<std::vector<uint8>>(*identity))
163 std::string_view json = {
reinterpret_cast<char const*
>(std::get<std::vector<uint8>>(*identity).data()), std::get<std::vector<uint8>>(*identity).size() };
164 ::JSON::RealmList::RealmListTicketIdentity data;
165 std::size_t jsonStart = json.find(
':');
166 if (jsonStart != std::string_view::npos &&
::JSON::Deserialize(json.substr(jsonStart + 1), &data))
170 if (!gameAccountInfo)
182 std::string_view json = {
reinterpret_cast<char const*
>(std::get<std::vector<uint8>>(*clientInfo).data()), std::get<std::vector<uint8>>(*clientInfo).size() };
183 ::JSON::RealmList::RealmListTicketClientInformation data;
184 std::size_t jsonStart = json.find(
':');
185 if (jsonStart != std::string_view::npos &&
::JSON::Deserialize(json.substr(jsonStart + 1), &data))
187 if (data.info().secret().size() == 32)
188 memcpy(clientSecret.emplace().data(), data.info().secret().data(), data.info().secret().size());
202 session->
SetClientInfo(gameAccountInfo->
Id, clientBuildVariant, *clientSecret);
212 std::vector<uint8> realmListTicket;
213 std::ranges::copy(
"AuthRealmListTicket\0"sv, std::back_inserter(realmListTicket));
214 responseValues.emplace_back(
"Param_RealmListTicket"sv, std::move(realmListTicket));
220 std::vector<std::pair<std::string_view, Variant>>&
params,
221 std::vector<std::pair<std::string_view, Variant>>& responseValues)
223 std::string subRegionId;
224 if (
Variant const* subRegion =
FindParamValue(
params,
"Command_RealmListRequest_v1"); subRegion && std::holds_alternative<std::string>(*subRegion))
225 subRegionId = std::get<std::string>(*subRegion);
229 if (realmListJson.empty())
232 ::JSON::RealmList::RealmCharacterCountList realmCharacterCounts;
235 ::JSON::RealmList::RealmCharacterCountEntry* countEntry = realmCharacterCounts.add_counts();
236 countEntry->set_wowrealmaddress(realmAddress);
237 countEntry->set_count(count);
242 if (characterCountsJson.empty())
245 responseValues.emplace_back(
"Param_RealmList"sv, std::move(realmListJson));
246 responseValues.emplace_back(
"Param_CharacterCountList"sv, std::move(characterCountsJson));
252 std::vector<std::pair<std::string_view, Variant>>&
params,
253 std::vector<std::pair<std::string_view, Variant>>& responseValues)
256 if (!realmAddress || !std::holds_alternative<uint64>(*realmAddress))
265 responseValues.emplace_back(
"Param_RealmJoinTicket"sv, std::move(result.
JoinTicket));
266 responseValues.emplace_back(
"Param_ServerAddresses"sv, std::move(result.
ServerAddresses));
267 responseValues.emplace_back(
"Param_JoinSecret"sv, std::move(result.
JoinSecret));
274 std::vector<std::pair<std::string_view, Variant>>& ,
275 std::vector<std::pair<std::string_view, Variant>>& responseValues)
279 if (proxyListJson.empty())
282 responseValues.emplace_back(
"Param_BleepProxyList"sv, std::move(proxyListJson));
292 if (from.has_bool_value())
293 return from.bool_value();
294 if (from.has_int_value())
295 return from.int_value();
296 if (from.has_float_value())
297 return from.float_value();
298 if (from.has_string_value())
299 return from.string_value();
300 if (from.has_blob_value())
301 return Variant{ std::in_place_type<std::vector<uint8>>,
302 reinterpret_cast<uint8 const*
>(from.blob_value().data()),
303 reinterpret_cast<uint8 const*
>(from.blob_value().data()) + from.blob_value().size() };
304 if (from.has_uint_value())
305 return from.uint_value();
312 std::visit([to]<
typename T>(T
const& value)
314 if constexpr (std::is_same_v<T, bool>)
315 to->set_bool_value(value);
316 else if constexpr (std::is_same_v<T, int64>)
317 to->set_int_value(value);
318 else if constexpr (std::is_same_v<T, double>)
319 to->set_float_value(value);
320 else if constexpr (std::is_same_v<T, std::string>)
321 to->set_string_value(value);
322 else if constexpr (std::is_same_v<T, std::vector<uint8>>)
323 to->set_blob_value(value.data(), value.size());
324 else if constexpr (std::is_same_v<T, uint64>)
325 to->set_uint_value(value);
327 static_assert(Trinity::dependant_false_v<T>);
340 std::vector<std::pair<std::string_view, Variant>>
params;
341 std::vector<std::pair<std::string_view, Variant>> responseValues;
343 for (Attribute
const& attribute : request->attribute())
345 if (!attribute.has_name() || !attribute.has_value())
353 for (
auto&& [name, value] : responseValues)
355 Attribute* attr = response->add_attribute();
356 attr->set_name(name.data(), name.length());
357 ToProto(value, attr->mutable_value());
368 std::vector<Variant> responseValues;
372 for (
Variant& value : responseValues)
373 ToProto(value, response->add_attribute_value());
383 switch (from.type_case())
385 case v2::Variant::kBoolValue:
386 return from.bool_value();
387 case v2::Variant::kIntValue:
388 return from.int_value();
389 case v2::Variant::kFloatValue:
390 return from.float_value();
391 case v2::Variant::kStringValue:
392 return from.string_value();
393 case v2::Variant::kBlobValue:
394 return Variant{ std::in_place_type<std::vector<uint8>>,
395 reinterpret_cast<uint8 const*
>(from.blob_value().data()),
396 reinterpret_cast<uint8 const*
>(from.blob_value().data()) + from.blob_value().size() };
397 case v2::Variant::kUintValue:
398 return from.uint_value();
408 std::visit([to]<
typename T>(T
const& value)
410 if constexpr (std::is_same_v<T, bool>)
411 to->set_bool_value(value);
412 else if constexpr (std::is_same_v<T, int64>)
413 to->set_int_value(value);
414 else if constexpr (std::is_same_v<T, double>)
415 to->set_float_value(value);
416 else if constexpr (std::is_same_v<T, std::string>)
417 to->set_string_value(value);
418 else if constexpr (std::is_same_v<T, std::vector<uint8>>)
419 to->set_blob_value(value.data(), value.size());
420 else if constexpr (std::is_same_v<T, uint64>)
421 to->set_uint_value(value);
423 static_assert(Trinity::dependant_false_v<T>);
436 std::vector<std::pair<std::string_view, Variant>>
params;
437 std::vector<std::pair<std::string_view, Variant>> responseValues;
439 for (v2::Attribute
const& attribute : request->attribute())
441 if (!attribute.has_name() || !attribute.has_value())
449 for (
auto&& [name, value] : responseValues)
451 v2::Attribute* attr = response->add_result();
452 attr->set_name(name.data(), name.length());
453 ToProto(value, attr->mutable_value());
464 std::vector<Variant> responseValues;
468 for (
Variant& value : responseValues)
469 ToProto(value, response->add_attribute_value());
@ ERROR_GAME_ACCOUNT_BANNED
@ ERROR_RPC_NOT_IMPLEMENTED
@ ERROR_RPC_MALFORMED_REQUEST
@ ERROR_UTIL_SERVER_INVALID_IDENTITY_ARGS
@ ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE
@ ERROR_GAME_ACCOUNT_SUSPENDED
@ ERROR_WOW_SERVICES_DENIED_REALM_LIST_TICKET
@ ERROR_UTIL_SERVER_UNKNOWN_REALM
LocaleConstant GetLocaleByName(std::string_view name)
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
std::unordered_set< uint32 > params[2]
#define TC_LOG_ERROR(filterType__, message__,...)
@ LOGIN_UPD_BNET_LAST_LOGIN_INFO
std::optional< T > Optional
Optional helper class to wrap optional values within.
static uint32 GetLastCharPlayed(Session const *session, std::vector< std::pair< std::string_view, Variant > > ¶ms, std::vector< std::pair< std::string_view, Variant > > &responseValues)
static Variant * FindParamValue(std::vector< std::pair< std::string_view, Variant > > ¶ms, std::string_view paramName)
static uint32 HandleClientRequest(Session *session, std::vector< std::pair< std::string_view, Variant > > ¶ms, std::vector< std::pair< std::string_view, Variant > > &responseValues)
static std::string_view ParseParamName(std::string_view command)
static uint32 JoinRealm(Session const *session, std::vector< std::pair< std::string_view, Variant > > ¶ms, std::vector< std::pair< std::string_view, Variant > > &responseValues)
static uint32 GetRealmList(Session const *session, std::vector< std::pair< std::string_view, Variant > > ¶ms, std::vector< std::pair< std::string_view, Variant > > &responseValues)
static uint32 GetBleepProxies(Session const *session, std::vector< std::pair< std::string_view, Variant > > ¶ms, std::vector< std::pair< std::string_view, Variant > > &responseValues)
static uint32 HandleGetAllValuesForAttribute(Session const *session, std::string_view command, std::vector< Variant > &responseValues)
static uint32 GetRealmListTicket(Session *session, std::vector< std::pair< std::string_view, Variant > > ¶ms, std::vector< std::pair< std::string_view, Variant > > &responseValues)
static std::vector< uint8 > CompressJson(std::string const &json)
GameUtilities(Session *session)
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 HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const *request, game_utilities::v1::GetAllValuesForAttributeResponse *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
uint32 HandleProcessTask(game_utilities::v2::client::ProcessTaskRequest const *request, game_utilities::v2::client::ProcessTaskResponse *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
uint32 HandleGetAllValuesForAttribute(game_utilities::v2::client::GetAllValuesForAttributeRequest const *request, game_utilities::v2::client::GetAllValuesForAttributeResponse *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
GameUtilities(Session *session)
std::string GetClientInfo() const
Minutes GetTimezoneOffset() const
uint32 GetAccountId() const
std::array< uint8, 32 > GetClientSecret() const
LastPlayedCharacterInfo const * GetLastPlayedCharacter(std::string_view subRegion) const
void SetClientInfo(uint32 gameAccountId, ClientBuild::VariantId buildVariant, std::array< uint8, 32 > const &clientSecret)
ClientBuild::VariantId GetBuildVariant() const
std::string const & GetLocale() const
std::string const & GetOS() const
boost::asio::ip::address const & GetRemoteIpAddress() const
GameAccountInfo const * GetGameAccountInfo() const
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setUInt8(uint8 index, uint8 value)
Battlenet::Services::Variant FromProto(bgs::protocol::Variant const &from)
void ToProto(Battlenet::Services::Variant const &from, bgs::protocol::Variant *to)
Battlenet::Services::Variant FromProto(bgs::protocol::v2::Variant const &from)
void ToProto(Battlenet::Services::Variant const &from, bgs::protocol::v2::Variant *to)
std::variant< bool, int64, double, std::string, std::vector< uint8 >, uint64 > Variant
TC_SHARED_API std::string Serialize(google::protobuf::Message const &message)
TC_SHARED_API bool Deserialize(std::string_view json, google::protobuf::Message *message)
AccountTypes SecurityLevel
bool IsPermanenetlyBanned
std::unordered_map< uint32, uint8 > CharacterCounts
ClientBuild::Platform::Id Platform
std::vector< uint8 > JoinSecret
std::vector< uint8 > JoinTicket
std::vector< uint8 > ServerAddresses
static constexpr T GetHash(std::span< V, Extent > data) noexcept