/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* 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 .
*/
#include "WorldserverGameUtilitiesService.h"
#include "BattlenetRpcErrorCodes.h"
#include "IpAddress.h"
#include "Log.h"
#include "MapUtils.h"
#include "ProtobufJSON.h"
#include "RealmList.h"
#include "RealmList.pb.h"
#include
std::unordered_map const Battlenet::Services::GameUtilitiesService::ClientRequestHandlers =
{
{ "Command_RealmListRequest_v1", &GameUtilitiesService::HandleRealmListRequest },
{ "Command_RealmJoinRequest_v1", &GameUtilitiesService::HandleRealmJoinRequest }
};
Battlenet::Services::GameUtilitiesService::GameUtilitiesService(WorldSession* session) : BaseService(session)
{
}
uint32 Battlenet::Services::GameUtilitiesService::HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response, std::function& /*continuation*/)
{
Attribute const* command = nullptr;
std::unordered_map params;
auto removeSuffix = [](std::string const& string) -> std::string
{
size_t pos = string.rfind('_');
if (pos != std::string::npos)
return string.substr(0, pos);
return string;
};
for (int32 i = 0; i < request->attribute_size(); ++i)
{
Attribute const& attr = request->attribute(i);
if (strstr(attr.name().c_str(), "Command_") == attr.name().c_str())
{
command = &attr;
params[removeSuffix(attr.name())] = &attr.value();
}
else
params[attr.name()] = &attr.value();
}
if (!command)
{
TC_LOG_ERROR("session.rpc", "{} sent ClientRequest with no command.", GetCallerInfo());
return ERROR_RPC_MALFORMED_REQUEST;
}
auto itr = ClientRequestHandlers.find(removeSuffix(command->name()));
if (itr == ClientRequestHandlers.end())
{
TC_LOG_ERROR("session.rpc", "{} sent ClientRequest with unknown command {}.", GetCallerInfo(), removeSuffix(command->name()));
return ERROR_RPC_NOT_IMPLEMENTED;
}
return (this->*itr->second)(params, response);
}
uint32 Battlenet::Services::GameUtilitiesService::HandleRealmListRequest(std::unordered_map const& params, game_utilities::v1::ClientResponse* response)
{
std::string subRegionId;
if (Variant const* subRegion = Trinity::Containers::MapGetValuePtr(params, "Command_RealmListRequest_v1"))
subRegionId = subRegion->string_value();
std::vector compressed = sRealmList->GetRealmList(_session->GetClientBuild(), _session->GetSecurity(), 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(compressed.data()) = json.length() + 1;
if (compress(compressed.data() + 4, &compressedLength, reinterpret_cast(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::Services::GameUtilitiesService::HandleRealmJoinRequest(std::unordered_map const& params, game_utilities::v1::ClientResponse* response)
{
if (Variant const* realmAddress = Trinity::Containers::MapGetValuePtr(params, "Param_RealmAddress"))
return sRealmList->JoinRealm(uint32(realmAddress->uint_value()), _session->GetClientBuild(), _session->GetClientBuildVariant(),
Trinity::Net::make_address(_session->GetRemoteAddress()), _session->GetRealmListSecret(), _session->GetSessionDbcLocale(),
_session->GetOS(), _session->GetTimezoneOffset(), _session->GetAccountName(), _session->GetSecurity(), response);
return ERROR_WOW_SERVICES_INVALID_JOIN_TICKET;
}
uint32 Battlenet::Services::GameUtilitiesService::HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response, std::function& /*continuation*/)
{
if (request->attribute_key().find("Command_RealmListRequest_v1") == 0)
{
sRealmList->WriteSubRegions(response);
return ERROR_OK;
}
return ERROR_RPC_NOT_IMPLEMENTED;
}