Core: Updated to 6.2.4

* Rewrite bnetserver for new authentication protocol
This commit is contained in:
Shauren
2016-03-28 17:12:57 +02:00
parent 619669c620
commit dde620c402
85 changed files with 9688 additions and 4976 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
DROP TABLE IF EXISTS `battlenet_components`;
DROP TABLE IF EXISTS `battlenet_modules`;
DROP TABLE IF EXISTS `account_last_played_character`;
CREATE TABLE `account_last_played_character` (
`accountId` int(10) unsigned NOT NULL,
`region` tinyint(3) unsigned NOT NULL,
`battlegroup` tinyint(3) unsigned NOT NULL,
`realmId` int(10) unsigned,
`characterName` varchar(12),
`characterGUID` bigint(20) unsigned,
`lastPlayedTime` int(10) unsigned,
PRIMARY KEY(`accountId`,`region`,`battlegroup`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `battlenet_accounts`
DROP `s`,
DROP `v`,
DROP `sessionKey`;
UPDATE `realmlist` SET `gamebuild`=21355 WHERE `gamebuild`=20726;

View File

@@ -1,59 +0,0 @@
/*
* 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 "AuthCodes.h"
#include "Define.h"
#include <vector>
namespace AuthHelper
{
// List of client builds for verbose version info in realmlist packet
static std::vector<RealmBuildInfo> const ClientBuilds =
{
{ 20726, 6, 2, 3, ' ' },
{ 20574, 6, 2, 2, 'a' },
{ 20490, 6, 2, 2, 'a' },
{ 15595, 4, 3, 4, ' ' },
{ 14545, 4, 2, 2, ' ' },
{ 13623, 4, 0, 6, 'a' },
{ 13930, 3, 3, 5, 'a' }, // 3.3.5a China Mainland build
{ 12340, 3, 3, 5, 'a' },
{ 11723, 3, 3, 3, 'a' },
{ 11403, 3, 3, 2, ' ' },
{ 11159, 3, 3, 0, 'a' },
{ 10505, 3, 2, 2, 'a' },
{ 9947, 3, 1, 3, ' ' },
{ 8606, 2, 4, 3, ' ' },
{ 6141, 1, 12, 3, ' ' },
{ 6005, 1, 12, 2, ' ' },
{ 5875, 1, 12, 1, ' ' },
};
RealmBuildInfo const* GetBuildInfo(int build)
{
for (std::size_t i = 0; i < ClientBuilds.size(); ++i)
if (ClientBuilds[i].Build == build)
return &ClientBuilds[i];
return nullptr;
}
bool IsBuildSupportingBattlenet(int build)
{
return build >= 15595;
}
}

View File

@@ -1,162 +0,0 @@
/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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 _AUTHCODES_H
#define _AUTHCODES_H
enum GameAccountFlags
{
GAMEACCOUNT_FLAG_GM = 0x00000001,
GAMEACCOUNT_FLAG_NOKICK = 0x00000002,
GAMEACCOUNT_FLAG_COLLECTOR = 0x00000004,
GAMEACCOUNT_FLAG_WOW_TRIAL = 0x00000008,
GAMEACCOUNT_FLAG_CANCELLED = 0x00000010,
GAMEACCOUNT_FLAG_IGR = 0x00000020,
GAMEACCOUNT_FLAG_WHOLESALER = 0x00000040,
GAMEACCOUNT_FLAG_PRIVILEGED = 0x00000080,
GAMEACCOUNT_FLAG_EU_FORBID_ELV = 0x00000100,
GAMEACCOUNT_FLAG_EU_FORBID_BILLING = 0x00000200,
GAMEACCOUNT_FLAG_WOW_RESTRICTED = 0x00000400,
GAMEACCOUNT_FLAG_PARENTAL_CONTROL = 0x00000800,
GAMEACCOUNT_FLAG_REFERRAL = 0x00001000,
GAMEACCOUNT_FLAG_BLIZZARD = 0x00002000,
GAMEACCOUNT_FLAG_RECURRING_BILLING = 0x00004000,
GAMEACCOUNT_FLAG_NOELECTUP = 0x00008000,
GAMEACCOUNT_FLAG_KR_CERTIFICATE = 0x00010000,
GAMEACCOUNT_FLAG_EXPANSION_COLLECTOR = 0x00020000,
GAMEACCOUNT_FLAG_DISABLE_VOICE = 0x00040000,
GAMEACCOUNT_FLAG_DISABLE_VOICE_SPEAK = 0x00080000,
GAMEACCOUNT_FLAG_REFERRAL_RESURRECT = 0x00100000,
GAMEACCOUNT_FLAG_EU_FORBID_CC = 0x00200000,
GAMEACCOUNT_FLAG_OPENBETA_DELL = 0x00400000,
GAMEACCOUNT_FLAG_PROPASS = 0x00800000,
GAMEACCOUNT_FLAG_PROPASS_LOCK = 0x01000000,
GAMEACCOUNT_FLAG_PENDING_UPGRADE = 0x02000000,
GAMEACCOUNT_FLAG_RETAIL_FROM_TRIAL = 0x04000000,
GAMEACCOUNT_FLAG_EXPANSION2_COLLECTOR = 0x08000000,
GAMEACCOUNT_FLAG_OVERMIND_LINKED = 0x10000000,
GAMEACCOUNT_FLAG_DEMOS = 0x20000000,
GAMEACCOUNT_FLAG_DEATH_KNIGHT_OK = 0x40000000,
};
namespace Battlenet
{
enum AuthResult
{
AUTH_OK = 0,
AUTH_INTERNAL_ERROR = 100,
AUTH_CORRUPTED_MODULE = 101,
AUTH_NO_BATTLETAGS = 102,
AUTH_BAD_SERVER_PROOF = 103,
AUTH_UNKNOWN_ACCOUNT = 104,
AUTH_CLOSED = 105,
AUTH_LOGIN_TIMEOUT = 106,
AUTH_NO_GAME_ACCOUNTS = 107,
AUTH_INVALID_TOKEN = 108,
AUTH_INVALID_PROGRAM = 109,
AUTH_INVALID_OS = 110,
AUTH_UNSUPPORTED_LANGUAGE = 111,
AUTH_REGION_BAD_VERSION = 112,
AUTH_TEMP_OUTAGE = 113,
AUTH_CANT_DOWNLOAD_MODULE = 114,
AUTH_DUPLICATE_LOGON = 115,
AUTH_BAD_CREDENTIALS_2 = 116,
AUTH_VERSION_CHECK_SUCCEEDED = 117,
AUTH_BAD_VERSION_HASH = 118,
AUTH_CANT_RETRIEVE_PORTAL_LIST = 119,
AUTH_DARK_PORTAL_DOES_NOT_EXIST = 120,
AUTH_DARK_PORTAL_FILE_CORRUPTED = 121,
AUTH_BATTLENET_MAINTENANCE = 122,
AUTH_LOGON_TOO_FAST = 123,
AUTH_USE_GRUNT_LOGON = 124,
AUTH_NO_GAME_ACCOUNTS_IN_REGION = 140,
AUTH_ACCOUNT_LOCKED = 141,
LOGIN_SERVER_BUSY = 200,
LOGIN_NO_GAME_ACCOUNT = 201,
LOGIN_BANNED = 202,
LOGIN_SUSPENDED = 203,
LOGIN_GAME_ACCOUNT_LOCKED = 204,
LOGIN_ALREADY_ONLINE = 205,
LOGIN_NOTIME = 206,
LOGIN_EXPIRED = 207,
LOGIN_EXPIRED_2 = 208,
LOGIN_PARENTALCONTROL = 209,
LOGIN_TRIAL_EXPIRED = 210,
LOGIN_ANTI_INDULGENCE = 211,
LOGIN_INCORRECT_REGION = 212,
LOGIN_LOCKED_ENFORCED = 213,
LOGIN_CHARGEBACK = 214,
LOGIN_IGR_WITHOUT_BNET = 215,
LOGIN_UNLOCKABLE_LOCK = 216,
LOGIN_IGR_REQUIRED = 217,
LOGIN_PAYMENT_CHANGED = 218,
LOGIN_INVALID_PAYMENT = 219,
LOGIN_INVALID_ACCOUNT_STATE = 220
};
namespace Wow
{
enum AuthResult
{
WOW_SUCCESS = 0,
WOW_FAIL_BANNED = 3,
WOW_FAIL_UNKNOWN_ACCOUNT = 4,
WOW_FAIL_INCORRECT_PASSWORD = 5,
WOW_FAIL_ALREADY_ONLINE = 6,
WOW_FAIL_NO_TIME = 7,
WOW_FAIL_DB_BUSY = 8,
WOW_FAIL_VERSION_INVALID = 9,
WOW_FAIL_VERSION_UPDATE = 10,
WOW_FAIL_INVALID_SERVER = 11,
WOW_FAIL_SUSPENDED = 12,
WOW_FAIL_FAIL_NOACCESS = 13,
WOW_SUCCESS_SURVEY = 14,
WOW_FAIL_PARENTCONTROL = 15,
WOW_FAIL_LOCKED_ENFORCED = 16,
WOW_FAIL_TRIAL_ENDED = 17,
WOW_FAIL_OVERMIND_CONVERTED = 18,
WOW_FAIL_ANTI_INDULGENCE = 19,
WOW_FAIL_EXPIRED = 20,
WOW_FAIL_NO_GAME_ACCOUNT = 21,
WOW_FAIL_BILLING_LOCK = 22,
WOW_FAIL_IGR_WITHOUT_BNET = 23,
WOW_FAIL_AA_LOCK = 24,
WOW_FAIL_UNLOCKABLE_LOCK = 25,
WOW_FAIL_MUST_USE_BNET = 26,
WOW_FAIL_OTHER = 255,
};
}
}
struct RealmBuildInfo
{
int Build;
int MajorVersion;
int MinorVersion;
int BugfixVersion;
int HotfixVersion;
};
namespace AuthHelper
{
RealmBuildInfo const* GetBuildInfo(int build);
bool IsBuildSupportingBattlenet(int build);
}
#endif

View File

@@ -1,42 +0,0 @@
/*
* 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 "BattlenetPacketCrypt.h"
#include "Cryptography/HmacHash.h"
#include "Cryptography/BigNumber.h"
Battlenet::PacketCrypt::PacketCrypt() : ::PacketCrypt(SHA256_DIGEST_LENGTH)
{
}
void Battlenet::PacketCrypt::Init(BigNumber* K)
{
uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0x68, 0xE0, 0xC7, 0x2E, 0xDD, 0xD6, 0xD2, 0xF3, 0x1E, 0x5A, 0xB1, 0x55, 0xB1, 0x8B, 0x63, 0x1E };
uint8 ClientDecryptionKey[SEED_KEY_SIZE] = { 0xDE, 0xA9, 0x65, 0xAE, 0x54, 0x3A, 0x1E, 0x93, 0x9E, 0x69, 0x0C, 0xAA, 0x68, 0xDE, 0x78, 0x39 };
HmacSha256 serverEncryptHmac(K->GetNumBytes(), K->AsByteArray().get());
serverEncryptHmac.UpdateData(ServerEncryptionKey, SEED_KEY_SIZE);
serverEncryptHmac.Finalize();
HmacSha256 clientDecryptHmac(K->GetNumBytes(), K->AsByteArray().get());
clientDecryptHmac.UpdateData(ClientDecryptionKey, SEED_KEY_SIZE);
clientDecryptHmac.Finalize();
_clientDecrypt.Init(clientDecryptHmac.GetDigest());
_serverEncrypt.Init(serverEncryptHmac.GetDigest());
_initialized = true;
}

View File

@@ -16,9 +16,9 @@ CollectSourceFiles(
# Exclude
${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders)
if( WIN32 )
if (WIN32)
list(APPEND PRIVATE_SOURCES ${sources_windows})
if ( MSVC )
if (MSVC)
list(APPEND PRIVATE_SOURCES bnetserver.rc)
endif()
endif()
@@ -35,7 +35,7 @@ add_executable(bnetserver
${PRIVATE_PCH_SOURCE}
)
if( NOT WIN32 )
if (NOT WIN32)
set_target_properties(bnetserver PROPERTIES
COMPILE_DEFINITIONS _TRINITY_BNET_CONFIG="${CONF_DIR}/bnetserver.conf"
)
@@ -62,26 +62,32 @@ set_target_properties(bnetserver
FOLDER
"server")
if( WIN32 )
if ( MSVC )
if (WIN32)
if (MSVC)
add_custom_command(TARGET bnetserver
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.conf.dist ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.cert.pem ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.key.pem ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/
)
elseif ( MINGW )
elseif (MINGW)
add_custom_command(TARGET bnetserver
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.conf.dist ${CMAKE_BINARY_DIR}/bin/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.cert.pem ${CMAKE_BINARY_DIR}/bin/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.key.pem ${CMAKE_BINARY_DIR}/bin/
)
endif()
endif()
if( UNIX )
if (UNIX)
install(TARGETS bnetserver DESTINATION bin)
install(FILES bnetserver.conf.dist DESTINATION ${CONF_DIR})
elseif( WIN32 )
install(FILES bnetserver.conf.dist DESTINATION ${CONF_DIR})
install(FILES bnetserver.cert.pem bnetserver.key.pem DESTINATION bin)
elseif (WIN32)
install(TARGETS bnetserver DESTINATION "${CMAKE_INSTALL_PREFIX}")
install(FILES bnetserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}")
install(FILES bnetserver.cert.pem bnetserver.key.pem DESTINATION "${CMAKE_INSTALL_PREFIX}")
endif()
# Generate precompiled header

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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
@@ -24,25 +23,17 @@
* authentication server
*/
#include "ComponentManager.h"
#include "ModuleManager.h"
#include "SessionManager.h"
#include "Common.h"
#include "Config.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "AppenderDB.h"
#include "ProcessPriority.h"
#include "RealmList.h"
#include "GitRevision.h"
#include "Util.h"
#include "SslContext.h"
#include "DatabaseLoader.h"
#include <cstdlib>
#include "LoginRESTService.h"
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/program_options.hpp>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <google/protobuf/stubs/common.h>
using boost::asio::ip::tcp;
using namespace boost::program_options;
@@ -92,6 +83,8 @@ int main(int argc, char** argv)
if (vm.count("help") || vm.count("version"))
return 0;
GOOGLE_PROTOBUF_VERIFY_VERSION;
#if PLATFORM == PLATFORM_WINDOWS
if (configService.compare("install") == 0)
return WinServiceInstall() ? 0 : 1;
@@ -135,15 +128,18 @@ int main(int argc, char** argv)
}
}
if (!Battlenet::SslContext::Initialize())
{
TC_LOG_ERROR("server.bnetserver", "Failed to initialize SSL context");
return 1;
}
// Initialize the database connection
if (!StartDB())
return 1;
_ioService = new boost::asio::io_service();
// Get the list of realms for the server
sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10));
// Start the listening port (acceptor) for auth connections
int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119);
if (bnport < 0 || bnport > 0xFFFF)
@@ -154,6 +150,17 @@ int main(int argc, char** argv)
return 1;
}
if (!sLoginService.Start(*_ioService))
{
StopDB();
delete _ioService;
TC_LOG_ERROR("server.bnetserver", "Failed to initialize login service");
return 1;
}
// Get the list of realms for the server
sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10));
std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");
sSessionMgr.StartNetwork(*_ioService, bindIp, bnport);
@@ -179,9 +186,6 @@ int main(int argc, char** argv)
_banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(_banExpiryCheckInterval));
_banExpiryCheckTimer->async_wait(BanExpiryHandler);
sComponentMgr->Load();
sModuleMgr->Load();
#if PLATFORM == PLATFORM_WINDOWS
if (m_ServiceStatus != -1)
{
@@ -197,6 +201,8 @@ int main(int argc, char** argv)
_banExpiryCheckTimer->cancel();
_dbPingTimer->cancel();
sLoginService.Stop();
sSessionMgr.StopNetwork();
sRealmList->Close();
@@ -211,6 +217,7 @@ int main(int argc, char** argv)
delete _banExpiryCheckTimer;
delete _dbPingTimer;
delete _ioService;
google::protobuf::ShutdownProtobufLibrary();
return 0;
}

View File

@@ -1,428 +0,0 @@
/*
* 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 "AuthenticationPackets.h"
#include "Session.h"
#include "Util.h"
std::string Battlenet::Authentication::RequestCommon::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::RequestCommon" << std::endl;
APPEND_FIELD(stream, Program);
APPEND_FIELD(stream, Platform);
APPEND_FIELD(stream, Locale);
APPEND_FIELD(stream, Versions);
return stream.str();
}
void Battlenet::Authentication::ResumeRequest::Read()
{
Common.Program = _stream.ReadFourCC();
Common.Platform = _stream.ReadFourCC();
Common.Locale = _stream.ReadFourCC();
Common.Versions.resize(_stream.Read<uint32>(6));
for (size_t i = 0; i < Common.Versions.size(); ++i)
{
Version::Record& component = Common.Versions[i];
component.ProgramId = _stream.ReadFourCC();
component.Component = _stream.ReadFourCC();
component.Version = _stream.Read<uint32>(32);
}
Account = _stream.ReadString(9, 3);
GameAccountRegion = _stream.Read<uint8>(8);
GameAccountName = _stream.ReadString(5, 1);
}
std::string Battlenet::Authentication::ResumeRequest::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::ResumeRequest" << std::endl;
APPEND_FIELD(stream, Common);
APPEND_FIELD(stream, Account);
APPEND_FIELD(stream, GameAccountRegion);
APPEND_FIELD(stream, GameAccountName);
return stream.str();
}
void Battlenet::Authentication::ResumeRequest::CallHandler(Session* session)
{
session->HandleResumeRequest(*this);
}
Battlenet::Authentication::ProofResponse::~ProofResponse()
{
for (size_t i = 0; i < Response.size(); ++i)
delete Response[i];
}
void Battlenet::Authentication::ProofResponse::Read()
{
Response.resize(_stream.Read<uint32>(3));
for (size_t i = 0; i < Response.size(); ++i)
{
BitStream*& dataStream = Response[i];
dataStream = new BitStream(_stream.Read<uint32>(10));
memcpy(dataStream->GetBuffer(), _stream.ReadBytes(dataStream->GetSize()).get(), dataStream->GetSize());
}
}
std::string Battlenet::Authentication::ProofResponse::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::ProofRequest" << std::endl;
APPEND_FIELD(stream, Response.size());
return stream.str();
}
void Battlenet::Authentication::ProofResponse::CallHandler(Session* session)
{
session->HandleProofResponse(*this);
}
void Battlenet::Authentication::LogonRequest3::Read()
{
Common.Program = _stream.ReadFourCC();
Common.Platform = _stream.ReadFourCC();
Common.Locale = _stream.ReadFourCC();
Common.Versions.resize(_stream.Read<uint32>(6));
for (size_t i = 0; i < Common.Versions.size(); ++i)
{
Version::Record& component = Common.Versions[i];
component.ProgramId = _stream.ReadFourCC();
component.Component = _stream.ReadFourCC();
component.Version = _stream.Read<uint32>(32);
}
if (_stream.Read<uint32>(1))
Account = _stream.ReadString(9, 3);
Compatibility = _stream.Read<uint64>(64);
}
std::string Battlenet::Authentication::LogonRequest3::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::LogonRequest3" << std::endl;
APPEND_FIELD(stream, Common);
APPEND_FIELD(stream, Account);
APPEND_FIELD(stream, Compatibility);
return stream.str();
}
void Battlenet::Authentication::LogonRequest3::CallHandler(Session* session)
{
session->HandleLogonRequest(*this);
}
Battlenet::Authentication::LogonResponse::~LogonResponse()
{
for (ModuleInfo* m : Result.Success.FinalRequest)
delete m;
}
void Battlenet::Authentication::LogonResponse::Write()
{
_stream.Write(Result.Type, 1);
if (Result.Type == ResultType::SUCCESS)
{
_stream.Write(Result.Success.FinalRequest.size(), 3);
for (size_t i = 0; i < Result.Success.FinalRequest.size(); ++i)
{
ModuleInfo* info = Result.Success.FinalRequest[i];
_stream.WriteBytes(info->Handle.Type.c_str(), 4);
_stream.WriteFourCC(info->Handle.Region);
_stream.WriteBytes(info->Handle.ModuleId, 32);
_stream.Write(info->DataSize, 10);
_stream.WriteBytes(info->Data, info->DataSize);
}
_stream.Write(Result.Success.PingTimeout + std::numeric_limits<int32>::min(), 32);
_stream.Write(Result.Success.RegulatorRules.is_initialized(), 1);
if (Result.Success.RegulatorRules.is_initialized())
{
_stream.Write(Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET, 1);
if (Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET)
{
_stream.Write(Result.Success.RegulatorRules->LeakyBucket.Threshold, 32);
_stream.Write(Result.Success.RegulatorRules->LeakyBucket.Rate, 32);
}
}
_stream.WriteString(Result.Success.FullName.GivenName, 8);
_stream.WriteString(Result.Success.FullName.Surname, 8);
_stream.Write(Result.Success.AccountId, 32);
_stream.Write(Result.Success.Region, 8);
_stream.Write(Result.Success.Flags, 64);
_stream.Write(Result.Success.GameAccountRegion, 8);
_stream.WriteString(Result.Success.GameAccountName, 5, -1);
_stream.Write(Result.Success.GameAccountFlags, 64);
_stream.Write(Result.Success.LogonFailures, 32);
}
else
{
_stream.Write(Result.Failure.Strings.is_initialized(), 1);
if (Result.Failure.Strings.is_initialized())
{
_stream.WriteBytes(Result.Failure.Strings->Type.c_str(), 4);
_stream.WriteFourCC(Result.Failure.Strings->Region);
_stream.WriteBytes(Result.Failure.Strings->ModuleId, 32);
}
_stream.Write(Result.Failure.Result.Type, 2);
if (Result.Failure.Result.Type == FailureType::FAILURE)
{
_stream.Write(Result.Failure.Result.Failure.Error, 16);
_stream.Write(Result.Failure.Result.Failure.Wait + std::numeric_limits<int32>::min(), 32);
}
}
_stream.Write(Raf.is_initialized(), 1);
if (Raf.is_initialized())
{
_stream.Write(Raf->size(), 10);
_stream.WriteBytes(Raf->data(), Raf->size());
}
}
std::string Battlenet::Authentication::LogonResponse::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::LogonResponse" << std::endl;
APPEND_FIELD(stream, Result);
APPEND_FIELD(stream, Raf);
return stream.str();
}
std::string Battlenet::Authentication::FailureType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::FailureType" << std::endl;
APPEND_FIELD(stream, Strings);
APPEND_FIELD(stream, Result);
return stream.str();
}
std::string Battlenet::Authentication::FailureType::ResultType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::ResponseFailure::Result" << std::endl;
switch (Type)
{
case UPDATE:
APPEND_FIELD(stream, Update);
break;
case FAILURE:
APPEND_FIELD(stream, Failure);
break;
case VERSION_CHECK_DISCONNECT:
APPEND_FIELD(stream, VersionCheckDisconnect);
break;
default:
break;
}
return stream.str();
}
std::string Battlenet::Authentication::FailureType::ResultType::UpdateType::ToString() const
{
return "Battlenet::Authentication::ResponseFailure::Result::Update";
}
std::string Battlenet::Authentication::FailureType::ResultType::FailureType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::ResponseFailure::Result::Failure" << std::endl;
APPEND_FIELD(stream, Error);
APPEND_FIELD(stream, Wait);
return stream.str();
}
std::string Battlenet::Authentication::FailureType::ResultType::VersionCheckDisconnectType::ToString() const
{
return "Battlenet::Authentication::ResponseFailure::Result::VersionCheckDisconnect";
}
std::string Battlenet::Authentication::Regulator::NoneType::ToString() const
{
return "Battlenet::Regulator::None";
}
std::string Battlenet::Authentication::Regulator::LeakyBucketType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Regulator::LeakyBucket" << std::endl;
APPEND_FIELD(stream, Threshold);
APPEND_FIELD(stream, Rate);
return stream.str();
}
std::string Battlenet::Authentication::Regulator::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Regulator" << std::endl;
switch (Type)
{
case NONE:
APPEND_FIELD(stream, None);
break;
case LEAKY_BUCKET:
APPEND_FIELD(stream, LeakyBucket);
break;
default:
break;
}
return stream.str();
}
std::string Battlenet::Authentication::LogonResponse::ResultType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::LogonResponse::Result" << std::endl;
switch (Type)
{
case SUCCESS:
APPEND_FIELD(stream, Success);
break;
case FAILURE:
APPEND_FIELD(stream, Failure);
break;
default:
break;
}
return stream.str();
}
std::string Battlenet::Authentication::LogonResponse::ResultType::SuccessType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::LogonResponse::Result::Success" << std::endl;
APPEND_FIELD(stream, FinalRequest);
APPEND_FIELD(stream, PingTimeout);
APPEND_FIELD(stream, RegulatorRules);
APPEND_FIELD(stream, FullName);
APPEND_FIELD(stream, AccountId);
APPEND_FIELD(stream, Region);
APPEND_FIELD(stream, Flags);
APPEND_FIELD(stream, GameAccountRegion);
APPEND_FIELD(stream, GameAccountName);
APPEND_FIELD(stream, GameAccountFlags);
APPEND_FIELD(stream, LogonFailures);
return stream.str();
}
void Battlenet::Authentication::LogonResponse::SetAuthResult(AuthResult result)
{
Result.Type = result != AUTH_OK ? ResultType::FAILURE : ResultType::SUCCESS;
Result.Failure.Result.Failure.Error = result;
}
Battlenet::Authentication::ResumeResponse::~ResumeResponse()
{
for (ModuleInfo* m : Result.Success.FinalRequest)
delete m;
}
void Battlenet::Authentication::ResumeResponse::Write()
{
_stream.Write(Result.Type, 1);
if (Result.Type == ResultType::SUCCESS)
{
_stream.Write(Result.Success.FinalRequest.size(), 3);
for (size_t i = 0; i < Result.Success.FinalRequest.size(); ++i)
{
ModuleInfo* info = Result.Success.FinalRequest[i];
_stream.WriteBytes(info->Handle.Type.c_str(), 4);
_stream.WriteFourCC(info->Handle.Region);
_stream.WriteBytes(info->Handle.ModuleId, 32);
_stream.Write(info->DataSize, 10);
_stream.WriteBytes(info->Data, info->DataSize);
}
_stream.Write(Result.Success.PingTimeout + std::numeric_limits<int32>::min(), 32);
_stream.Write(Result.Success.RegulatorRules.is_initialized(), 1);
if (Result.Success.RegulatorRules.is_initialized())
{
_stream.Write(Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET, 1);
if (Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET)
{
_stream.Write(Result.Success.RegulatorRules->LeakyBucket.Threshold, 32);
_stream.Write(Result.Success.RegulatorRules->LeakyBucket.Rate, 32);
}
}
}
else
{
_stream.Write(Result.Failure.Strings.is_initialized(), 1);
if (Result.Failure.Strings.is_initialized())
{
_stream.WriteBytes(Result.Failure.Strings->Type.c_str(), 4);
_stream.WriteFourCC(Result.Failure.Strings->Region);
_stream.WriteBytes(Result.Failure.Strings->ModuleId, 32);
}
_stream.Write(Result.Failure.Result.Type, 2);
if (Result.Failure.Result.Type == FailureType::FAILURE)
{
_stream.Write(Result.Failure.Result.Failure.Error, 16);
_stream.Write(Result.Failure.Result.Failure.Wait + std::numeric_limits<int32>::min(), 32);
}
}
}
std::string Battlenet::Authentication::ResumeResponse::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::ResumeResponse" << std::endl;
return stream.str();
}
void Battlenet::Authentication::ResumeResponse::SetAuthResult(AuthResult result)
{
Result.Type = result != AUTH_OK ? ResultType::FAILURE : ResultType::SUCCESS;
Result.Failure.Result.Failure.Error = result;
}
Battlenet::Authentication::ProofRequest::~ProofRequest()
{
for (size_t i = 0; i < Modules.size(); ++i)
delete Modules[i];
}
void Battlenet::Authentication::ProofRequest::Write()
{
_stream.Write(Modules.size(), 3);
for (ModuleInfo const* info : Modules)
{
_stream.WriteBytes(info->Handle.Type.c_str(), 4);
_stream.WriteFourCC(info->Handle.Region);
_stream.WriteBytes(info->Handle.ModuleId, 32);
_stream.Write(info->DataSize, 10);
_stream.WriteBytes(info->Data, info->DataSize);
}
}
std::string Battlenet::Authentication::ProofRequest::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Authentication::ProofRequest" << std::endl;
APPEND_FIELD(stream, Modules);
return stream.str();
}

View File

@@ -1,267 +0,0 @@
/*
* 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 AuthenticationPackets_h__
#define AuthenticationPackets_h__
#include "PacketsBase.h"
#include "ComponentManager.h"
#include "ModuleManager.h"
namespace Battlenet
{
namespace Authentication
{
enum Opcode
{
CMSG_LOGON_REQUEST = 0x0, // Deprecated
CMSG_RESUME_REQUEST = 0x1,
CMSG_PROOF_RESPONSE = 0x2,
CMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_REQUEST_2 = 0x8, // Not implemented
CMSG_LOGON_REQUEST_3 = 0x9,
CMSG_SINGLE_SIGN_ON_REQUEST_3 = 0xA, // Not implemented
SMSG_LOGON_RESPONSE = 0x0,
SMSG_RESUME_RESPONSE = 0x1,
SMSG_PROOF_REQUEST = 0x2,
SMSG_PATCH = 0x3, // Not implemented
SMSG_AUTHORIZED_LICENSES = 0x4, // Not implemented
SMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_RESPONSE_2 = 0x8 // Not implemented
};
struct RequestCommon : public PrintableComponent
{
std::string Program;
std::string Platform;
std::string Locale;
std::vector<Version::Record> Versions;
std::string ToString() const override;
};
class ResumeRequest final : public ClientPacket
{
public:
ResumeRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_RESUME_REQUEST, AUTHENTICATION) && "Invalid packet header for ResumeRequest");
}
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
RequestCommon Common;
std::string Account;
uint8 GameAccountRegion = 0;
std::string GameAccountName;
};
class ProofResponse final : public ClientPacket
{
public:
ProofResponse(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_PROOF_RESPONSE, AUTHENTICATION) && "Invalid packet header for ProofResponse");
}
~ProofResponse();
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
std::vector<BitStream*> Response;
};
class LogonRequest3 final : public ClientPacket
{
public:
LogonRequest3(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_LOGON_REQUEST_3, AUTHENTICATION) && "Invalid packet header for LogonRequest3");
}
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
RequestCommon Common;
std::string Account;
uint64 Compatibility = 0;
};
struct FailureType : public PrintableComponent
{
Optional<Cache::Handle> Strings;
enum
{
UPDATE = 0,
FAILURE = 1,
VERSION_CHECK_DISCONNECT = 2
};
struct ResultType : public PrintableComponent
{
int32 Type = FAILURE;
struct UpdateType : public PrintableComponent
{
std::string ToString() const override;
} Update;
struct FailureType : public PrintableComponent
{
AuthResult Error = AUTH_OK;
int32 Wait = 0;
std::string ToString() const override;
} Failure;
struct VersionCheckDisconnectType : public PrintableComponent
{
std::string ToString() const override;
} VersionCheckDisconnect;
std::string ToString() const override;
} Result;
std::string ToString() const override;
};
struct Regulator : public PrintableComponent
{
enum
{
NONE = 0,
LEAKY_BUCKET = 1
};
int32 Type = LEAKY_BUCKET;
struct NoneType : public PrintableComponent
{
std::string ToString() const override;
} None;
struct LeakyBucketType : public PrintableComponent
{
uint32 Threshold = 25000000;
uint32 Rate = 1000;
std::string ToString() const override;
} LeakyBucket;
std::string ToString() const override;
};
class LogonResponse final : public ServerPacket
{
public:
LogonResponse() : ServerPacket(PacketHeader(SMSG_LOGON_RESPONSE, AUTHENTICATION))
{
}
~LogonResponse();
void Write() override;
std::string ToString() const override;
void SetAuthResult(AuthResult result);
struct ResultType : public PrintableComponent
{
enum
{
SUCCESS = 0,
FAILURE = 1
};
int32 Type = SUCCESS;
struct SuccessType : public PrintableComponent
{
std::vector<ModuleInfo*> FinalRequest;
int32 PingTimeout = 120000;
Optional<Regulator> RegulatorRules;
Battlenet::Account::FullName FullName;
uint32 AccountId = 0;
uint8 Region = 2;
uint64 Flags = 0;
uint8 GameAccountRegion = 2;
std::string GameAccountName;
uint64 GameAccountFlags = 0;
uint32 LogonFailures = 0;
std::string ToString() const override;
} Success;
FailureType Failure;
std::string ToString() const override;
} Result;
Optional<std::vector<uint8>> Raf;
};
class ResumeResponse final : public ServerPacket
{
public:
ResumeResponse() : ServerPacket(PacketHeader(SMSG_RESUME_RESPONSE, AUTHENTICATION))
{
}
~ResumeResponse();
void Write() override;
std::string ToString() const override;
void SetAuthResult(AuthResult result);
struct ResultType
{
enum
{
SUCCESS = 0,
FAILURE = 1
};
int32 Type = SUCCESS;
struct SuccessType
{
std::vector<ModuleInfo*> FinalRequest;
int32 PingTimeout = 120000;
Optional<Regulator> RegulatorRules;
} Success;
FailureType Failure;
} Result;
};
class ProofRequest final : public ServerPacket
{
public:
ProofRequest() : ServerPacket(PacketHeader(SMSG_PROOF_REQUEST, AUTHENTICATION)) { }
~ProofRequest();
void Write() override;
std::string ToString() const override;
std::vector<ModuleInfo*> Modules;
};
}
}
#endif // AuthenticationPackets_h__

View File

@@ -1,258 +0,0 @@
/*
* 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 BitStream_h__
#define BitStream_h__
#include "Common.h"
#include "ByteConverter.h"
#include "MessageBuffer.h"
#include <exception>
#include <vector>
#include <type_traits>
#include <memory>
namespace Battlenet
{
union FloatToInt
{
float AsFloat;
uint32 AsInt;
};
class BitStreamPositionException : public std::exception
{
static uint32 const MessageSize = 128;
public:
BitStreamPositionException(bool read, uint32 operationSize, uint32 position, uint32 streamSize)
{
memset(_message, 0, MessageSize);
snprintf(_message, MessageSize, "Attempted to %s more bits (%u) %s stream than %s (%u)\n",
(read ? "read" : "write"),
operationSize + position,
(read ? "from" : "to"),
(read ? "exist" : "allowed"),
streamSize);
}
char const* what() const throw()
{
return _message;
}
private:
char _message[MessageSize];
};
class BitStream
{
public:
static uint32 const MaxSize = 0x4000;
// length : The maximum number of bytes to read
BitStream(uint32 length) : _writePos(length * 8), _readPos(0)
{
_buffer.resize(length, 0);
}
BitStream(MessageBuffer&& buffer) : _writePos(uint32(buffer.GetActiveSize()) << 3), _readPos(0), _buffer(buffer.Move())
{
}
BitStream() : _writePos(0), _readPos(0)
{
_buffer.reserve(0x1000);
}
void AlignToNextByte()
{
_readPos = (_readPos + 7) & ~7;
_writePos = (_writePos + 7) & ~7;
}
std::string ReadString(uint32 bitCount, int32 baseLength = 0)
{
uint32 len = Read<uint32>(bitCount) + baseLength;
AlignToNextByte();
std::string str(reinterpret_cast<char*>(&_buffer[_readPos >> 3]), len);
_readPos += len * 8;
return str;
}
std::unique_ptr<uint8[]> ReadBytes(uint32 count)
{
AlignToNextByte();
if (_readPos + count * 8 > _writePos)
throw BitStreamPositionException(true, count * 8, _readPos, _writePos);
std::unique_ptr<uint8[]> buf(new uint8[count]);
memcpy(buf.get(), &_buffer[_readPos >> 3], count);
_readPos += count * 8;
return buf;
}
float ReadFloat()
{
union
{
float AsFloat;
uint32 AsInt;
} convert;
convert.AsInt = Read<uint32>(32);
return convert.AsFloat;
}
std::string ReadFourCC()
{
uint32 fcc = Read<uint32>(32);
EndianConvertReverse(fcc);
size_t len = 4;
while (!(fcc & 0xFF) && len)
{
fcc >>= 8;
--len;
}
return std::string(reinterpret_cast<char*>(&fcc), len);
}
template<typename T>
T Read(uint32 bitCount)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type");
if (_readPos + bitCount > _writePos)
throw BitStreamPositionException(true, bitCount, _readPos, _writePos);
uint64 ret = 0;
while (bitCount != 0)
{
uint32 bitPos = (_readPos & 7);
uint32 bitsLeftInByte = 8 - bitPos;
if (bitsLeftInByte >= bitCount)
bitsLeftInByte = bitCount;
bitCount -= bitsLeftInByte;
ret |= (uint64)(_buffer[_readPos >> 3] >> bitPos & (uint32)((uint8)(1 << bitsLeftInByte) - 1)) << bitCount;
_readPos += bitsLeftInByte;
}
return static_cast<T>(ret);
}
void WriteString(std::string const& str, uint32 bitCount, int32 baseLength = 0)
{
Write(str.length() + baseLength, bitCount);
WriteBytes(str.c_str(), uint32(str.length()));
}
template<typename T>
void WriteBytes(T* data, uint32 count)
{
AlignToNextByte();
if (!count || !data)
return;
if ((_writePos >> 3) + count > MaxSize)
throw BitStreamPositionException(false, count * 8, _writePos, MaxSize * 8);
_buffer.resize(_buffer.size() + count);
memcpy(&_buffer[_writePos >> 3], data, count);
_writePos += count * 8;
}
void WriteFloat(float value)
{
union
{
float AsFloat;
uint32 AsInt;
} convert;
convert.AsFloat = value;
Write(convert.AsInt, 32);
}
void WriteFourCC(std::string const& fcc)
{
uint32 intVal = *(uint32*)fcc.c_str();
size_t len = fcc.length();
EndianConvertReverse(intVal);
// Add padding
while (len++ < 4)
intVal >>= 8;
Write(intVal, 32);
}
template<typename T>
void Write(T value, uint32 bitCount)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type");
if (_writePos + bitCount > 8 * MaxSize)
throw BitStreamPositionException(false, bitCount, _writePos, MaxSize * 8);
while (bitCount != 0)
{
uint32 bitPos = (_writePos & 7);
uint32 bitsLeftInByte = 8 - bitPos;
if (bitsLeftInByte >= bitCount)
bitsLeftInByte = bitCount;
bitCount -= bitsLeftInByte;
uint8 firstHalf = (uint8)(~(((uint8)(1 << bitsLeftInByte) - 1) << bitPos));
uint8 secondHalf = (uint8)((((uint8)(1 << bitsLeftInByte) - 1) & (uint8)(value >> bitCount)) << bitPos);
if (_buffer.size() > (_writePos >> 3))
_buffer[_writePos >> 3] = (uint8)((_buffer[_writePos >> 3] & firstHalf) | secondHalf);
else
_buffer.push_back(secondHalf);
_writePos += bitsLeftInByte;
}
}
bool IsRead() const { return _readPos >= _writePos; }
uint8* GetBuffer() { return _buffer.data(); }
uint8 const* GetBuffer() const { return _buffer.data(); }
uint32 GetReadPos() const { return _readPos; }
size_t GetSize() const { return ((_writePos + 7) & ~7) / 8; }
// These methods are meant to only be used when their corresponding actions in the client ignore the value completely
void ReadSkip(uint32 bitCount) { _readPos += bitCount; }
void WriteSkip(uint32 bitCount) { Write(0, bitCount); }
private:
uint32 _writePos;
uint32 _readPos;
std::vector<uint8> _buffer;
};
template<>
bool BitStream::Read<bool>(uint32 bitCount);
template<>
void BitStream::Write<bool>(bool value, uint32 bitCount);
}
#endif // BitStream_h__

View File

@@ -1,111 +0,0 @@
/*
* 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 "Session.h"
#include "Util.h"
#include "CachePackets.h"
void Battlenet::Cache::GetStreamItemsRequest::Read()
{
_stream.ReadSkip(31);
Token = _stream.Read<uint32>(32);
ReferenceTime = _stream.Read<int32>(32) - std::numeric_limits<int32>::min();
Direction = _stream.Read<uint8>(1);
MaxItems = _stream.Read<uint8>(6);
Locale = _stream.ReadFourCC();
Stream.Type = _stream.Read<uint8>(1);
if (Stream.Type == StreamId::DESCRIPTION)
{
Stream.Description.ItemName = _stream.ReadFourCC();
Stream.Description.Channel = _stream.ReadFourCC();
}
else
Stream.Index = _stream.Read<uint16>(16);
}
std::string Battlenet::Cache::GetStreamItemsRequest::StreamId::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Cache::GetStreamItemsRequest::StreamId" << std::endl;
if (Type == INDEX)
APPEND_FIELD(stream, Index);
else
APPEND_FIELD(stream, Description);
return stream.str();
}
std::string Battlenet::Cache::GetStreamItemsRequest::StreamId::DescriptionType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Cache::GetStreamItemsRequest::StreamId::Description" << std::endl;
APPEND_FIELD(stream, Channel);
APPEND_FIELD(stream, ItemName);
return stream.str();
}
std::string Battlenet::Cache::GetStreamItemsRequest::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Cache::GetStreamItemsRequest" << std::endl;
APPEND_FIELD(stream, Token);
APPEND_FIELD(stream, MaxItems);
APPEND_FIELD(stream, ReferenceTime);
APPEND_FIELD(stream, Direction);
APPEND_FIELD(stream, Stream);
APPEND_FIELD(stream, Locale);
return stream.str();
}
void Battlenet::Cache::GetStreamItemsRequest::CallHandler(Session* session)
{
session->HandleGetStreamItemsRequest(*this);
}
Battlenet::Cache::GetStreamItemsResponse::~GetStreamItemsResponse()
{
for (size_t i = 0; i < Items.size(); ++i)
delete Items[i];
}
void Battlenet::Cache::GetStreamItemsResponse::Write()
{
_stream.Write(Offset, 16);
_stream.Write(TotalNumItems, 16);
_stream.Write(Token, 32);
_stream.Write(Items.size(), 6);
for (ModuleInfo const* info : Items)
{
_stream.WriteBytes(info->Handle.Type.c_str(), 4);
_stream.WriteFourCC(info->Handle.Region);
_stream.WriteBytes(info->Handle.ModuleId, 32);
_stream.WriteSkip(27);
_stream.WriteBytes(info->Data, 4);
}
}
std::string Battlenet::Cache::GetStreamItemsResponse::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Cache::GetStreamItemsResponse" << std::endl;
APPEND_FIELD(stream, Items);
APPEND_FIELD(stream, Offset);
APPEND_FIELD(stream, TotalNumItems);
APPEND_FIELD(stream, Token);
return stream.str();
}

View File

@@ -1,110 +0,0 @@
/*
* 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 CachePackets_h__
#define CachePackets_h__
#include "ModuleManager.h"
#include "PacketsBase.h"
namespace Battlenet
{
namespace Cache
{
enum Opcode
{
CMSG_GATEWAY_LOOKUP_REQUEST = 0x2, // Not implemented
CMSG_CONNECT_REQUEST = 0x4, // Not implemented
CMSG_DATA_CHUNK = 0x7, // Not implemented
CMSG_GET_STREAM_ITEMS_REQUEST = 0x9,
SMSG_GATEWAY_LOOKUP_RESPONSE = 0x3, // Not implemented
SMSG_CONNECT_RESPONSE = 0x4, // Not implemented
SMSG_PUBLISH_LIST_RESPONSE = 0x7, // Not implemented
SMSG_RESULT = 0x8, // Not implemented
SMSG_GET_STREAM_ITEMS_RESPONSE = 0x9
};
class GetStreamItemsRequest final : public ClientPacket
{
public:
GetStreamItemsRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_GET_STREAM_ITEMS_REQUEST, CACHE) && "Invalid packet header for GetStreamItemsRequest");
}
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
enum
{
BEFORE = 0,
AFTER = 1
};
uint32 Token = 0;
uint8 MaxItems = 0;
int32 ReferenceTime = 0;
uint8 Direction = BEFORE;
struct StreamId : public PrintableComponent
{
enum
{
INDEX = 0,
DESCRIPTION = 1
};
int32 Type;
uint16 Index;
struct DescriptionType : public PrintableComponent
{
std::string Channel;
std::string ItemName;
std::string ToString() const override;
} Description;
std::string ToString() const override;
} Stream;
std::string Locale;
};
class GetStreamItemsResponse final : public ServerPacket
{
public:
GetStreamItemsResponse() : ServerPacket(PacketHeader(SMSG_GET_STREAM_ITEMS_RESPONSE, CACHE))
{
}
~GetStreamItemsResponse();
void Write() override;
std::string ToString() const override;
std::vector<ModuleInfo*> Items;
uint16 Offset = 0;
uint16 TotalNumItems = 1;
uint32 Token = 0;
};
}
}
#endif // CachePackets_h__

View File

@@ -1,71 +0,0 @@
/*
* 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 ChatPackets_h__
#define ChatPackets_h__
#include "PacketsBase.h"
namespace Battlenet
{
namespace Chat
{
enum Opcode
{
CMSG_JOIN_REQUEST_2 = 0x00, // Not implemented
CMSG_LEAVE_REQUEST = 0x02, // Not implemented
CMSG_INVITE_REQUEST = 0x03, // Not implemented
CMSG_CREATE_AND_INVITE_REQUEST = 0x0A, // Not implemented
CMSG_MESSAGE_SEND = 0x0B, // Not implemented
CMSG_DATAGRAM_CONNECTION_UPDATE = 0x0D, // Not implemented
CMSG_REPORT_SPAM_REQUEST = 0x0E, // Not implemented
CMSG_WHISPER_SEND = 0x13, // Not implemented
CMSG_ENUM_CATEGORY_DESCRIPTIONS = 0x15, // Not implemented
CMSG_ENUM_CONFERENCE_DESCRIPTIONS = 0x17, // Not implemented
CMSG_ENUM_CONFERENCE_MEMBER_COUNTS = 0x19, // Not implemented
CMSG_MODIFY_CHANNEL_LIST_REQUEST = 0x1B, // Deprecated in client
CMSG_GET_MEMBER_COUNT_REQUEST = 0x1F, // Not implemented
CMSG_MODIFY_CHANNEL_LIST_REQUEST_2 = 0x20, // Not implemented
CMSG_GAME_DATA_SEND_REQUEST = 0x22, // Not implemented
SMSG_MEMBERSHIP_CHANGE_NOTIFY = 0x01, // Not implemented
SMSG_INVITE_NOTIFY = 0x04, // Not implemented
SMSG_INVITE_CANCELED = 0x07, // Not implemented
SMSG_MESSAGE_RECV = 0x0B, // Not implemented
SMSG_MESSAGE_UNDELIVERABLE = 0x0C, // Not implemented
SMSG_DATAGRAM_CONNECTION_UPDATE = 0x0D, // Not implemented
SMSG_INVITE_FAILURE = 0x0F, // Not implemented
SMSG_SYSTEM_MESSAGE = 0x10, // Not implemented
SMSG_MESSAGE_BLOCKED = 0x12, // Not implemented
SMSG_WHISPER_RECV = 0x13, // Not implemented
SMSG_WHISPER_UNDELIVERABLE = 0x14, // Not implemented
SMSG_CATEGORY_DESCRIPTIONS = 0x16, // Not implemented
SMSG_CONFERENCE_DESCRIPTIONS = 0x18, // Not implemented
SMSG_CONFERENCE_MEMBER_COUNTS = 0x1A, // Not implemented
SMSG_JOIN_NOTIFY_2 = 0x1B, // Not implemented
SMSG_MODIFY_CHANNEL_LIST_RESPONSE = 0x1C, // Deprecated in client
SMSG_CONFIG_CHANGED = 0x1D, // Not implemented
SMSG_WHISPER_ECHO_RECV = 0x1E, // Not implemented
SMSG_GET_MEMBER_COUNT_RESPONSE = 0x1F, // Not implemented
SMSG_MODIFY_CHANNEL_LIST_RESPONSE_2 = 0x21, // Not implemented
SMSG_GAME_DATA_SEND_RESPONSE = 0x23, // Not implemented
SMSG_GAME_DATA_RECV = 0x24 // Not implemented
};
}
}
#endif // ChatPackets_h__

View File

@@ -1,123 +0,0 @@
/*
* 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 "Session.h"
#include "ConnectionPackets.h"
std::string Battlenet::Connection::Ping::ToString() const
{
return "Battlenet::Connection::Ping";
}
void Battlenet::Connection::Ping::CallHandler(Session* session)
{
session->HandlePing(*this);
}
std::string Battlenet::Connection::EnableEncryption::ToString() const
{
return "Battlenet::Connection::EnableEncryption";
}
void Battlenet::Connection::EnableEncryption::CallHandler(Session* session)
{
session->HandleEnableEncryption(*this);
}
std::string Battlenet::Connection::LogoutRequest::ToString() const
{
return "Battlenet::Connection::LogoutRequest";
}
void Battlenet::Connection::LogoutRequest::CallHandler(Session* session)
{
session->HandleLogoutRequest(*this);
}
void Battlenet::Connection::DisconnectRequest::Read()
{
Error = _stream.Read<uint16>(16);
Timeout = _stream.Read<uint32>(32);
}
std::string Battlenet::Connection::DisconnectRequest::ToString() const
{
std::ostringstream str;
str << "Battlenet::Connection::DisconnectRequest" << std::endl;
APPEND_FIELD(str, Error);
APPEND_FIELD(str, Timeout);
return str.str();
}
void Battlenet::Connection::ConnectionClosing::Read()
{
Packets.resize(_stream.Read<uint8>(6));
for (size_t i = 0; i < Packets.size(); ++i)
{
PacketInfo& info = Packets[i];
info.Command = _stream.ReadFourCC();
info.Time = _stream.Read<uint32>(32);
info.Size = _stream.Read<uint32>(16);
info.Layer = _stream.ReadFourCC();
info.Offset = _stream.Read<uint32>(16);
}
Reason = _stream.Read<ClosingReason>(4);
_stream.ReadBytes(_stream.Read<uint8>(8)); // BadData
if (_stream.Read<bool>(1)) // HasHeader
{
Header.Command = _stream.Read<uint32>(6);
if (_stream.Read<bool>(1))
Header.Channel = _stream.Read<int32>(4);
}
Now = _stream.Read<time_t>(32);
}
std::string Battlenet::Connection::ConnectionClosing::PacketInfo::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Connection::ConnectionClosing::PacketInfo" << std::endl;
APPEND_FIELD(stream, Layer);
APPEND_FIELD(stream, Command);
APPEND_FIELD(stream, Offset);
APPEND_FIELD(stream, Size);
APPEND_FIELD(stream, Time);
return stream.str();
}
std::string Battlenet::Connection::ConnectionClosing::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Connection::ConnectionClosing" << std::endl;
APPEND_FIELD(stream, Header);
APPEND_FIELD(stream, Reason);
APPEND_FIELD(stream, Packets);
APPEND_FIELD(stream, Now);
return stream.str();
}
void Battlenet::Connection::ConnectionClosing::CallHandler(Session* session)
{
session->HandleConnectionClosing(*this);
}
std::string Battlenet::Connection::Pong::ToString() const
{
return "Battlenet::Connection::Pong";
}

View File

@@ -1,157 +0,0 @@
/*
* 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 ConnectionPackets_h__
#define ConnectionPackets_h__
#include "PacketsBase.h"
namespace Battlenet
{
namespace Connection
{
enum Opcode
{
CMSG_PING = 0x0,
CMSG_ENABLE_ENCRYPTION = 0x5,
CMSG_LOGOUT_REQUEST = 0x6,
CMSG_DISCONNECT_REQUEST = 0x7, // Not handled
CMSG_CONNECTION_CLOSING = 0x9,
SMSG_PONG = 0x0,
SMSG_BOOM = 0x1, // Not implemented
SMSG_REGULATOR_UPDATE = 0x2, // Not implemented
SMSG_SERVER_VERSION = 0x3, // Not implemented
SMSG_STUN_SERVERS = 0x4 // Not implemented
};
class Ping final : public ClientPacket
{
public:
Ping(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_PING, CONNECTION) && "Invalid packet header for Ping");
}
void Read() override { }
std::string ToString() const override;
void CallHandler(Session* session) override;
};
class EnableEncryption final : public ClientPacket
{
public:
EnableEncryption(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_ENABLE_ENCRYPTION, CONNECTION) && "Invalid packet header for EnableEncryption");
}
void Read() override { }
std::string ToString() const override;
void CallHandler(Session* session) override;
uint8* GetRemainingData() { return _stream.GetBuffer() + (((_stream.GetReadPos() + 7) & ~7) / 8); }
size_t GetRemainingSize() const { return _stream.GetSize() - (((_stream.GetReadPos() + 7) & ~7) / 8); }
};
class LogoutRequest final : public ClientPacket
{
public:
LogoutRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_LOGOUT_REQUEST, CONNECTION) && "Invalid packet header for LogoutRequest");
}
void Read() override { }
std::string ToString() const override;
void CallHandler(Session* session) override;
};
class DisconnectRequest final : public ClientPacket
{
public:
DisconnectRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_DISCONNECT_REQUEST, CONNECTION) && "Invalid packet header for DisconnectRequest");
}
void Read() override;
std::string ToString() const override;
uint16 Error = 0;
uint32 Timeout = 0;
};
class ConnectionClosing final : public ClientPacket
{
public:
enum ClosingReason
{
PACKET_TOO_LARGE = 1,
PACKET_CORRUPT = 2,
PACKET_INVALID = 3,
PACKET_INCORRECT = 4,
HEADER_CORRUPT = 5,
HEADER_IGNORED = 6,
HEADER_INCORRECT = 7,
PACKET_REJECTED = 8,
CHANNEL_UNHANDLED = 9,
COMMAND_UNHANDLED = 10,
COMMAND_BAD_PERMISSIONS = 11,
DIRECT_CALL = 12,
TIMEOUT = 13,
};
struct PacketInfo : public PrintableComponent
{
std::string Layer;
std::string Command;
uint16 Offset;
uint16 Size;
uint32 Time;
std::string ToString() const override;
};
ConnectionClosing(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_CONNECTION_CLOSING, CONNECTION) && "Invalid packet header for ConnectionClosing");
}
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
PacketHeader Header;
ClosingReason Reason = PACKET_CORRUPT;
std::vector<PacketInfo> Packets;
time_t Now = 0;
};
class Pong final : public ServerPacket
{
public:
Pong() : ServerPacket(PacketHeader(SMSG_PONG, CONNECTION))
{
}
void Write() override { }
std::string ToString() const override;
};
}
}
#endif // ConnectionPackets_h__

View File

@@ -1,71 +0,0 @@
/*
* 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 "FriendsPackets.h"
void Battlenet::Friends::SendInvitationRequest::Read()
{
Token = _stream.Read<uint32>(32);
if (_stream.Read<bool>(1))
PresenceId = _stream.Read<uint32>(32);
if (_stream.Read<bool>(1))
AccountMail = _stream.ReadString(9, 3);
if (_stream.Read<bool>(1))
AccountId = _stream.Read<uint32>(32);
if (_stream.Read<bool>(1))
{
GameAccount = boost::in_place();
GameAccount->Region = _stream.Read<uint8>(8);
GameAccount->ProgramId = _stream.ReadFourCC();
GameAccount->Id = _stream.Read<uint32>(32);
}
_stream.ReadSkip(7);
if (_stream.Read<bool>(1))
Nickname = _stream.ReadString(7);
Source = _stream.ReadFourCC();
Role = _stream.Read<uint32>(32);
if (_stream.Read<bool>(1))
InvitationMsg = _stream.ReadString(9);
}
std::string Battlenet::Friends::SendInvitationRequest::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Friends::SendInvitationRequest" << std::endl;
APPEND_FIELD(stream, Token);
APPEND_FIELD(stream, PresenceId);
APPEND_FIELD(stream, GameAccount);
APPEND_FIELD(stream, AccountId);
APPEND_FIELD(stream, AccountMail);
APPEND_FIELD(stream, Nickname);
APPEND_FIELD(stream, InvitationMsg);
APPEND_FIELD(stream, Source);
APPEND_FIELD(stream, Role);
return stream.str();
}
void Battlenet::Friends::SendInvitationRequest::CallHandler(Session* /*session*/)
{
}

View File

@@ -1,90 +0,0 @@
/*
* 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 FriendsPackets_h__
#define FriendsPackets_h__
#include "PacketsBase.h"
namespace Battlenet
{
namespace Friends
{
enum Opcode
{
CMSG_FRIEND_INVITE = 0x01, // Not implemented
CMSG_FRIEND_INVITE_RESPONSE = 0x02, // Not implemented
CMSG_FRIEND_REMOVE = 0x04, // Not implemented
CMSG_FRIEND_NOTE = 0x05, // Not implemented
CMSG_TOONS_OF_FRIEND_REQUEST = 0x06, // Not implemented
CMSG_BLOCK_ADD = 0x08, // Not implemented
CMSG_BLOCK_REMOVE = 0x0A, // Not implemented
CMSG_GET_FRIENDS_OF_FRIEND = 0x0B, // Not implemented
CMSG_GET_SOCIAL_NETWORK_FRIENDS = 0x0D, // Deprecated in client
CMSG_SOCIAL_NETWORK_CONNECT = 0x0F, // Deprecated in client
CMSG_SOCIAL_NETWORK_DISCONNECT = 0x11, // Deprecated in client
CMSG_SOCIAL_NETWORK_CHECK_CONNECTED = 0x13, // Deprecated in client
CMSG_REALID_FRIEND_INVITE = 0x16, // Deprecated in client
CMSG_SEND_INVITATION_REQUEST = 0x1A, // Not implemented
SMSG_FRIEND_INVITE_NOTIFY = 0x01, // Not implemented
SMSG_FRIEND_INVITE_RESULT = 0x03, // Not implemented
SMSG_TOONS_OF_FRIEND_NOTIFY = 0x06, // Not implemented
SMSG_BLOCK_INVITE_NOTIFY = 0x07, // Deprecated in client
SMSG_BLOCK_ADD_FAILURE = 0x09, // Not implemented
SMSG_FRIENDS_OF_FRIEND = 0x0C, // Deprecated in client
SMSG_SOCIAL_NETWORK_FRIENDS = 0x0E, // Deprecated in client
SMSG_SOCIAL_NETWORK_CONNECT_RESULT = 0x10, // Deprecated in client
SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT = 0x12, // Deprecated in client
SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT = 0x14, // Deprecated in client
SMSG_MAX_FRIENDS_NOTIFY = 0x15, // Not implemented
SMSG_FRIENDS_LIST_NOTIFY_3 = 0x18, // Deprecated in client
SMSG_SEND_INVITATION_RESULT = 0x1B, // Not implemented
SMSG_FRIEND_INVITATION_ADDED_NOTIFY = 0x1C, // Not implemented
SMSG_FRIEND_INVITATION_REMOVED_NOTIFY = 0x1D, // Not implemented
SMSG_FRIENDS_LIST_NOTIFY_5 = 0x1E, // Not implemented
SMSG_ACCOUNT_BLOCK_ADDED_NOTIFY = 0x1F, // Not implemented
SMSG_ACCOUNT_BLOCK_REMOVED_NOTIFY = 0x20, // Not implemented
SMSG_TOON_BLOCK_NOTIFY = 0x21, // Not implemented
SMSG_FRIENDS_OF_FRIEND_RESULT = 0x22 // Not implemented
};
class SendInvitationRequest final : public ClientPacket
{
public:
SendInvitationRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) { }
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
uint32 Token = 0;
Optional<uint32> PresenceId;
Optional<GameAccount::Handle> GameAccount;
Optional<uint32> AccountId;
Optional<std::string> AccountMail;
Optional<std::string> Nickname;
Optional<std::string> InvitationMsg;
std::string Source;
uint32 Role = 0;
};
}
}
#endif // FriendsPackets_h__

View File

@@ -1,263 +0,0 @@
/*
* 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 "PacketManager.h"
Battlenet::ClientPacket* Battlenet::PacketManager::CreateClientPacket(PacketHeader const& header, BitStream& stream)
{
auto packetInfo = _clientPacketTable.find(header);
if (packetInfo == _clientPacketTable.end())
return nullptr;
if (!packetInfo->second.Constructor)
return nullptr;
ClientPacket* packet = packetInfo->second.Constructor(header, stream);
packet->Read();
return packet;
}
char const* Battlenet::PacketManager::GetClientPacketName(PacketHeader const& header)
{
auto packetInfo = _clientPacketTable.find(header);
if (packetInfo == _clientPacketTable.end())
return nullptr;
return packetInfo->second.Name;
}
char const* Battlenet::PacketManager::GetServerPacketName(PacketHeader const& header)
{
auto packetInfo = _serverPacketTable.find(header);
if (packetInfo == _serverPacketTable.end())
return nullptr;
return packetInfo->second.Name;
}
bool Battlenet::PacketManager::IsHandled(PacketHeader const& header)
{
auto packetInfo = _clientPacketTable.find(header);
if (packetInfo == _clientPacketTable.end())
return false;
return packetInfo->second.HasHandler;
}
Battlenet::PacketManager::PacketManager()
{
RegisterAuthenticationPackets();
RegisterConnectionPackets();
RegisterWoWRealmPackets();
RegisterFriendsPackets();
RegisterPresencePackets();
RegisterChatPackets();
RegisterSupportPackets();
RegisterCachePackets();
RegisterAchievementPackets();
RegisterProfilePackets();
}
#define REGISTER_CLIENT_PACKET(header, packetClass) RegisterClientPacket<packetClass>(header, #packetClass)
#define REGISTER_SERVER_PACKET(header, packetClass) RegisterPacketName(_serverPacketTable, header, #packetClass)
#define REGISTER_CLIENT_PACKET_NAME(header, name) RegisterPacketName(_clientPacketTable, header, name)
#define REGISTER_SERVER_PACKET_NAME(header, name) RegisterPacketName(_serverPacketTable, header, name)
void Battlenet::PacketManager::RegisterAuthenticationPackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest");
REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION), Authentication::ResumeRequest);
REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION), Authentication::ProofResponse);
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_REQUEST_2, AUTHENTICATION), "Authentication::GenerateSingleSignOnTokenRequest2");
REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_LOGON_REQUEST_3, AUTHENTICATION), Authentication::LogonRequest3);
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_SINGLE_SIGN_ON_REQUEST_3, AUTHENTICATION), "Authentication::SingleSignOnRequest3");
REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_LOGON_RESPONSE, AUTHENTICATION), Authentication::LogonResponse);
REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_RESUME_RESPONSE, AUTHENTICATION), Authentication::ResumeResponse);
REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_PROOF_REQUEST, AUTHENTICATION), Authentication::ProofRequest);
REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_PATCH, AUTHENTICATION), "Authentication::Patch");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_AUTHORIZED_LICENSES, AUTHENTICATION), "Authentication::AuthorizedLicenses");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_RESPONSE_2, AUTHENTICATION), "Authentication::GenerateSingleSignOnTokenResponse2");
}
void Battlenet::PacketManager::RegisterConnectionPackets()
{
REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_PING, CONNECTION), Connection::Ping);
REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_ENABLE_ENCRYPTION, CONNECTION), Connection::EnableEncryption);
REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_LOGOUT_REQUEST, CONNECTION), Connection::LogoutRequest);
REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_DISCONNECT_REQUEST, CONNECTION), Connection::DisconnectRequest);
REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_CONNECTION_CLOSING, CONNECTION), Connection::ConnectionClosing);
REGISTER_SERVER_PACKET(PacketHeader(Connection::SMSG_PONG, CONNECTION), Connection::Pong);
REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_BOOM, CONNECTION), "Connection::Boom");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_REGULATOR_UPDATE, CONNECTION), "Connection::RegulatorUpdate");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_SERVER_VERSION, CONNECTION), "Connection::ServerVersion");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_STUN_SERVERS, CONNECTION), "Connection::STUNServers");
}
void Battlenet::PacketManager::RegisterWoWRealmPackets()
{
REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM), WoWRealm::ListSubscribeRequest);
REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_LIST_UNSUBSCRIBE, WOWREALM), WoWRealm::ListUnsubscribe);
REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_JOIN_REQUEST_V2, WOWREALM), WoWRealm::JoinRequestV2);
REGISTER_CLIENT_PACKET_NAME(PacketHeader(WoWRealm::CMSG_MULTI_LOGON_REQUEST_V2, WOWREALM), "WoWRealm::MultiLogonRequestV2");
REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM), WoWRealm::ListSubscribeResponse);
REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_UPDATE, WOWREALM), WoWRealm::ListUpdate);
REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_COMPLETE, WOWREALM), WoWRealm::ListComplete);
REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_TOON_READY, WOWREALM), WoWRealm::ToonReady);
REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_TOON_LOGGED_OUT, WOWREALM), WoWRealm::ToonLoggedOut);
REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_JOIN_RESPONSE_V2, WOWREALM), WoWRealm::JoinResponseV2);
}
void Battlenet::PacketManager::RegisterFriendsPackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_INVITE, FRIENDS), "Friends::FriendInvite");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_INVITE_RESPONSE, FRIENDS), "Friends::FriendInviteResponse");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_REMOVE, FRIENDS), "Friends::FriendRemove");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_NOTE, FRIENDS), "Friends::FriendNote");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_TOONS_OF_FRIEND_REQUEST, FRIENDS), "Friends::ToonsOfFriendRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_BLOCK_ADD, FRIENDS), "Friends::BlockAdd");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_BLOCK_REMOVE, FRIENDS), "Friends::BlockRemove");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS), "Friends::GetFriendsOfFriend");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_GET_SOCIAL_NETWORK_FRIENDS, FRIENDS), "Friends::GetSocialNetworkFriends");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS), "Friends::SocialNetworkConnect");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_DISCONNECT, FRIENDS), "Friends::SocialNetworkDisconnect");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS), "Friends::SocialNetworkCheckConnected");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_REALID_FRIEND_INVITE, FRIENDS), "Friends::RealIdFriendInvite");
REGISTER_CLIENT_PACKET(PacketHeader(Friends::CMSG_SEND_INVITATION_REQUEST, FRIENDS), Friends::SendInvitationRequest);
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITE_NOTIFY, FRIENDS), "Friends::FriendInviteNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITE_RESULT, FRIENDS), "Friends::FriendInviteResult");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_TOONS_OF_FRIEND_NOTIFY, FRIENDS), "Friends::ToonsOfFriendNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_BLOCK_INVITE_NOTIFY, FRIENDS), "Friends::BlockInviteNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_BLOCK_ADD_FAILURE, FRIENDS), "Friends::BlockAddFailure");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_OF_FRIEND, FRIENDS), "Friends::FriendsOfFriend");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_FRIENDS, FRIENDS), "Friends::SocialNetworkFriends");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_CONNECT_RESULT, FRIENDS), "Friends::SocialNetworkConnectResult");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT, FRIENDS), "Friends::SocialNetworkDisconnectResult");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS), "Friends::SocialNetworkCheckConnectedResult");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_MAX_FRIENDS_NOTIFY, FRIENDS), "Friends::MaxFriendsNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_LIST_NOTIFY_3, FRIENDS), "Friends::FriendsListNotify3");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SEND_INVITATION_RESULT, FRIENDS), "SendInvitationResult");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITATION_ADDED_NOTIFY, FRIENDS), "Friends::FriendInvitationAddedNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITATION_REMOVED_NOTIFY, FRIENDS), "Friends::FriendInvitationRemovedNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_LIST_NOTIFY_5, FRIENDS), "Friends::FriendsListNotify5");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_ACCOUNT_BLOCK_ADDED_NOTIFY, FRIENDS), "Friends::AccountBlockAddedNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_ACCOUNT_BLOCK_REMOVED_NOTIFY, FRIENDS), "Friends::AccountBlockRemovedNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_TOON_BLOCK_NOTIFY, FRIENDS), "Friends::ToonBlockNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_OF_FRIEND_RESULT, FRIENDS), "Friends::FriendsOfFriendResult");
}
void Battlenet::PacketManager::RegisterPresencePackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Presence::CMSG_UPDATE_REQUEST, PRESENCE), "Presence::UpdateRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Presence::CMSG_STATISTIC_SUBSCRIBE, PRESENCE), "Presence::StatisticSubscribe");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_UPDATE_NOTIFY, PRESENCE), "Presence::UpdateNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_FIELD_SPEC_ANNOUNCE, PRESENCE), "Presence::FieldSpecAnnounce");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_STATISTICS_UPDATE, PRESENCE), "Presence::StatisticsUpdate");
}
void Battlenet::PacketManager::RegisterChatPackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_JOIN_REQUEST_2, CHAT), "Chat::JoinRequest2");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_LEAVE_REQUEST, CHAT), "Chat::LeaveRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_INVITE_REQUEST, CHAT), "Chat::InviteRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_CREATE_AND_INVITE_REQUEST, CHAT), "Chat::CreateAndInviteRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MESSAGE_SEND, CHAT), "Chat::MessageSend");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_DATAGRAM_CONNECTION_UPDATE, CHAT), "Chat::DatagramConnectionUpdate");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_REPORT_SPAM_REQUEST, CHAT), "Chat::ReportSpamRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_WHISPER_SEND, CHAT), "Chat::WhisperSend");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CATEGORY_DESCRIPTIONS, CHAT), "Chat::EnumCategoryDescriptions");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CONFERENCE_DESCRIPTIONS, CHAT), "Chat::EnumConferenceDescriptions");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CONFERENCE_MEMBER_COUNTS, CHAT), "Chat::EnumConferenceMemberCounts");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MODIFY_CHANNEL_LIST_REQUEST, CHAT), "Chat::ModifyChannelListRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_GET_MEMBER_COUNT_REQUEST, CHAT), "Chat::GetMemberCountRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MODIFY_CHANNEL_LIST_REQUEST_2, CHAT), "Chat::ModifyChannelListRequest2");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_GAME_DATA_SEND_REQUEST, CHAT), "Chat::GameDataSendRequest");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MEMBERSHIP_CHANGE_NOTIFY, CHAT), "Chat::MembershipChangeNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_NOTIFY, CHAT), "Chat::InviteNotify");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_CANCELED, CHAT), "Chat::InviteCanceled");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_RECV, CHAT), "Chat::MessageRecv");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_UNDELIVERABLE, CHAT), "Chat::MessageUndeliverable");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_DATAGRAM_CONNECTION_UPDATE, CHAT), "Chat::DatagramConnectionUpdate");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_FAILURE, CHAT), "Chat::InviteFailed");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_SYSTEM_MESSAGE, CHAT), "Chat::SystemMessage");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_BLOCKED, CHAT), "Chat::MessageBlocked");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_RECV, CHAT), "Chat::WhisperRecv");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_UNDELIVERABLE, CHAT), "Chat::WhisperUndeliverable");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CATEGORY_DESCRIPTIONS, CHAT), "Chat::CategoryDescriptions");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFERENCE_DESCRIPTIONS, CHAT), "Chat::ConferenceDescriptions");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFERENCE_MEMBER_COUNTS, CHAT), "Chat::ConferenceMemberCounts");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_JOIN_NOTIFY_2, CHAT), "Chat::JoinNotify2");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MODIFY_CHANNEL_LIST_RESPONSE, CHAT), "Chat::ModifyChannelListResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFIG_CHANGED, CHAT), "Chat::ConfigChanged");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_ECHO_RECV, CHAT), "Chat::WhisperEchoRecv");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_GET_MEMBER_COUNT_RESPONSE, CHAT), "Chat::GetMemberCountResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MODIFY_CHANNEL_LIST_RESPONSE_2, CHAT), "Chat::ModifyChannelListResponse2");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_GAME_DATA_SEND_RESPONSE, CHAT), "Chat::GameDataSendResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_GAME_DATA_RECV, CHAT), "Chat::GameDataRecv");
}
void Battlenet::PacketManager::RegisterSupportPackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Support::CMSG_COMPLAINT_REQUEST, SUPPORT), "Support::ComplaintRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Support::CMSG_COMPLAINT_REQUEST_2, SUPPORT), "Support::ComplaintRequest2");
}
void Battlenet::PacketManager::RegisterAchievementPackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_LISTEN_REQUEST, ACHIEVEMENT), "Achievement::ListenRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_CRITERIA_FLUSH_REQUEST, ACHIEVEMENT), "Achievement::CriteriaFlushRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_CHANGE_TROPHY_CASE_REQUEST, ACHIEVEMENT), "Achievement::ChangeTrophyCaseRequest");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_DATA, ACHIEVEMENT), "Achievement::Data");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_CRITERIA_FLUSH_RESPONSE, ACHIEVEMENT), "Achievement::CriteriaFlushResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_ACHIEVEMENT_HANDLE_UPDATE, ACHIEVEMENT), "Achievement::AchievementHandleUpdate");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_CHANGE_TROPHY_CASE_RESULT, ACHIEVEMENT), "Achievement::ChangeTrophyCaseResult");
}
void Battlenet::PacketManager::RegisterCachePackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_GATEWAY_LOOKUP_REQUEST, CACHE), "Cache::GatewayLookupRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_CONNECT_REQUEST, CACHE), "Cache::ConnectRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_DATA_CHUNK, CACHE), "Cache::DataChunk");
REGISTER_CLIENT_PACKET(PacketHeader(Cache::CMSG_GET_STREAM_ITEMS_REQUEST, CACHE), Cache::GetStreamItemsRequest);
REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_GATEWAY_LOOKUP_RESPONSE, CACHE), "Cache::GatewayLookupResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_CONNECT_RESPONSE, CACHE), "Cache::ConnectResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_PUBLISH_LIST_RESPONSE, CACHE), "Cache::PublishListResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_RESULT, CACHE), "Cache::Result");
REGISTER_SERVER_PACKET(PacketHeader(Cache::SMSG_GET_STREAM_ITEMS_RESPONSE, CACHE), Cache::GetStreamItemsResponse);
}
void Battlenet::PacketManager::RegisterProfilePackets()
{
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_READ_REQUEST, PROFILE), "Profile::ReadRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_ADDRESS_QUERY_REQUEST, PROFILE), "Profile::AddressQueryRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_RESOLVE_TOON_HANDLE_TO_NAME_REQUEST, PROFILE), "Profile::ResolveHandleToToonNameRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_RESOLVE_TOON_NAME_TO_HANDLE_REQUEST, PROFILE), "Profile::ResolveToonNameToHandleRequest");
REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_CHANGE_SETTINGS, PROFILE), "Profile::ChangeSettings");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_READ_RESPONSE, PROFILE), "Profile::ReadResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_ADDRESS_QUERY_RESPONSE, PROFILE), "Profile::AddressQueryResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_RESOLVE_TOON_HANDLE_TO_NAME_RESPONSE, PROFILE), "Profile::ResolveHandleToToonNameResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_RESOLVE_TOON_NAME_TO_HANDLE_RESPONSE, PROFILE), "Profile::ResolveToonNameToHandleResponse");
REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_SETTINGS_AVAILABLE, PROFILE), "Profile::SettingsAvailable");
}

View File

@@ -1,105 +0,0 @@
/*
* 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 PacketManager_h__
#define PacketManager_h__
#include "Packets.h"
#include <map>
#include <type_traits>
template<typename T>
struct has_call_handler
{
template<typename U, void(U::*)(Battlenet::Session*)> struct test_has_call_handler { };
template<typename U> static char Test(test_has_call_handler<U, &U::CallHandler>*);
template<typename U> static int Test(...);
static const bool value = sizeof(Test<T>(nullptr)) == sizeof(char);
};
namespace Battlenet
{
class PacketManager
{
typedef ClientPacket*(*PacketCreateFn)(PacketHeader const& header, BitStream& stream);
struct PacketInfo
{
PacketCreateFn Constructor;
char const* Name;
bool HasHandler;
};
PacketManager();
void RegisterAuthenticationPackets();
void RegisterConnectionPackets();
void RegisterWoWRealmPackets();
void RegisterFriendsPackets();
void RegisterPresencePackets();
void RegisterChatPackets();
void RegisterSupportPackets();
void RegisterAchievementPackets();
void RegisterCachePackets();
void RegisterProfilePackets();
template<class PacketType>
static ClientPacket* New(PacketHeader const& header, BitStream& stream)
{
return new PacketType(header, stream);
}
void RegisterPacketName(std::map<PacketHeader, PacketInfo>& packetTable, PacketHeader const& header, char const* name)
{
PacketInfo& info = packetTable[header];
info.Constructor = nullptr;
info.Name = name;
info.HasHandler = false;
}
template<class PacketType>
void RegisterClientPacket(PacketHeader const& header, char const* name)
{
PacketInfo& info = _clientPacketTable[header];
info.Constructor = &New<PacketType>;
info.Name = name;
info.HasHandler = has_call_handler<PacketType>::value;
}
public:
ClientPacket* CreateClientPacket(PacketHeader const& header, BitStream& stream);
char const* GetClientPacketName(PacketHeader const& header);
char const* GetServerPacketName(PacketHeader const& header);
bool IsHandled(PacketHeader const& header);
static PacketManager& Instance()
{
static PacketManager instance;
return instance;
}
private:
std::map<PacketHeader, PacketInfo> _clientPacketTable;
std::map<PacketHeader, PacketInfo> _serverPacketTable;
};
}
#define sPacketManager Battlenet::PacketManager::Instance()
#endif // PacketManager_h__

View File

@@ -1,32 +0,0 @@
/*
* 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 Packets_h__
#define Packets_h__
#include "AuthenticationPackets.h"
#include "ConnectionPackets.h"
#include "WoWRealmPackets.h"
#include "FriendsPackets.h"
#include "PresencePackets.h"
#include "ChatPackets.h"
#include "SupportPackets.h"
#include "AchievementPackets.h"
#include "CachePackets.h"
#include "ProfilePackets.h"
#endif // Packets_h__

View File

@@ -1,119 +0,0 @@
/*
* 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 PacketsBase_h__
#define PacketsBase_h__
#include "AuthCodes.h"
#include "BitStream.h"
#include "Common.h"
#include "Errors.h"
#include "PacketsCommon.h"
#include <string>
#include <boost/asio/ip/tcp.hpp>
using boost::asio::ip::tcp;
namespace Battlenet
{
class BitStream;
class Session;
enum Channel
{
AUTHENTICATION = 0,
CONNECTION = 1,
WOWREALM = 2,
FRIENDS = 3,
PRESENCE = 4,
CHAT = 5,
SUPPORT = 7,
ACHIEVEMENT = 8,
CACHE = 11,
PROFILE = 14
};
struct PacketHeader : public PrintableComponent
{
PacketHeader(uint32 opcode, uint32 channel) : Command(opcode), Channel(channel) { }
PacketHeader() : Command(0), Channel(AUTHENTICATION) { }
uint32 Command;
int32 Channel;
bool operator<(PacketHeader const& right) const
{
if (Command < right.Command)
return true;
if (Command > right.Command)
return false;
return Channel < right.Channel;
}
bool operator==(PacketHeader const& right) const
{
return Command == right.Command && Channel == right.Channel;
}
std::string ToString() const override;
};
class Packet : public PrintableComponent
{
public:
Packet(PacketHeader const& header, BitStream& stream) : _header(header), _stream(stream) { }
virtual ~Packet() { }
PacketHeader const& GetHeader() const { return _header; }
virtual void Write() = 0;
virtual void Read() = 0;
protected:
PacketHeader _header;
BitStream& _stream;
private:
Packet(Packet const& right) = delete;
Packet& operator=(Packet const& right) = delete;
};
class ClientPacket : public Packet
{
public:
ClientPacket(PacketHeader const& header, BitStream& stream) : Packet(header, stream) { }
void Write() override final { ASSERT(!"Write not implemented for client packets."); }
virtual void CallHandler(Session* session);
};
class ServerPacket : public Packet
{
public:
ServerPacket(PacketHeader const& header);
~ServerPacket();
void Read() override final { ASSERT(!"Read not implemented for server packets."); }
uint8* GetData() { return _stream.GetBuffer(); }
uint8 const* GetData() const { return _stream.GetBuffer(); }
size_t GetSize() const { return _stream.GetSize(); }
};
}
#endif // PacketsBase_h__

View File

@@ -1,111 +0,0 @@
/*
* 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 "PacketsCommon.h"
#include "Util.h"
std::string Battlenet::Version::Record::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Version::Record" << std::endl;
APPEND_FIELD(stream, ProgramId);
APPEND_FIELD(stream, Component);
APPEND_FIELD(stream, Version);
return stream.str();
}
std::string Battlenet::Cache::Handle::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Cache::Handle" << std::endl;
APPEND_FIELD(stream, Type);
APPEND_FIELD(stream, Region);
stream << "ModuleId: " << ByteArrayToHexStr(ModuleId, 32) << std::endl;
return stream.str();
}
std::string Battlenet::Account::FullName::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Account::FullName" << std::endl;
APPEND_FIELD(stream, GivenName);
APPEND_FIELD(stream, Surname);
return stream.str();
}
std::string Battlenet::GameAccount::Handle::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::GameAccount::Handle" << std::endl;
APPEND_FIELD(stream, Region);
APPEND_FIELD(stream, ProgramId);
APPEND_FIELD(stream, Id);
return stream.str();
}
std::string Battlenet::PrintableRealmHandle::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::RealmHandle" << std::endl;
APPEND_FIELD(stream, Region);
APPEND_FIELD(stream, Site);
APPEND_FIELD(stream, Realm);
return stream.str();
}
std::string Battlenet::Toon::FullName::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Toon::FullName" << std::endl;
APPEND_FIELD(stream, Region);
APPEND_FIELD(stream, ProgramId);
APPEND_FIELD(stream, Realm);
APPEND_FIELD(stream, Name);
return stream.str();
}
std::string Battlenet::Toon::Handle::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Toon::Handle" << std::endl;
APPEND_FIELD(stream, Region);
APPEND_FIELD(stream, ProgramId);
APPEND_FIELD(stream, Realm);
APPEND_FIELD(stream, Id);
return stream.str();
}
std::string Battlenet::Profile::RecordAddress::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::Profile::RecordAddress" << std::endl;
APPEND_FIELD(stream, Label);
APPEND_FIELD(stream, Id);
return stream.str();
}
std::ostream& Battlenet::Format::FieldToString(std::ostream& stream, char const* fieldName, PrintableComponent const& u, std::true_type)
{
if (fieldName[0])
stream << fieldName << ": ";
return stream << u.ToString();
}
std::ostream& Battlenet::Format::FieldToString(std::ostream& stream, char const* fieldName, uint8 const& u, std::false_type)
{
return FieldToString(stream, fieldName, uint32(u), std::false_type());
}

View File

@@ -1,182 +0,0 @@
/*
* 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 PacketsCommon_h__
#define PacketsCommon_h__
#include "Common.h"
#include "Realm/Realm.h"
#include <typeinfo>
namespace Battlenet
{
struct PrintableComponent
{
virtual ~PrintableComponent() { }
virtual std::string ToString() const = 0;
};
namespace Format
{
template<typename T>
struct is_printable : std::is_base_of<PrintableComponent, typename std::remove_pointer<T>::type>::type
{
};
template<typename T>
typename std::enable_if<!std::is_pointer<T>::value, T>::type const& Dereference(T const& t) { return t; };
template<typename T>
typename std::enable_if<std::is_pointer<T>::value, typename std::remove_pointer<T>::type>::type const& Dereference(T const& t) { return *t; };
template<typename T>
std::ostream& FieldToString(std::ostream& stream, char const* fieldName, T const& u, std::false_type)
{
if (fieldName[0])
stream << fieldName << ": ";
return stream << u << std::endl;
}
std::ostream& FieldToString(std::ostream& stream, char const* fieldName, PrintableComponent const& u, std::true_type);
std::ostream& FieldToString(std::ostream& stream, char const* fieldName, uint8 const& u, std::false_type);
template<typename T>
std::ostream& FieldToString(std::ostream& stream, char const* fieldName, std::vector<T> const& u, std::false_type)
{
stream << fieldName << ":" << std::endl;
for (T const& t : u)
FieldToString(stream, "", Dereference(t), is_printable<T>());
return stream;
}
template<typename T>
std::ostream& FieldToString(std::ostream& stream, char const* fieldName, Optional<T> const& u)
{
if (u)
FieldToString(stream, fieldName, Dereference(*u), is_printable<T>());
return stream;
}
template<typename T>
std::ostream& FieldToString(std::ostream& stream, char const* fieldName, T const& u)
{
return FieldToString(stream, fieldName, Dereference(u), is_printable<T>());
}
}
#define APPEND_FIELD(stream, field) Format::FieldToString(stream, #field, field)
namespace Version
{
struct Record : public PrintableComponent
{
std::string ProgramId;
std::string Component;
uint32 Version;
std::string ToString() const override;
};
}
namespace Cache
{
struct Handle : public PrintableComponent
{
std::string Type;
std::string Region;
uint8 ModuleId[32] = { };
std::string ToString() const override;
};
}
namespace Account
{
struct FullName : public PrintableComponent
{
std::string GivenName;
std::string Surname;
std::string ToString() const override;
};
}
namespace GameAccount
{
struct Handle : public PrintableComponent
{
uint8 Region = 0;
std::string ProgramId;
uint32 Id = 0;
std::string ToString() const override;
};
}
// For use in packets
struct PrintableRealmHandle : public RealmHandle, public PrintableComponent
{
PrintableRealmHandle() : RealmHandle() { }
PrintableRealmHandle(uint8 region, uint8 battlegroup, uint32 index)
: RealmHandle(region, battlegroup, index) { }
PrintableRealmHandle& operator=(RealmHandle const& r)
{
RealmHandle::operator=(r);
return *this;
}
std::string ToString() const override;
};
namespace Toon
{
struct FullName : public PrintableComponent
{
uint8 Region = 0;
std::string ProgramId;
uint32 Realm = 0;
std::string Name;
std::string ToString() const override;
};
struct Handle : public PrintableComponent
{
uint8 Region = 0;
std::string ProgramId;
uint32 Realm = 0;
uint64 Id = 0;
std::string ToString() const override;
};
}
namespace Profile
{
struct RecordAddress : public PrintableComponent
{
uint32 Label = 0;
uint64 Id = 0;
std::string ToString() const override;
};
}
}
#endif // PacketsCommon_h__

View File

@@ -1,44 +0,0 @@
/*
* 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 ProfilePackets_h__
#define ProfilePackets_h__
#include "PacketsBase.h"
namespace Battlenet
{
namespace Profile
{
enum Opcode
{
CMSG_READ_REQUEST = 0x0, // Not implemented
CMSG_ADDRESS_QUERY_REQUEST = 0x1, // Not implemented
CMSG_RESOLVE_TOON_HANDLE_TO_NAME_REQUEST = 0x2, // Not implemented
CMSG_RESOLVE_TOON_NAME_TO_HANDLE_REQUEST = 0x3, // Not implemented
CMSG_CHANGE_SETTINGS = 0x5, // Not implemented
SMSG_READ_RESPONSE = 0x0, // Not implemented
SMSG_ADDRESS_QUERY_RESPONSE = 0x1, // Not implemented
SMSG_RESOLVE_TOON_HANDLE_TO_NAME_RESPONSE = 0x2, // Not implemented
SMSG_RESOLVE_TOON_NAME_TO_HANDLE_RESPONSE = 0x3, // Not implemented
SMSG_SETTINGS_AVAILABLE = 0x4 // Not implemented
};
}
}
#endif // ProfilePackets_h__

View File

@@ -1,260 +0,0 @@
/*
* 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 "WoWRealmPackets.h"
#include "Session.h"
#include <boost/lexical_cast.hpp>
#include <boost/asio/ip/address.hpp>
void Battlenet::WoWRealm::ListSubscribeRequest::CallHandler(Session* session)
{
session->HandleListSubscribeRequest(*this);
}
void Battlenet::WoWRealm::ListUnsubscribe::CallHandler(Session* session)
{
session->HandleListUnsubscribe(*this);
}
void Battlenet::WoWRealm::JoinRequestV2::Read()
{
ClientSalt = _stream.Read<uint32>(32);
_stream.ReadSkip(20);
Id.Region = _stream.Read<uint8>(8);
_stream.ReadSkip(12);
Id.Site = _stream.Read<uint8>(8);
Id.Realm = _stream.Read<uint32>(32);
}
std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::JoinRequestV2" << std::endl;
APPEND_FIELD(stream, Id);
APPEND_FIELD(stream, ClientSalt);
return stream.str();
}
void Battlenet::WoWRealm::JoinRequestV2::CallHandler(Session* session)
{
session->HandleJoinRequestV2(*this);
}
void Battlenet::WoWRealm::ListSubscribeResponse::Write()
{
_stream.Write(Type, 1);
if (Type == SUCCESS)
{
_stream.Write(ToonCounts.size(), 7);
for (ToonCountEntry const& entry : ToonCounts)
{
_stream.Write(entry.Realm.Region, 8);
_stream.WriteSkip(12);
_stream.Write(entry.Realm.Site, 8);
_stream.Write(entry.Realm.Realm, 32);
_stream.Write(entry.Count, 16);
}
}
else
_stream.Write(Failure, 8);
}
std::string Battlenet::WoWRealm::ListSubscribeResponse::ToonCountEntry::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ListSubscribeResponse::ToonCountEntry" << std::endl;
APPEND_FIELD(stream, Realm);
APPEND_FIELD(stream, Count);
return stream.str();
}
std::string Battlenet::WoWRealm::ListSubscribeResponse::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ListSubscribeResponse" << std::endl;
if (Type == SUCCESS)
APPEND_FIELD(stream, ToonCounts);
else
APPEND_FIELD(stream, Failure);
return stream.str();
}
void Battlenet::WoWRealm::ListUpdate::Write()
{
_stream.Write(State.Type, 1);
if (State.Type == StateType::UPDATE)
{
_stream.Write(State.Update.Category, 32);
_stream.WriteFloat(State.Update.Population);
_stream.Write(State.Update.StateFlags, 8);
_stream.WriteSkip(19);
_stream.Write(State.Update.Type + -std::numeric_limits<int32>::min(), 32);
_stream.WriteString(State.Update.Name, 10);
_stream.Write(State.Update.PrivilegedData.is_initialized(), 1);
if (State.Update.PrivilegedData.is_initialized())
{
_stream.WriteString(State.Update.PrivilegedData->Version, 5);
_stream.Write(State.Update.PrivilegedData->ConfigId, 32);
boost::asio::ip::address_v4::bytes_type ip = State.Update.PrivilegedData->Address.address().to_v4().to_bytes();
uint16 port = State.Update.PrivilegedData->Address.port();
EndianConvertReverse(ip);
EndianConvertReverse(port);
_stream.WriteBytes(ip.data(), 4);
_stream.WriteBytes(&port, 2);
}
_stream.Write(State.Update.InfoFlags, 8);
}
_stream.Write(Id.Region, 8);
_stream.WriteSkip(12);
_stream.Write(Id.Site, 8);
_stream.Write(Id.Realm, 32);
}
std::string Battlenet::WoWRealm::ListUpdate::PrivilegedDataType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::RealmInfo::PrivilegedData" << std::endl;
APPEND_FIELD(stream, Version);
APPEND_FIELD(stream, ConfigId);
APPEND_FIELD(stream, Address);
return stream.str();
}
std::string Battlenet::WoWRealm::ListUpdate::StateType::UpdateType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ListUpdate::State::Update" << std::endl;
APPEND_FIELD(stream, InfoFlags);
APPEND_FIELD(stream, Name);
APPEND_FIELD(stream, Type);
APPEND_FIELD(stream, Category);
APPEND_FIELD(stream, StateFlags);
APPEND_FIELD(stream, Population);
APPEND_FIELD(stream, PrivilegedData);
return stream.str();
}
std::string Battlenet::WoWRealm::ListUpdate::StateType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ListUpdate::State" << std::endl;
if (Type == UPDATE)
APPEND_FIELD(stream, Update);
else
APPEND_FIELD(stream, Delete);
return stream.str();
}
std::string Battlenet::WoWRealm::ListUpdate::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ListUpdate" << std::endl;
APPEND_FIELD(stream, Id);
APPEND_FIELD(stream, State);
return stream.str();
}
void Battlenet::WoWRealm::ToonReady::Write()
{
_stream.Write(Name.Region, 8);
_stream.WriteFourCC(Name.ProgramId);
_stream.Write(Name.Realm, 32);
_stream.WriteString(Name.Name, 7, -2);
_stream.WriteSkip(21);
_stream.Write(ProfileAddress.Id, 64);
_stream.Write(ProfileAddress.Label, 32);
_stream.Write(Handle.Id, 64);
_stream.Write(Handle.Realm, 32);
_stream.Write(Handle.Region, 8);
_stream.WriteFourCC(Handle.ProgramId);
}
std::string Battlenet::WoWRealm::ToonReady::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::ToonReady" << std::endl;
APPEND_FIELD(stream, Name);
APPEND_FIELD(stream, Handle);
APPEND_FIELD(stream, ProfileAddress);
return stream.str();
}
void Battlenet::WoWRealm::JoinResponseV2::Write()
{
_stream.Write(Type, 1);
if (Type == SUCCESS)
{
_stream.Write(Success.ServerSalt, 32);
_stream.Write(Success.IPv4.size(), 5);
for (tcp::endpoint const& addr : Success.IPv4)
{
boost::asio::ip::address_v4::bytes_type ip = addr.address().to_v4().to_bytes();
uint16 port = addr.port();
EndianConvertReverse(port);
_stream.WriteBytes(ip.data(), 4);
_stream.WriteBytes(&port, 2);
}
_stream.Write(Success.IPv6.size(), 5);
for (tcp::endpoint const& addr : Success.IPv6)
{
boost::asio::ip::address_v6::bytes_type ip = addr.address().to_v6().to_bytes();
uint16 port = addr.port();
EndianConvertReverse(port);
_stream.WriteBytes(ip.data(), 16);
_stream.WriteBytes(&port, 2);
}
}
else
_stream.Write(Failure, 8);
}
std::string Battlenet::WoWRealm::JoinResponseV2::SuccessType::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::JoinResponseV2::Success" << std::endl;
APPEND_FIELD(stream, ServerSalt);
APPEND_FIELD(stream, IPv4);
APPEND_FIELD(stream, IPv6);
return stream.str();
}
std::string Battlenet::WoWRealm::JoinResponseV2::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::WoWRealm::JoinResponseV2" << std::endl;
if (Type == SUCCESS)
APPEND_FIELD(stream, Success);
else
APPEND_FIELD(stream, Failure);
return stream.str();
}

View File

@@ -1,238 +0,0 @@
/*
* 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 WoWRealmPackets_h__
#define WoWRealmPackets_h__
#include "PacketsBase.h"
#include "RealmList.h"
namespace Battlenet
{
namespace WoWRealm
{
enum Opcode
{
CMSG_LIST_SUBSCRIBE_REQUEST = 0x0,
CMSG_LIST_UNSUBSCRIBE = 0x1,
CMSG_JOIN_REQUEST_V2 = 0x8,
CMSG_MULTI_LOGON_REQUEST_V2 = 0x9, // Not implemented
SMSG_LIST_SUBSCRIBE_RESPONSE = 0x0,
SMSG_LIST_UPDATE = 0x2,
SMSG_LIST_COMPLETE = 0x3,
SMSG_TOON_READY = 0x6, // Not implemented
SMSG_TOON_LOGGED_OUT = 0x7, // Not implemented
SMSG_JOIN_RESPONSE_V2 = 0x8
};
class ListSubscribeRequest final : public ClientPacket
{
public:
ListSubscribeRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM) && "Invalid packet header for ListSubscribeRequest");
}
void Read() override { }
std::string ToString() const override { return "Battlenet::WoWRealm::ListSubscribeRequest"; }
void CallHandler(Session* session) override;
};
class ListUnsubscribe final : public ClientPacket
{
public:
ListUnsubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_LIST_UNSUBSCRIBE, WOWREALM) && "Invalid packet header for ListUnsubscribe");
}
void Read() override { }
std::string ToString() const override { return "Battlenet::WoWRealm::ListUnsubscribe"; }
void CallHandler(Session* session) override;
};
class JoinRequestV2 final : public ClientPacket
{
public:
JoinRequestV2(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
ASSERT(header == PacketHeader(CMSG_JOIN_REQUEST_V2, WOWREALM) && "Invalid packet header for RealmJoinRequest");
}
void Read() override;
std::string ToString() const override;
void CallHandler(Session* session) override;
uint32 ClientSalt = 0;
PrintableRealmHandle Id;
};
class ListSubscribeResponse final : public ServerPacket
{
public:
ListSubscribeResponse() : ServerPacket(PacketHeader(SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM))
{
}
struct ToonCountEntry : public PrintableComponent
{
ToonCountEntry(PrintableRealmHandle const& realm, uint16 count) : Realm(realm), Count(count) { }
PrintableRealmHandle Realm;
uint16 Count;
std::string ToString() const override;
};
void Write() override;
std::string ToString() const override;
enum
{
SUCCESS = 0,
FAILURE = 1
};
int32 Type = SUCCESS;
std::vector<ToonCountEntry> ToonCounts;
Wow::AuthResult Failure = Wow::WOW_SUCCESS;
};
class ListUpdate final : public ServerPacket
{
public:
ListUpdate() : ServerPacket(PacketHeader(SMSG_LIST_UPDATE, WOWREALM))
{
}
void Write() override;
std::string ToString() const override;
PrintableRealmHandle Id;
struct PrivilegedDataType : public PrintableComponent
{
std::string Version;
uint32 ConfigId = 0;
tcp::endpoint Address;
std::string ToString() const override;
};
struct StateType : public PrintableComponent
{
enum
{
DELETED = 0,
UPDATE = 1
};
int32 Type = UPDATE;
struct DeleteType : public PrintableComponent
{
std::string ToString() const override { return "Battlenet::WoWRealm::ListUpdate::State::Delete"; }
} Delete;
struct UpdateType : public PrintableComponent
{
uint8 InfoFlags = 0;
std::string Name;
int32 Type = 0;
uint32 Category = 0;
uint8 StateFlags = 0;
float Population = 0.0f;
Optional<PrivilegedDataType> PrivilegedData;
std::string ToString() const override;
} Update;
std::string ToString() const override;
} State;
};
class ListComplete final : public ServerPacket
{
public:
ListComplete() : ServerPacket(PacketHeader(SMSG_LIST_COMPLETE, WOWREALM))
{
}
void Write() override { }
std::string ToString() const override { return "Battlenet::WoWRealm::ListComplete"; }
};
class ToonReady final : public ServerPacket
{
public:
ToonReady() : ServerPacket(PacketHeader(SMSG_TOON_READY, WOWREALM))
{
}
void Write() override;
std::string ToString() const override;
Toon::FullName Name;
Toon::Handle Handle;
Profile::RecordAddress ProfileAddress;
};
class ToonLoggedOut final : public ServerPacket
{
public:
ToonLoggedOut() : ServerPacket(PacketHeader(SMSG_TOON_LOGGED_OUT, WOWREALM))
{
}
void Write() override { }
std::string ToString() const override { return "Battlenet::WoWRealm::ToonLoggedOut"; }
};
class JoinResponseV2 final : public ServerPacket
{
public:
JoinResponseV2() : ServerPacket(PacketHeader(SMSG_JOIN_RESPONSE_V2, WOWREALM))
{
}
void Write() override;
std::string ToString() const override;
enum
{
SUCCESS = 0,
FAILURE = 1
};
int32 Type = SUCCESS;
struct SuccessType : public PrintableComponent
{
uint32 ServerSalt;
std::vector<tcp::endpoint> IPv4;
std::vector<tcp::endpoint> IPv6;
std::string ToString() const override;
} Success;
Wow::AuthResult Failure = Wow::WOW_SUCCESS;
};
}
}
#endif // WoWRealmPackets_h__

View File

@@ -1,10 +1,5 @@
#include "Common.h"
#include "Configuration/Config.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "ComponentManager.h"
#include "ModuleManager.h"
#include "RealmList.h"
#include "ByteBuffer.h"
#include "Packets.h"
#include "Session.h"
#include "LoginRESTService.h"
#include "SessionManager.h"
#include "SslContext.h"
#include "ServiceDispatcher.h"

View File

@@ -0,0 +1,433 @@
/*
* 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 "LoginRESTService.h"
#include "Configuration/Config.h"
#include "DatabaseEnv.h"
#include "ProtobufJSON.h"
#include "Realm.h"
#include "SessionManager.h"
#include "SHA1.h"
#include "SHA256.h"
#include "SslContext.h"
#include "Util.h"
#include "httpget.h"
#include "httppost.h"
#include "soapH.h"
int ns1__executeCommand(soap*, char*, char**) { return SOAP_OK; }
int32 handle_get_plugin(soap* soapClient)
{
return sLoginService.HandleGet(soapClient);
}
int32 handle_post_plugin(soap* soapClient)
{
return sLoginService.HandlePost(soapClient);
}
bool LoginRESTService::Start(boost::asio::io_service& ioService)
{
_bindIP = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");
_port = sConfigMgr->GetIntDefault("LoginREST.Port", 8081);
if (_port < 0 || _port > 0xFFFF)
{
TC_LOG_ERROR("server.rest", "Specified login service port (%d) out of allowed range (1-65535), defaulting to 8081", _port);
_port = 8081;
}
boost::system::error_code ec;
boost::asio::ip::tcp::resolver resolver(ioService);
boost::asio::ip::tcp::resolver::iterator end;
std::string configuredAddress = sConfigMgr->GetStringDefault("LoginREST.ExternalAddress", "127.0.0.1");
boost::asio::ip::tcp::resolver::query externalAddressQuery(boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port));
boost::asio::ip::tcp::resolver::iterator endPoint = resolver.resolve(externalAddressQuery, ec);
if (endPoint == end || ec)
{
TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.ExternalAddress %s", configuredAddress.c_str());
return false;
}
_externalAddress = endPoint->endpoint();
configuredAddress = sConfigMgr->GetStringDefault("LoginREST.LocalAddress", "127.0.0.1");
boost::asio::ip::tcp::resolver::query localAddressQuery(boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port));
endPoint = resolver.resolve(localAddressQuery, ec);
if (endPoint == end || ec)
{
TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.ExternalAddress %s", configuredAddress.c_str());
return false;
}
_localAddress = endPoint->endpoint();
// set up form inputs
Battlenet::JSON::Login::FormInput* input;
_formInputs.set_type(Battlenet::JSON::Login::LOGIN_FORM);
input = _formInputs.add_inputs();
input->set_input_id("account_name");
input->set_type("text");
input->set_label("E-mail");
input->set_max_length(320);
input = _formInputs.add_inputs();
input->set_input_id("password");
input->set_type("password");
input->set_label("Password");
input->set_max_length(16);
input = _formInputs.add_inputs();
input->set_input_id("log_in_submit");
input->set_type("submit");
input->set_label("Log In");
_loginTicketCleanupTimer = new boost::asio::deadline_timer(ioService);
_loginTicketCleanupTimer->expires_from_now(boost::posix_time::seconds(10));
_loginTicketCleanupTimer->async_wait(std::bind(&LoginRESTService::CleanupLoginTickets, this, std::placeholders::_1));
_thread = std::thread(std::bind(&LoginRESTService::Run, this));
return true;
}
void LoginRESTService::Stop()
{
_stopped = true;
_loginTicketCleanupTimer->cancel();
_thread.join();
}
boost::asio::ip::tcp::endpoint const& LoginRESTService::GetAddressForClient(boost::asio::ip::address const& address) const
{
if (address.is_loopback())
return _localAddress;
if (boost::asio::ip::address_v4::netmask(_localAddress.address().to_v4()).to_ulong() & address.to_v4().to_ulong())
return _localAddress;
return _externalAddress;
}
void LoginRESTService::Run()
{
soap soapServer(SOAP_C_UTFSTRING, SOAP_C_UTFSTRING);
// check every 3 seconds if world ended
soapServer.accept_timeout = 3;
soapServer.recv_timeout = 5;
soapServer.send_timeout = 5;
if (!soap_valid_socket(soap_bind(&soapServer, _bindIP.c_str(), _port, 100)))
{
TC_LOG_ERROR("server.rest", "Couldn't bind to %s:%d", _bindIP.c_str(), _port);
return;
}
TC_LOG_INFO("server.rest", "Login service bound to http://%s:%d", _bindIP.c_str(), _port);
http_post_handlers handlers[] =
{
{ "application/json;charset=utf-8", handle_post_plugin },
{ "application/json", handle_post_plugin },
{ NULL }
};
soap_register_plugin_arg(&soapServer, &http_get, handle_get_plugin);
soap_register_plugin_arg(&soapServer, &http_post, handlers);
soap_register_plugin_arg(&soapServer, &ContentTypePlugin::Init, "application/json;charset=utf-8");
// Use our already ready ssl context
soapServer.ctx = Battlenet::SslContext::instance().native_handle();
soapServer.ssl_flags = SOAP_SSL_RSA;
while (!_stopped)
{
if (!soap_valid_socket(soap_accept(&soapServer)))
continue; // ran into an accept timeout
std::unique_ptr<soap> soapClient = Trinity::make_unique<soap>(soapServer);
boost::asio::ip::address_v4 address(soapClient->ip);
if (soap_ssl_accept(soapClient.get()) != SOAP_OK)
{
TC_LOG_DEBUG("server.rest", "Failed SSL handshake from IP=%s", address.to_string().c_str());
continue;
}
TC_LOG_DEBUG("server.rest", "Accepted connection from IP=%s", address.to_string().c_str());
std::thread([soapClient{ std::move(soapClient) }]
{
soap_serve(soapClient.get());
}).detach();
}
// and release the context handle here - soap does not own it so it should not free it on exit
soapServer.ctx = nullptr;
TC_LOG_INFO("server.rest", "Login service exiting...");
}
int32 LoginRESTService::HandleGet(soap* soapClient)
{
boost::asio::ip::address_v4 address(soapClient->ip);
std::string ip_address = address.to_string();
TC_LOG_DEBUG("server.rest", "[%s:%d] Handling GET request path=\"%s\"", ip_address.c_str(), soapClient->port, soapClient->path);
static std::string const expectedPath = "/bnetserver/login/";
if (strstr(soapClient->path, expectedPath.c_str()) != &soapClient->path[0])
return 404;
return SendResponse(soapClient, _formInputs);
}
int32 LoginRESTService::HandlePost(soap* soapClient)
{
boost::asio::ip::address_v4 address(soapClient->ip);
std::string ip_address = address.to_string();
TC_LOG_DEBUG("server.rest", "[%s:%d] Handling POST request path=\"%s\"", ip_address.c_str(), soapClient->port, soapClient->path);
static std::string const expectedPath = "/bnetserver/login/";
if (strstr(soapClient->path, expectedPath.c_str()) != &soapClient->path[0])
return 404;
char *buf;
size_t len;
soap_http_body(soapClient, &buf, &len);
Battlenet::JSON::Login::LoginForm loginForm;
Battlenet::JSON::Login::LoginResult loginResult;
if (!JSON::Deserialize(buf, &loginForm))
{
if (soap_register_plugin_arg(soapClient, &ResponseCodePlugin::Init, nullptr) != SOAP_OK)
return 500;
ResponseCodePlugin* responseCode = reinterpret_cast<ResponseCodePlugin*>(soap_lookup_plugin(soapClient, ResponseCodePlugin::PluginId));
ASSERT(responseCode);
responseCode->ErrorCode = 400;
loginResult.set_authentication_state(Battlenet::JSON::Login::LOGIN);
loginResult.set_error_code("UNABLE_TO_DECODE");
loginResult.set_error_message("There was an internal error while connecting to Battle.net. Please try again later.");
return SendResponse(soapClient, loginResult);
}
std::string login;
std::string password;
for (int32 i = 0; i < loginForm.inputs_size(); ++i)
{
if (loginForm.inputs(i).input_id() == "account_name")
login = loginForm.inputs(i).value();
else if (loginForm.inputs(i).input_id() == "password")
password = loginForm.inputs(i).value();
}
Utf8ToUpperOnlyLatin(login);
Utf8ToUpperOnlyLatin(password);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO);
stmt->setString(0, login);
stmt->setString(1, CalculateShaPassHash(login, std::move(password)));
if (PreparedQueryResult result = LoginDatabase.Query(stmt))
{
std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo = Trinity::make_unique<Battlenet::Session::AccountInfo>();
accountInfo->LoadResult(result);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID);
stmt->setUInt32(0, accountInfo->Id);
if (PreparedQueryResult characterCountsResult = LoginDatabase.Query(stmt))
{
do
{
Field* fields = characterCountsResult->Fetch();
accountInfo->GameAccounts[fields[0].GetUInt32()]
.CharacterCounts[Battlenet::RealmHandle{ fields[3].GetUInt8(), fields[4].GetUInt8(), fields[2].GetUInt32() }.GetAddress()] = fields[1].GetUInt8();
} while (characterCountsResult->NextRow());
}
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS);
stmt->setUInt32(0, accountInfo->Id);
if (PreparedQueryResult lastPlayerCharactersResult = LoginDatabase.Query(stmt))
{
Field* fields = lastPlayerCharactersResult->Fetch();
Battlenet::RealmHandle realmId{ fields[1].GetUInt8(), fields[2].GetUInt8(), fields[3].GetUInt32() };
Battlenet::Session::LastPlayedCharacterInfo& lastPlayedCharacter = accountInfo->GameAccounts[fields[0].GetUInt32()]
.LastPlayedCharacters[realmId.GetSubRegionAddress()];
lastPlayedCharacter.RealmId = realmId;
lastPlayedCharacter.CharacterName = fields[4].GetString();
lastPlayedCharacter.CharacterGUID = fields[5].GetUInt64();
lastPlayedCharacter.LastPlayedTime = fields[6].GetUInt32();
}
BigNumber ticket;
ticket.SetRand(20 * 8);
loginResult.set_login_ticket("TC-" + ByteArrayToHexStr(ticket.AsByteArray(20).get(), 20));
AddLoginTicket(loginResult.login_ticket(), std::move(accountInfo));
}
loginResult.set_authentication_state(Battlenet::JSON::Login::DONE);
return SendResponse(soapClient, loginResult);
}
int32 LoginRESTService::SendResponse(soap* soapClient, google::protobuf::Message const& response)
{
std::string jsonResponse = JSON::Serialize(response);
soap_response(soapClient, SOAP_FILE);
soap_send_raw(soapClient, jsonResponse.c_str(), jsonResponse.length());
return soap_end_send(soapClient);
}
std::string LoginRESTService::CalculateShaPassHash(std::string const& name, std::string const& password)
{
SHA256Hash email;
email.UpdateData(name);
email.Finalize();
SHA256Hash sha;
sha.UpdateData(ByteArrayToHexStr(email.GetDigest(), email.GetLength()));
sha.UpdateData(":");
sha.UpdateData(password);
sha.Finalize();
return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength(), true);
}
std::unique_ptr<Battlenet::Session::AccountInfo> LoginRESTService::VerifyLoginTicket(std::string const& id)
{
std::unique_lock<std::mutex> lock(_loginTicketMutex);
auto itr = _validLoginTickets.find(id);
if (itr != _validLoginTickets.end())
{
if (itr->second.ExpiryTime > time(nullptr))
{
std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo = std::move(itr->second.Account);
_validLoginTickets.erase(itr);
return accountInfo;
}
}
return std::unique_ptr<Battlenet::Session::AccountInfo>();
}
void LoginRESTService::AddLoginTicket(std::string const& id, std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo)
{
std::unique_lock<std::mutex> lock(_loginTicketMutex);
_validLoginTickets[id] = { id, std::move(accountInfo), time(nullptr) + 10 };
}
void LoginRESTService::CleanupLoginTickets(boost::system::error_code const& error)
{
if (error)
return;
time_t now = time(nullptr);
{
std::unique_lock<std::mutex> lock(_loginTicketMutex);
for (auto itr = _validLoginTickets.begin(); itr != _validLoginTickets.end();)
{
if (itr->second.ExpiryTime < now)
itr = _validLoginTickets.erase(itr);
else
++itr;
}
}
_loginTicketCleanupTimer->expires_from_now(boost::posix_time::seconds(10));
_loginTicketCleanupTimer->async_wait(std::bind(&LoginRESTService::CleanupLoginTickets, this, std::placeholders::_1));
}
Namespace namespaces[] =
{
{ NULL, NULL, NULL, NULL }
};
LoginRESTService& LoginRESTService::Instance()
{
static LoginRESTService instance;
return instance;
}
char const* const LoginRESTService::ResponseCodePlugin::PluginId = "bnet-error-code";
int32 LoginRESTService::ResponseCodePlugin::Init(soap* s, soap_plugin* p, void* /*arg*/)
{
ResponseCodePlugin* data = new ResponseCodePlugin();
data->fresponse = s->fresponse;
p->id = PluginId;
p->fdelete = &Destroy;
p->data = data;
s->fresponse = &ChangeResponse;
return SOAP_OK;
}
void LoginRESTService::ResponseCodePlugin::Destroy(soap* s, soap_plugin* p)
{
ResponseCodePlugin* data = reinterpret_cast<ResponseCodePlugin*>(p->data);
s->fresponse = data->fresponse;
delete data;
}
int32 LoginRESTService::ResponseCodePlugin::ChangeResponse(soap* s, int32 originalResponse, size_t contentLength)
{
ResponseCodePlugin* self = reinterpret_cast<ResponseCodePlugin*>(soap_lookup_plugin(s, PluginId));
return self->fresponse(s, self->ErrorCode && originalResponse == SOAP_FILE ? self->ErrorCode : originalResponse, contentLength);
}
char const* const LoginRESTService::ContentTypePlugin::PluginId = "bnet-content-type";
int32 LoginRESTService::ContentTypePlugin::Init(soap* s, soap_plugin* p, void* arg)
{
ContentTypePlugin* data = new ContentTypePlugin();
data->fposthdr = s->fposthdr;
data->ContentType = reinterpret_cast<char const*>(arg);
p->id = PluginId;
p->fdelete = &Destroy;
p->data = data;
s->fposthdr = &OnSetHeader;
return SOAP_OK;
}
void LoginRESTService::ContentTypePlugin::Destroy(soap* s, soap_plugin* p)
{
ContentTypePlugin* data = reinterpret_cast<ContentTypePlugin*>(p->data);
s->fposthdr = data->fposthdr;
delete data;
}
int32 LoginRESTService::ContentTypePlugin::OnSetHeader(soap* s, char const* key, char const* value)
{
ContentTypePlugin* self = reinterpret_cast<ContentTypePlugin*>(soap_lookup_plugin(s, PluginId));
if (key && !strcmp("Content-Type", key))
value = self->ContentType;
return self->fposthdr(s, key, value);
}

View File

@@ -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 LoginRESTService_h__
#define LoginRESTService_h__
#include "Session.h"
#include "Define.h"
#include "Login.pb.h"
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <atomic>
#include <mutex>
#include <thread>
struct soap;
struct soap_plugin;
class LoginRESTService
{
public:
LoginRESTService() : _stopped(false), _port(0) { }
static LoginRESTService& Instance();
bool Start(boost::asio::io_service& ioService);
void Stop();
boost::asio::ip::tcp::endpoint const& GetAddressForClient(boost::asio::ip::address const& address) const;
std::unique_ptr<Battlenet::Session::AccountInfo> VerifyLoginTicket(std::string const& id);
private:
void Run();
friend int32 handle_get_plugin(soap* soapClient);
int32 HandleGet(soap* soapClient);
friend int32 handle_post_plugin(soap* soapClient);
int32 HandlePost(soap* soapClient);
int32 SendResponse(soap* soapClient, google::protobuf::Message const& response);
std::string CalculateShaPassHash(std::string const& name, std::string const& password);
void AddLoginTicket(std::string const& id, std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo);
void CleanupLoginTickets(boost::system::error_code const& error);
struct LoginTicket
{
std::string Id;
std::unique_ptr<Battlenet::Session::AccountInfo> Account;
std::time_t ExpiryTime;
};
struct ResponseCodePlugin
{
static char const* const PluginId;
static int32 Init(soap* s, soap_plugin*, void*);
static void Destroy(soap* s, soap_plugin* p);
static int32 ChangeResponse(soap* s, int32 originalResponse, size_t contentLength);
int32(*fresponse)(soap* s, int32 status, size_t length);
int32 ErrorCode;
};
struct ContentTypePlugin
{
static char const* const PluginId;
static int32 Init(soap* s, soap_plugin* p, void*);
static void Destroy(soap* s, soap_plugin* p);
static int32 OnSetHeader(soap* s, char const* key, char const* value);
int32(*fposthdr)(soap* s, char const* key, char const* value);
char const* ContentType;
};
std::thread _thread;
std::atomic<bool> _stopped;
Battlenet::JSON::Login::FormInputs _formInputs;
std::string _bindIP;
int32 _port;
boost::asio::ip::tcp::endpoint _externalAddress;
boost::asio::ip::tcp::endpoint _localAddress;
std::mutex _loginTicketMutex;
std::unordered_map<std::string, LoginTicket> _validLoginTickets;
boost::asio::deadline_timer* _loginTicketCleanupTimer;
};
#define sLoginService LoginRESTService::Instance()
#endif // LoginRESTService_h__

View File

@@ -1,55 +0,0 @@
/*
* 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 "ComponentManager.h"
#include "DatabaseEnv.h"
Battlenet::ComponentMgr::~ComponentMgr()
{
for (Version::Record* component : _components)
delete component;
}
void Battlenet::ComponentMgr::Load()
{
QueryResult result = LoginDatabase.Query("SELECT Program, Platform, Build FROM battlenet_components");
if (result)
{
do
{
Field* fields = result->Fetch();
Version::Record* component = new Version::Record();
component->ProgramId = fields[0].GetString();
component->Component = fields[1].GetString();
component->Version = fields[2].GetUInt32();
_components.insert(component);
_programs.insert(component->ProgramId);
_platforms.insert(component->Component);
} while (result->NextRow());
}
}
bool Battlenet::ComponentMgr::HasComponent(Battlenet::Version::Record const* component) const
{
for (Version::Record const* c : _components)
if (component->ProgramId == c->ProgramId && component->Component == c->Component && component->Version == c->Version)
return true;
return false;
}

View File

@@ -1,55 +0,0 @@
/*
* 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 ComponentManager_h__
#define ComponentManager_h__
#include "Define.h"
#include "PacketsCommon.h"
#include <cstring>
#include <string>
#include <set>
namespace Battlenet
{
class ComponentMgr
{
ComponentMgr() { }
~ComponentMgr();
public:
void Load();
bool HasComponent(Version::Record const* component) const;
bool HasProgram(std::string const& program) const { return _programs.count(program) != 0; }
bool HasPlatform(std::string const& platform) const { return _platforms.count(platform) != 0; }
static ComponentMgr* instance()
{
static ComponentMgr instance;
return &instance;
}
private:
std::set<Version::Record*> _components;
std::set<std::string> _programs;
std::set<std::string> _platforms;
};
}
#define sComponentMgr Battlenet::ComponentMgr::instance()
#endif // ComponentManager_h__

View File

@@ -1,66 +0,0 @@
/*
* 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 "ModuleManager.h"
#include "DatabaseEnv.h"
Battlenet::ModuleManager::~ModuleManager()
{
for (auto const& m : _modules)
delete m.second;
}
void Battlenet::ModuleManager::Load()
{
QueryResult result = LoginDatabase.Query("SELECT `Hash`, `Name`, `Type`, `System`, `Data` FROM battlenet_modules");
if (result)
{
do
{
Field* fields = result->Fetch();
ModuleInfo* module = new ModuleInfo();
module->Handle.Type = fields[2].GetString();
HexStrToByteArray(fields[0].GetString(), module->Handle.ModuleId);
std::string data = fields[4].GetString();
module->DataSize = data.length() / 2;
if (module->DataSize)
{
module->Data = new uint8[data.length() / 2];
HexStrToByteArray(data, module->Data);
}
_modules[{ fields[3].GetString(), fields[1].GetString() }] = module;
} while (result->NextRow());
}
}
Battlenet::ModuleInfo* Battlenet::ModuleManager::CreateModule(std::string const& os, std::string const& name) const
{
ModuleKey key { os, name };
if (!_modules.count(key))
return nullptr;
return new ModuleInfo(*_modules.at(key));
}
std::string Battlenet::ModuleInfo::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::ModuleInput" << std::endl;
APPEND_FIELD(stream, Handle);
return stream.str();
}

View File

@@ -1,91 +0,0 @@
/*
* 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 ModuleManager_h__
#define ModuleManager_h__
#include "PacketsCommon.h"
namespace Battlenet
{
struct ModuleKey
{
std::string Platform;
std::string Name;
bool operator<(ModuleKey const& right) const
{
int32 res = Platform.compare(right.Platform);
if (res < 0)
return true;
else if (res > 0)
return false;
return Name < right.Name;
}
};
struct ModuleInfo : public PrintableComponent
{
ModuleInfo() : DataSize(0), Data(nullptr) { Handle.Region = "EU"; }
ModuleInfo(ModuleInfo const& right) : DataSize(right.DataSize), Data(nullptr)
{
Handle.Type = right.Handle.Type;
Handle.Region = right.Handle.Region;
memcpy(Handle.ModuleId, right.Handle.ModuleId, 32);
if (DataSize)
{
Data = new uint8[DataSize];
memcpy(Data, right.Data, DataSize);
}
}
virtual ~ModuleInfo()
{
delete[] Data;
}
Cache::Handle Handle;
uint32 DataSize;
uint8* Data;
std::string ToString() const override;
};
class ModuleManager
{
ModuleManager() { }
~ModuleManager();
public:
void Load();
ModuleInfo* CreateModule(std::string const& os, std::string const& name) const;
static ModuleManager* instance()
{
static ModuleManager instance;
return &instance;
}
private:
std::map<ModuleKey, ModuleInfo*> _modules;
};
}
#define sModuleMgr Battlenet::ModuleManager::instance()
#endif // ModuleManager_h__

File diff suppressed because it is too large Load Diff

View File

@@ -18,140 +18,165 @@
#ifndef Session_h__
#define Session_h__
#include "Packets.h"
#include "BattlenetPacketCrypt.h"
#include "Realm.h"
#include "SslContext.h"
#include "SslSocket.h"
#include "Socket.h"
#include "BigNumber.h"
#include "Callback.h"
#include "MPSCQueue.h"
#include <memory>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl.hpp>
#include <google/protobuf/message.h>
#include <memory>
struct Realm;
using boost::asio::ip::tcp;
namespace pb = google::protobuf;
namespace bgs
{
namespace protocol
{
class Variant;
namespace account
{
namespace v1
{
class GetAccountStateRequest;
class GetAccountStateResponse;
class GetGameAccountStateRequest;
class GetGameAccountStateResponse;
}
}
namespace authentication
{
namespace v1
{
class LogonRequest;
class VerifyWebCredentialsRequest;
}
}
namespace game_utilities
{
namespace v1
{
class ClientRequest;
class ClientResponse;
class GetAllValuesForAttributeRequest;
class GetAllValuesForAttributeResponse;
}
}
}
}
using namespace bgs::protocol;
namespace Battlenet
{
struct PacketHeader;
class BitStream;
enum ModuleType
class Session : public Socket<Session, SslSocket<SslContext>>
{
MODULE_PASSWORD,
MODULE_TOKEN,
MODULE_THUMBPRINT,
MODULE_SELECT_GAME_ACCOUNT,
MODULE_RISK_FINGERPRINT,
MODULE_RESUME,
MODULE_COUNT
};
enum class BufferSizes : uint32
{
SRP_6_V = 0x80,
SRP_6_S = 0x20,
Read = 0x4000
};
struct AccountInfo
{
void LoadResult(Field* fields);
uint32 Id;
std::string Login;
bool IsLockedToIP;
std::string LockCountry;
std::string LastIP;
uint32 FailedLogins;
bool IsBanned;
bool IsPermanenetlyBanned;
};
struct GameAccountInfo
{
void LoadResult(Field* fields);
uint32 Id;
std::string Name;
std::string DisplayName;
bool IsBanned;
bool IsPermanenetlyBanned;
AccountTypes SecurityLevel;
};
class Session : public Socket<Session>
{
typedef Socket<Session> BattlenetSocket;
typedef Socket<Session, SslSocket<SslContext>> BattlenetSocket;
public:
struct LastPlayedCharacterInfo
{
Battlenet::RealmHandle RealmId;
std::string CharacterName;
uint64 CharacterGUID;
uint32 LastPlayedTime;
};
struct GameAccountInfo
{
void LoadResult(Field* fields);
uint32 Id;
std::string Name;
std::string DisplayName;
bool IsBanned;
bool IsPermanenetlyBanned;
AccountTypes SecurityLevel;
std::unordered_map<uint32 /*realmAddress*/, uint8> CharacterCounts;
std::unordered_map<std::string /*subRegion*/, LastPlayedCharacterInfo> LastPlayedCharacters;
};
struct AccountInfo
{
void LoadResult(PreparedQueryResult result);
uint32 Id;
std::string Login;
bool IsLockedToIP;
std::string LockCountry;
std::string LastIP;
uint32 FailedLogins;
bool IsBanned;
bool IsPermanenetlyBanned;
std::unordered_map<uint32, GameAccountInfo> GameAccounts;
};
explicit Session(tcp::socket&& socket);
~Session();
void LogUnhandledPacket(PacketHeader const& header);
// Authentication
void HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest);
void HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest);
void HandleProofResponse(Authentication::ProofResponse const& proofResponse);
// Connection
void HandlePing(Connection::Ping const& ping);
void HandleEnableEncryption(Connection::EnableEncryption& enableEncryption);
void HandleLogoutRequest(Connection::LogoutRequest const& logoutRequest);
void HandleConnectionClosing(Connection::ConnectionClosing const& connectionClosing);
// WoWRealm
void HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& listSubscribeRequest);
void HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& listUnsubscribe);
void HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest);
// Friends
// Cache
void HandleGetStreamItemsRequest(Cache::GetStreamItemsRequest const& getStreamItemsRequest);
void Start() override;
bool Update() override;
void UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmHandle>& deletedRealms);
uint32 GetAccountId() const { return _accountInfo->Id; }
uint32 GetGameAccountId() const { return _gameAccountInfo->Id; }
bool IsToonOnline() const { return _toonOnline; }
void SetToonOnline(bool online) { _toonOnline = online; }
void SendResponse(uint32 token, pb::Message const* response);
void SendResponse(uint32 token, uint32 status);
bool IsSubscribedToRealmListUpdates() const { return _subscribedToRealmListUpdates; }
void SendRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request, std::function<void(MessageBuffer)> callback)
{
_responseCallbacks[_requestToken] = std::move(callback);
SendRequest(serviceHash, methodId, request);
}
void AsyncWrite(ServerPacket* packet);
void SendRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request);
protected:
void ReadHandler() override;
uint32 HandleLogon(authentication::v1::LogonRequest const* logonRequest);
uint32 HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* verifyWebCredentialsRequest);
uint32 HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response);
uint32 HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response);
uint32 HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response);
uint32 HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response);
private:
void _SetVSFields(std::string const& rI);
typedef bool(Session::*ModuleHandler)(BitStream* dataStream, ServerPacket** response);
static ModuleHandler const ModuleHandlers[MODULE_COUNT];
void CheckIpCallback(PreparedQueryResult result);
void HandleLogonRequestCallback(PreparedQueryResult result);
void HandleResumeRequestCallback(PreparedQueryResult result);
void HandleListSubscribeRequestCallback(PreparedQueryResult result);
bool HandlePasswordModule(BitStream* dataStream, ServerPacket** response);
bool HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response);
bool HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response);
bool HandleResumeModule(BitStream* dataStream, ServerPacket** response);
bool UnhandledModule(BitStream* dataStream, ServerPacket** response);
WoWRealm::ListUpdate* BuildListUpdate(Realm const* realm) const;
std::string GetClientInfo() const;
AccountInfo* _accountInfo;
protected:
void HandshakeHandler(boost::system::error_code const& error);
void ReadHandler() override;
bool ReadHeaderLengthHandler();
bool ReadHeaderHandler();
bool ReadDataHandler();
private:
void AsyncWrite(MessageBuffer* packet);
void AsyncHandshake();
void CheckIpCallback(PreparedQueryResult result);
typedef uint32(Session::*ClientRequestHandler)(std::unordered_map<std::string, Variant const*> const&, game_utilities::v1::ClientResponse*);
static std::unordered_map<std::string, ClientRequestHandler> const ClientRequestHandlers;
uint32 GetRealmListTicket(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response);
uint32 GetLastCharPlayed(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response);
uint32 GetRealmList(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response);
uint32 JoinRealm(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response);
MessageBuffer _headerLengthBuffer;
MessageBuffer _headerBuffer;
MessageBuffer _packetBuffer;
std::unique_ptr<AccountInfo> _accountInfo;
GameAccountInfo* _gameAccountInfo; // Points at selected game account (inside _gameAccounts)
std::vector<GameAccountInfo> _gameAccounts;
std::string _locale;
std::string _os;
@@ -159,38 +184,16 @@ namespace Battlenet
std::string _ipCountry;
BigNumber N;
BigNumber g;
BigNumber k;
std::array<uint8, 32> _clientSecret;
BigNumber I;
BigNumber s;
BigNumber v;
BigNumber b;
BigNumber B;
BigNumber K; // session key
BigNumber _reconnectProof;
std::queue<ModuleType> _modulesWaitingForData;
struct EncryptableBuffer
{
MessageBuffer Buffer;
bool Encrypt;
};
MPSCQueue<EncryptableBuffer> _bufferQueue;
PacketCrypt _crypt;
bool _authed;
bool _subscribedToRealmListUpdates;
bool _toonOnline;
PreparedQueryResultFuture _queryFuture;
std::function<void(PreparedQueryResult)> _queryCallback;
};
std::unordered_map<uint32, std::function<void(MessageBuffer)>> _responseCallbacks;
uint32 _requestToken;
};
}
#endif // Session_h__

View File

@@ -37,41 +37,8 @@ void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock, uint32 thread
sSessionMgr.OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex);
}
void Battlenet::SessionManager::AddSession(Session* session)
Battlenet::SessionManager& Battlenet::SessionManager::Instance()
{
std::unique_lock<boost::shared_mutex> lock(_sessionMutex);
_sessions[{ session->GetAccountId(), session->GetGameAccountId() }] = session;
_sessionsByAccountId[session->GetAccountId()].push_back(session);
}
void Battlenet::SessionManager::RemoveSession(Session* session)
{
std::unique_lock<boost::shared_mutex> lock(_sessionMutex);
auto itr = _sessions.find({ session->GetAccountId(), session->GetGameAccountId() });
// Remove old session only if it was not overwritten by reconnecting
if (itr != _sessions.end() && itr->second == session)
_sessions.erase(itr);
_sessionsByAccountId[session->GetAccountId()].remove(session);
}
Battlenet::Session* Battlenet::SessionManager::GetSession(uint32 accountId, uint32 gameAccountId) const
{
boost::shared_lock<boost::shared_mutex> lock(_sessionMutex);
auto itr = _sessions.find({ accountId, gameAccountId });
if (itr != _sessions.end())
return itr->second;
return nullptr;
}
std::list<Battlenet::Session*> Battlenet::SessionManager::GetSessions(uint32 accountId) const
{
boost::shared_lock<boost::shared_mutex> lock(_sessionMutex);
std::list<Session*> sessions;
auto itr = _sessionsByAccountId.find(accountId);
if (itr != _sessionsByAccountId.end())
sessions = itr->second;
return sessions;
static SessionManager instance;
return instance;
}

View File

@@ -18,68 +18,25 @@
#ifndef SessionManager_h__
#define SessionManager_h__
#include "Session.h"
#include "SocketMgr.h"
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include "Session.h"
namespace Battlenet
{
#pragma pack(push, 1)
struct SessionInfo
{
uint32 AccountId;
uint32 GameAccountId;
bool operator<(SessionInfo const& right) const
{
return memcmp(this, &right, sizeof(SessionInfo)) < 0;
}
};
#pragma pack(pop)
class SessionManager : public SocketMgr<Session>
{
typedef SocketMgr<Session> BaseSocketMgr;
typedef std::map<SessionInfo, Session*> SessionMap;
typedef std::map<uint32, std::list<Session*>> SessionByAccountMap;
public:
static SessionManager& Instance()
{
static SessionManager instance;
return instance;
}
static SessionManager& Instance();
bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount = 1) override;
// noop for now, will be needed later to broadcast realmlist updates for example
void AddSession(Session* /*session*/);
void RemoveSession(Session* /*session*/);
Session* GetSession(uint32 accountId, uint32 gameAccountId) const;
std::list<Session*> GetSessions(uint32 accountId) const;
template<typename Iterator>
void LockedForEach(Iterator iterator) const
{
boost::shared_lock<boost::shared_mutex> lock(_sessionMutex);
for (SessionMap::value_type const& pair : _sessions)
iterator(pair.second);
}
protected:
NetworkThread<Session>* CreateThreads() const override;
private:
static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex);
SessionMap _sessions;
SessionByAccountMap _sessionsByAccountId;
mutable boost::shared_mutex _sessionMutex;
};
}

View File

@@ -0,0 +1,45 @@
/*
* 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 "SslContext.h"
#include "Log.h"
bool Battlenet::SslContext::Initialize()
{
boost::system::error_code err;
#define LOAD_CHECK(fn) do { fn; \
if (err) \
{ \
TC_LOG_ERROR("server.ssl", #fn ## "failed: %s", err.message().c_str()); \
return false; \
} } while (0)
LOAD_CHECK(instance().set_options(boost::asio::ssl::context::no_sslv3, err));
LOAD_CHECK(instance().use_certificate_chain_file("bnetserver.cert.pem", err));
LOAD_CHECK(instance().use_private_key_file("bnetserver.key.pem", boost::asio::ssl::context::pem, err));
#undef LOAD_CHECK
return true;
}
boost::asio::ssl::context& Battlenet::SslContext::instance()
{
static boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
return context;
}

View File

@@ -15,16 +15,20 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BitStream.h"
#ifndef SslContext_h__
#define SslContext_h__
template<>
bool Battlenet::BitStream::Read<bool>(uint32 /*bitCount*/)
#include <boost/asio/ssl/context.hpp>
namespace Battlenet
{
return Read<uint8>(1) != 0;
class SslContext
{
public:
static bool Initialize();
static boost::asio::ssl::context& instance();
};
}
template<>
void Battlenet::BitStream::Write<bool>(bool value, uint32 /*bitCount*/)
{
Write<uint8>(value ? 1 : 0, 1);
}
#endif // SslContext_h__

View File

@@ -15,21 +15,19 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SupportPackets_h__
#define SupportPackets_h__
#include "AccountService.h"
#include "Session.h"
#include "PacketsBase.h"
namespace Battlenet
Battlenet::Services::Account::Account(Session* session) : AccountService(session)
{
namespace Support
{
enum Opcode
{
CMSG_COMPLAINT_REQUEST = 0x0, // Deprecated in client
CMSG_COMPLAINT_REQUEST_2 = 0x1 // Not implemented
};
}
}
#endif // SupportPackets_h__
uint32 Battlenet::Services::Account::HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response)
{
return _session->HandleGetAccountState(request, response);
}
uint32 Battlenet::Services::Account::HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response)
{
return _session->HandleGetGameAccountState(request, response);
}

View File

@@ -15,28 +15,30 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AchievementPackets_h__
#define AchievementPackets_h__
#ifndef AccountService_h__
#define AccountService_h__
#include "PacketsBase.h"
#include "Common.h"
#include "Service.h"
#include "account_service.pb.h"
namespace Battlenet
{
namespace Achievement
{
enum Opcode
{
CMSG_LISTEN_REQUEST = 0x0, // Not implemented
CMSG_CRITERIA_FLUSH_REQUEST = 0x3, // Not implemented
CMSG_CHANGE_TROPHY_CASE_REQUEST = 0x5, // Not implemented
class Session;
SMSG_DATA = 0x2, // Not implemented
SMSG_CRITERIA_FLUSH_RESPONSE = 0x3, // Not implemented
SMSG_ACHIEVEMENT_HANDLE_UPDATE = 0x4, // Not implemented
SMSG_CHANGE_TROPHY_CASE_RESULT = 0x6 // Not implemented
namespace Services
{
class Account : public Service<account::v1::AccountService>
{
typedef Service<account::v1::AccountService> AccountService;
public:
Account(Session* session);
uint32 HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response) override;
uint32 HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response) override;
};
}
}
#endif // AchievementPackets_h__
#endif // AccountService_h__

View File

@@ -15,25 +15,19 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PresencePackets_h__
#define PresencePackets_h__
#include "AuthenticationService.h"
#include "Session.h"
#include "PacketsBase.h"
namespace Battlenet
Battlenet::Services::Authentication::Authentication(Session* session) : AuthenticationService(session)
{
namespace Presence
{
enum Opcode
{
CMSG_UPDATE_REQUEST = 0x0, // Not implemented
CMSG_STATISTIC_SUBSCRIBE = 0x2, // Not implemented
SMSG_UPDATE_NOTIFY = 0x0, // Not implemented
SMSG_FIELD_SPEC_ANNOUNCE = 0x1, // Not implemented
SMSG_STATISTICS_UPDATE = 0x3 // Not implemented
};
}
}
#endif // PresencePackets_h__
uint32 Battlenet::Services::Authentication::HandleLogon(authentication::v1::LogonRequest const* request, NoData* /*respons*/)
{
return _session->HandleLogon(request);
}
uint32 Battlenet::Services::Authentication::HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* request, NoData* /*respons*/)
{
return _session->HandleVerifyWebCredentials(request);
}

View File

@@ -0,0 +1,44 @@
/*
* 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 AuthenticationService_h__
#define AuthenticationService_h__
#include "Common.h"
#include "Service.h"
#include "authentication_service.pb.h"
namespace Battlenet
{
class Session;
namespace Services
{
class Authentication : public Service<authentication::v1::AuthenticationService>
{
typedef Service<authentication::v1::AuthenticationService> AuthenticationService;
public:
Authentication(Session* session);
uint32 HandleLogon(authentication::v1::LogonRequest const* request, NoData* respons) override;
uint32 HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* request, NoData* respons) override;
};
}
}
#endif // AuthenticationService_h__

View File

@@ -0,0 +1,57 @@
/*
* 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 "ConnectionService.h"
#include "Duration.h"
#include "Log.h"
#include "Session.h"
#include "Util.h"
#include "BattlenetRpcErrorCodes.h"
Battlenet::Services::Connection::Connection(Session* session) : ConnectionService(session)
{
}
uint32 Battlenet::Services::Connection::HandleConnect(connection::v1::ConnectRequest const* request, connection::v1::ConnectResponse* response)
{
if (request->has_client_id())
response->mutable_client_id()->CopyFrom(request->client_id());
std::chrono::system_clock::duration now = std::chrono::system_clock::now().time_since_epoch();
response->mutable_server_id()->set_label(GetPID());
response->mutable_server_id()->set_epoch(std::chrono::duration_cast<Seconds>(now).count());
response->set_server_time(std::chrono::duration_cast<Milliseconds>(now).count());
response->set_use_bindless_rpc(request->use_bindless_rpc());
return ERROR_OK;
}
uint32 Battlenet::Services::Connection::HandleKeepAlive(NoData const* /*request*/)
{
return ERROR_OK;
}
uint32 Battlenet::Services::Connection::HandleRequestDisconnect(connection::v1::DisconnectRequest const* request)
{
connection::v1::DisconnectNotification disconnectNotification;
disconnectNotification.set_error_code(request->error_code());
ForceDisconnect(&disconnectNotification);
_session->DelayedCloseSocket();
return ERROR_OK;
}

View File

@@ -0,0 +1,46 @@
/*
* 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 ConnectionService_h__
#define ConnectionService_h__
#include "Common.h"
#include "Service.h"
#include "connection_service.pb.h"
namespace Battlenet
{
class Session;
namespace Services
{
class Connection : public Service<connection::v1::ConnectionService>
{
typedef Service<connection::v1::ConnectionService> ConnectionService;
public:
Connection(Session* session);
uint32 HandleConnect(connection::v1::ConnectRequest const* request, connection::v1::ConnectResponse* respons) override;
uint32 HandleKeepAlive(NoData const* request) override;
uint32 HandleRequestDisconnect(connection::v1::DisconnectRequest const* request) override;
};
}
}
#endif // ConnectionService_h__

View File

@@ -15,32 +15,19 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Packets.h"
#include "GameUtilitiesService.h"
#include "Session.h"
#include <sstream>
std::string Battlenet::PacketHeader::ToString() const
Battlenet::Services::GameUtilities::GameUtilities(Session* session) : GameUtilitiesService(session)
{
std::ostringstream stream;
stream << "Battlenet::PacketHeader" << std::endl;
APPEND_FIELD(stream, Command);
APPEND_FIELD(stream, Channel);
return stream.str();
}
Battlenet::ServerPacket::ServerPacket(PacketHeader const& header) : Packet(header, *new BitStream())
uint32 Battlenet::Services::GameUtilities::HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response)
{
_stream.Write(header.Command, 6);
_stream.Write(1, 1);
_stream.Write(header.Channel, 4);
return _session->HandleProcessClientRequest(request, response);
}
Battlenet::ServerPacket::~ServerPacket()
uint32 Battlenet::Services::GameUtilities::HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response)
{
delete &_stream;
}
void Battlenet::ClientPacket::CallHandler(Session* session)
{
session->LogUnhandledPacket(GetHeader());
return _session->HandleGetAllValuesForAttribute(request, response);
}

View File

@@ -0,0 +1,44 @@
/*
* 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 GameUtilitiesServiceService_h__
#define GameUtilitiesServiceService_h__
#include "Common.h"
#include "Service.h"
#include "game_utilities_service.pb.h"
namespace Battlenet
{
class Session;
namespace Services
{
class GameUtilities : public Service<game_utilities::v1::GameUtilitiesService>
{
typedef Service<game_utilities::v1::GameUtilitiesService> GameUtilitiesService;
public:
GameUtilities(Session* 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;
};
}
}
#endif // GameUtilitiesServiceService_h__

View File

@@ -0,0 +1,45 @@
/*
* 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 Service_h__
#define Service_h__
#include "Session.h"
namespace bgs { namespace protocol { } }
using namespace bgs::protocol;
namespace Battlenet
{
template<class T>
class Service : public T
{
public:
Service(Session* session) : T(true), _session(session) { }
protected:
void SendRequest(uint32 serviceHash, uint32 methodId, google::protobuf::Message const* request, std::function<void(MessageBuffer)> callback) override { _session->SendRequest(serviceHash, methodId, request, std::move(callback)); }
void SendRequest(uint32 serviceHash, uint32 methodId, google::protobuf::Message const* request) override { _session->SendRequest(serviceHash, methodId, request); }
void SendResponse(uint32 /*serviceHash*/, uint32 /*methodId*/, uint32 token, uint32 status) override { _session->SendResponse(token, status); }
void SendResponse(uint32 /*serviceHash*/, uint32 /*methodId*/, uint32 token, google::protobuf::Message const* response) override { _session->SendResponse(token, response); }
std::string GetCallerInfo() const override { return _session->GetClientInfo(); }
Session* _session;
};
}
#endif // Service_h__

View File

@@ -0,0 +1,48 @@
/*
* 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 "ServiceDispatcher.h"
Battlenet::ServiceDispatcher::ServiceDispatcher()
{
AddService<Services::Account>();
AddService<Services::Authentication>();
AddService<Service<challenge::v1::ChallengeService>>();
AddService<Service<channel::v1::ChannelService>>();
AddService<Services::Connection>();
AddService<Service<friends::v1::FriendsService>>();
AddService<Services::GameUtilities>();
AddService<Service<presence::v1::PresenceService>>();
AddService<Service<report::v1::ReportService>>();
AddService<Service<resources::v1::ResourcesService>>();
AddService<Service<user_manager::v1::UserManagerService>>();
}
void Battlenet::ServiceDispatcher::Dispatch(Session* 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->GetClientInfo().c_str(), serviceHash);
}
Battlenet::ServiceDispatcher& Battlenet::ServiceDispatcher::Instance()
{
static ServiceDispatcher instance;
return instance;
}

View File

@@ -0,0 +1,68 @@
/*
* 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 "MessageBuffer.h"
#include "Log.h"
#include "Common.h"
#include "AccountService.h"
#include "AuthenticationService.h"
#include "challenge_service.pb.h"
#include "channel_service.pb.h"
#include "ConnectionService.h"
#include "friends_service.pb.h"
#include "GameUtilitiesService.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 Session;
class ServiceDispatcher
{
public:
void Dispatch(Session* session, uint32 serviceHash, uint32 token, uint32 methodId, MessageBuffer buffer);
static ServiceDispatcher& Instance();
private:
ServiceDispatcher();
template<class Service>
void AddService()
{
_dispatchers[Service::OriginalHash::value] = &ServiceDispatcher::Dispatch<Service>;
}
template<class Service>
static void Dispatch(Session* session, uint32 token, uint32 methodId, MessageBuffer buffer)
{
Service(session).CallServerMethod(token, methodId, std::forward<MessageBuffer>(buffer));
}
std::unordered_map<uint32, std::function<void(Session*, uint32, uint32, MessageBuffer)>> _dispatchers;
};
}
#define sServiceDispatcher ServiceDispatcher::Instance()
#endif // ServiceRegistry_h__

View File

@@ -0,0 +1,100 @@
-----BEGIN CERTIFICATE-----
MIIFhjCCA26gAwIBAgIBATANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJVUzEU
MBIGA1UECgwLVHJpbml0eUNvcmUxKjAoBgNVBAsMIVRyaW5pdHlDb3JlIENlcnRp
ZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAwwgVHJpbml0eUNvcmUgQmF0dGxlLm5l
dCBBdXJvcmEgQ0EwHhcNMTYwMjI4MTMxMTI4WhcNMzYwMjIzMTMxMTI4WjBGMQsw
CQYDVQQGEwJVUzEUMBIGA1UECgwLVHJpbml0eUNvcmUxEzARBgNVBAsMCkRldmVs
b3BlcnMxDDAKBgNVBAMMAyouKjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMDdxGJioQxmsBq4etsAII4d8K+AnFepaetRL9/Y805IHrVwwRdklgvbP6c0
v4ddB0MC/T9HGJam2R4/3WqzqYXKqZStOVrCQvO+pVAEknlVlT4h7Jn6Us48eual
dj35nDRNUlBIszjn6WqMby31aoecuDJLksV8Tlwl0vQp0AcEKPH/+LlenMx2YIoI
uwkiA++VSt1Yar5U2i2BaBIjqY1jQEO8f9fLL/laElbl/mpWHs9jw8FPoZdAqcxC
KrWmr57XHvbEN7hHd3l2BgCael/mzlSLUZlIW91l6CF5hzGi3uaEnHCDWte2S+x9
iEjqq/9T36vOApP1UrW8xHyXU2cCAwEAAaOCAUkwggFFMAkGA1UdEwQCMAAwEQYJ
YIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRl
ZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFL5TLPbXOTB9xRBJ8pUFw7+2
6nlqMIGrBgNVHSMEgaMwgaCAFI7XCpyCprztwOvx8+S7g+SXQuFZoYGEpIGBMH8x
CzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwhVHJp
bml0eUNvcmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS4wLAYDVQQDDCVUcmluaXR5
Q29yZSBCYXR0bGUubmV0IEF1cm9yYSBSb290IENBggEBMA4GA1UdDwEB/wQEAwIF
oDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAgEACt0tfSaR
8wu4GPpqDD69Ch7o2tN6K4Wr8S2xkdmVMKTp6DXvpeWVlIiK30q8yxQdrzupyaTJ
CVmWmA+IAHlaHYy5EsWI3CW2q47y6HugZoGEYL7oVZEcgCy3F1c2q100T/fdYXoO
Se6PM87hC9iE9kvmL8WxN8o98zRYcrSgzen/xJjESSR1gdyVBiFiT0RE4qr+tFkq
JW6PUZiYoFXXerqR5QrsUkIkIYBp9f2BCOR9ZMlrlKe/ojUaRaW/3fFwyV22g+jQ
MRkzkxeg6ynfTcsMiiIHSpX3ajy+m03mfbp1fIaHr/F6YbxqpzylfUOu0VOp3cUo
5/so4JESWMpDaArmlNdfrfvLAjn0jKQZwNg/rI5SNGF55r2Dc8KXc6rZ7wJo0bvl
ZQIQMWES1ZLxBa/r5yF8kPnxUrNLIQ8HdPxonPeU5L2CpEv8k3Fii//8N6h0Orpv
I+FUGpYOcdBLITb/jVn5WkXW0q3Qjlb5MQjLyRweBVfP6WOUbyI3rV+BvbrgkJSI
DqN2duvVLJgJa6ebmYRs1NfkTaX/TY3MB4B+Eo0nM6f9qSbptDo2oXAt6mhJDyRQ
m9T7wdl98+cv5QlCZUBPbOEGv8ZM2I/hUZeW+svcWhd1ONyLVByCAFLsGWpAylML
DgH8o+NLrjzNhQxllkENFN0mVnfc42Yo+T8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF2jCCA8KgAwIBAgIBATANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJVUzEU
MBIGA1UECgwLVHJpbml0eUNvcmUxKjAoBgNVBAsMIVRyaW5pdHlDb3JlIENlcnRp
ZmljYXRlIEF1dGhvcml0eTEuMCwGA1UEAwwlVHJpbml0eUNvcmUgQmF0dGxlLm5l
dCBBdXJvcmEgUm9vdCBDQTAeFw0xNjAyMjgxMzAxMjJaFw0zNjAyMjMxMzAxMjJa
MHoxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwh
VHJpbml0eUNvcmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSkwJwYDVQQDDCBUcmlu
aXR5Q29yZSBCYXR0bGUubmV0IEF1cm9yYSBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAMOim0oMJ8hed2ZO0n4FSWCK+AqTKqOKEwkZzmv+f0jd5dH9
F9DmlkqGJXb1FWsd+5rp6GbDHorMsJDIKBfWuNxoVHvgSQUnBXosY/TTXn6DbLCN
hZWnfxARzAp8T/FXL/rlwhR1cYkN+WugAq58/Aa+khaG2JNvSb/e1y5KiJ7wKN2N
bFLZ/dIslBE5gJzgO5hU19WM0vSXRl2Pw0gWBNvvZUa4FH4tW95zdARtAxJPgg1d
21qtXnfbE8xTCLKE5GAIlOK+r9+3elt6y+EZiZ8cq/b/Jfp+1GNBAlVLlpPzS7LQ
f+DtVKJ4FTtADWmRWEEy4vaUhblDfo2nokNdmcnTy93bmOHwJlKkRZVT/vwhKlMS
INtBEXJfZS+UM+CvhIAhSwRwSa97Nz8WEpNvWJwl/eUT3D+JOF+bklTvR7Vwwwtu
PgJks8+aLCjEC/T5n7KotxTV1tW5OD3Dy3urJ01INe0SEHMMPVPj2ejqHg2ndGRF
dC0QlmIxNpaSGqs5H12rxbmwyOpv2P0+ESwlWCJn87WUJhbs9ez3lr8OyXByMpvU
5wqJxzrTMkJ2xHQp8XVIJclKHt/irExru/v7wS05usvr5fC4uCICAqQO5Ed6OvP+
/krW3YNR/5UgzUpFz+2md4AIXur8uU6qVEc31fKufiTWnVS2h3v1tccGsKg/AgMB
AAGjZjBkMB0GA1UdDgQWBBSO1wqcgqa87cDr8fPku4Pkl0LhWTAfBgNVHSMEGDAW
gBQS3qDGF+YcRzusE6ockR82TMa/czASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAvxnyXNtRosLnrG4BCgr3zwHx
H0T4h2yllCsqcM9DE3dBzyjtIooHLIEtuK5JtZKQawh95Hg9Y/e+aiXPgiIZtsob
mJn8GovjB6JpUsiA5I7NqNfOfcsZu39/PZC2F0C8t7M1FHmQpSEnL5m9pGnJ4Kzi
y/Zz4woAeT+tipJISDPJnWjvItQOS8Wv/mScbHa/8Z7o21ZITZMGRG8LIo8Fpc+p
8VT9ysJ1WvP/Cc1g703ojperADspKpA/yAWSI0WBrlNUUP3zN/RNKJq+pwKSad+3
o30tYGDkfTUMDFfsJ68UwalZHPuwCuG5g4ZIhMQwqzeOhX8nW40Pcsc9dQPIF2Jz
FHfSRtAUj0JCb5dS08AH7z2wQRELkzeR5x/5GB6b9fg96xjcHWTsfbH7K63e6Lv4
+ZEggfBip5VCL9xAyNK22p1TvXLY73V2zyqJ9dH/8lGWfm+OvQ1hzQbwPJ7J8BPI
u+fJJaOze557QKTmeHYPvoj/q3X2xLyMXW236fu5EBXK1RhDgrRXxf4aHB0Bzn7n
quyUU8spdLG97OljvGEiESLj9oWYbXKLnWqz6TWOnAmTtRLaK2iau3iP+7lwkaoe
Q6DZHDkgLtiTx7VwsSJZTU5o+TPj4wfjS9Jl3j8PMVPpfG5IFF3ErOEsz/KPu9Nz
j7x/l+OtqHw4Pithuig=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF5DCCA8ygAwIBAgIJAIgLslwk40XzMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV
BAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwhVHJpbml0eUNv
cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS4wLAYDVQQDDCVUcmluaXR5Q29yZSBC
YXR0bGUubmV0IEF1cm9yYSBSb290IENBMB4XDTE2MDIyODEyNDkwOFoXDTM2MDIy
MzEyNDkwOFowfzELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1RyaW5pdHlDb3JlMSow
KAYDVQQLDCFUcmluaXR5Q29yZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNV
BAMMJVRyaW5pdHlDb3JlIEJhdHRsZS5uZXQgQXVyb3JhIFJvb3QgQ0EwggIiMA0G
CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGrYWvS0mVParJd96E4z/qjCvW6eR0
buQ++VNEqVgeG14k4V41wkEzakB4nr2oGH10z9J/aqLlWnxaOl+yJ7BaomUAAOgJ
aCyqAJ8HaEU+7BbDO4MZXmtw1A3YcHsBkVx5wGm3tcH5IEXfVhvNZDqwAmYIcm7g
KFgnds6RFJmRxF4WznWiRr2MQkSOr/kc2eQ2VUg5afTlTxZva/mXEVpShinvbhaM
SgFBW+QahCwBJVQaLhEn+Wc6YNuHFmZ/i716xGb3cuYu89TF46iKQ/9Bm8yEFGg8
QA28IZQ1sXgVpzJI9eowFtqAwhl65ipjGw4xH33of+WcwJQNjF7HXymRqk0WAa2j
tXOEiShI3XDloblX7vKbAe9RFpfVIqT8UfKSOJGQDVzvl4wSihINshO7YgIqp97M
GnWtnlWCDb2mcSj8JjnzRjG2kZZCNR/2lgfCG/1VF+QLh/3vD2+N5YkJZqBK1JTF
Fx+p66lVQWfdh2MXPlGjat343HZGm0YR7nRjngO2j3YtTojdJxRfLgztQv94jMtW
PHE38ysUK7mS6KKqYXqyB19IOHL2QB8fjmON1hCd0wDW42ZB23ywNkASw6uJDR02
xXN2wiynIIb3cz6zouXd60wC7utMTveq8+rhFFgmFDdI2o9gwWQPA/43OYIlAdKV
g2NRhXb/6bzFkwIDAQABo2MwYTAdBgNVHQ4EFgQUEt6gxhfmHEc7rBOqHJEfNkzG
v3MwHwYDVR0jBBgwFoAUEt6gxhfmHEc7rBOqHJEfNkzGv3MwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAFzCJkcDCPVM
al+Thlip26LPkszZ4zWTsNsbUYmSe7h0kmMWt4x3mmZITfwb/eysYCnHThBVTjXj
9VWBGfbECZ/xdyXC2ur+qp0Mm7xH2Wuswf7yfPC+USNO6+/tFS282FO/nM0quaKV
knOC8ioCoASsBICB9lwRoYRKNBwRn3pkJplHepGahaJez4eedujO3dzxDdD32zy2
/AfdeFXTxhWY8PTjMBKC2zpUQD7Kdvl+D8SfIsq73b8a9XmhdNX7qTc6MjecCD7W
HAP2rrK7epjTaVJp4+PYlw7qfix/NT1fNkq2Mb2E77h2eToUG1mjs/mvG/4WfVCf
MaBHOKaw6fyZULf366Jbx02r8K05P5ouvS1Z0De1mZJuUEUYhTRSs2POIdrmVrn9
R83Y4l7TKNPJelq2uyEc4r+/fRrerIlT4HVlLPTC3SdW8ytYSUZXx+1NfJfQimie
veIyIaTOV3SfC4EfeXtPtUpcVJvmFXqVbnXOO7bQU63bfFuuVSeU6OXWjoFRVkdH
NYTGUGb5xg4hgWqlLWvWg0WPgLLabMbetrP6c5/Qhml/l07nJHeLoVxlFuwsL8HG
eu0JWqnmwamp4/mmblRC9UfyrIQeDS8gsx8q/t2zdzT4bBph0nqYkZSyiIoQzlMr
YdrWxeJm3sReR0G3FluL+03TGJypGfhr
-----END CERTIFICATE-----

View File

@@ -54,6 +54,22 @@ MaxPingTime = 30
BattlenetPort = 1119
#
# LoginREST.Port
# Description: TCP port to reach the REST login method.
# Default: 8081
#
# LoginREST.ExternalAddress
# Description: IP address sent to clients connecting from outside the network where bnetserver runs
#
# LoginREST.LocalAddress
# Description: IP address sent to clients connecting from inside the network where bnetserver runs
#
LoginREST.Port = 8081
LoginREST.ExternalAddress=127.0.0.1
LoginREST.LocalAddress=127.0.0.1
#
#
# BindIP

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwN3EYmKhDGawGrh62wAgjh3wr4CcV6lp61Ev39jzTkgetXDB
F2SWC9s/pzS/h10HQwL9P0cYlqbZHj/darOphcqplK05WsJC876lUASSeVWVPiHs
mfpSzjx65qV2PfmcNE1SUEizOOfpaoxvLfVqh5y4MkuSxXxOXCXS9CnQBwQo8f/4
uV6czHZgigi7CSID75VK3VhqvlTaLYFoEiOpjWNAQ7x/18sv+VoSVuX+alYez2PD
wU+hl0CpzEIqtaavntce9sQ3uEd3eXYGAJp6X+bOVItRmUhb3WXoIXmHMaLe5oSc
cINa17ZL7H2ISOqr/1Pfq84Ck/VStbzEfJdTZwIDAQABAoIBAHcu1DQERQd30a3B
gNIi4vtPzzN1I6gcXgL3+cC3vasLcEapdflxxDNxeoVmWFFbEKi9iSf4VF6MnrFN
wBM3ETRHh8IDxeSrFVqw3lFzcdyfIYnyxtZkVZVy1HQBne8wd/HuMkbAllg9IAYi
4HWjKgDBvSX/g6Sca4QQL6uIxy/9s3Z4K2vU8KbvUpwo+ON4HMt61fgrIrbEUVCl
TMCVEf8UphwHctmQJb/Pr0+BCTdiv04ga1dkt+ZyR2o0VN6T/zKDqk4m1sSl0GZz
8sn63GbuTlwHcm9GgkaxoeeZJK1/sdOSIZN8W3PpnyHrAZJlNOY7G684F1mBaWV1
PGCcVtkCgYEA8jCDTGub7ZyMk48x+8L3Devja3TQz7YNIGkVEbQBpNw4gDV8j1m6
EgqFdzowkY+gbA76ylNfm6Aa66RDR/LbTbXlsNd8YkXcbU3xDQ96F6cS51VBkled
hq+iAuGJB9VYN5yP1P/Oswg/AFMjOnsfBL/1zFo26364z9x8zazw0wsCgYEAy907
mpkk59AQ4YIDSR9wK2YpXv6HoBPFld6m7PAnBWFO0uNtQ0YppbYbrhmDqrxUoFud
ZiEHIa0gLlp9lHr+UdUAMPDlJ6gbMnJW3U5qiVuuZA13tiZFlv11qUeU1tQUzTUv
ZoIISN15Im0PQzUFbTxSFbS+vTYjsedv1C9UOpUCgYEAkTaTUzvmV3cZNtSSFLFW
ros0Zda56QDwJ/G5x06V+cJtQjpPwCf9kBms4ssKGgzzFDd7GdsZpVc/LPDlwnsU
ESkyWnEpzEa1HvivwrP38bykcf5Ffbh45CvkyTNvlTnPVjDScNUcm24jUE+I/OSb
uZ5bg7bH3TWzHDbIwg2iq/cCgYB+DPqvqoVhOAtYBBWX/vJSQ0bNT7/4QIFpG1RH
KG5YK0SbrLeAYz+ZELKowWniBbSluj/mSAGq1usQ/i6rwijB3FvT5v8puA2o8X24
NKY27BM2FgWxAJUCuREpa/Mhqdx6zanTTg9lTlt558kKGxyR4Dw445sUTwdfFuTU
Y7dGyQKBgAG0vyOdfku9TlPX2a3LasM5jkbxljeTlCJUlahW7LSoQEmLoEhOM4Ja
6CA5PADhA16pOUweKjOtSkNEcVEorFNjlH34PpnsysF+NsDBP5HEy0eYyHSYwg1Y
7BGwQxUOoBaUKMu7jVQcffrKiWOGEXzBDSEZ3A30t7+JIS7qy1d1
-----END RSA PRIVATE KEY-----

View File

@@ -117,21 +117,20 @@ void LoginDatabaseConnection::DoPrepareStatements()
#define BnetAccountInfo "ba.id, UPPER(ba.email), ba.locked, ba.lock_country, ba.last_ip, ba.failed_logins, bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, bab.unbandate = bab.bandate"
#define BnetGameAccountInfo "a.id, a.username, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, ab.unbandate = ab.bandate, aa.gmlevel"
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_INFO, "SELECT " BnetAccountInfo ", ba.sha_pass_hash, ba.v, ba.s, " BnetGameAccountInfo
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_INFO, "SELECT " BnetAccountInfo ", " BnetGameAccountInfo
" FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account"
" LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_VS_FIELDS, "UPDATE battlenet_accounts SET v = ?, s = ? WHERE email = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_SESSION_KEY, "UPDATE battlenet_accounts SET sessionKey = ?, online = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_RECONNECT_INFO, "SELECT " BnetAccountInfo ", ba.sessionKey, " BnetGameAccountInfo
" FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account"
" LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ? AND a.username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_FAILED_LOGINS, "UPDATE battlenet_accounts SET failed_logins = failed_logins + 1 WHERE email = ?", CONNECTION_ASYNC);
" LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ? AND ba.sha_pass_hash = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS, "SELECT rc.numchars, r.id, r.Region, r.Battlegroup, r.gamebuild FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID, "SELECT rc.acctid, rc.numchars, r.id, r.Region, r.Battlegroup FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID, "SELECT rc.acctid, rc.numchars, r.id, r.Region, r.Battlegroup FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id LEFT JOIN account a ON rc.acctid = a.id WHERE a.battlenet_account = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS, "SELECT lpc.accountId, lpc.region, lpc.battlegroup, lpc.realmId, lpc.characterName, lpc.characterGUID, lpc.lastPlayedTime FROM account_last_played_character lpc LEFT JOIN account a ON lpc.accountId = a.id WHERE a.battlenet_account = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS, "DELETE FROM account_last_played_character WHERE accountId = ? AND region = ? AND battlegroup = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_BNET_LAST_PLAYER_CHARACTERS, "INSERT INTO account_last_played_character (accountId, region, battlegroup, realmId, characterName, characterGUID, lastPlayedTime) VALUES (?,?,?,?,?,?,?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_BNET_ACCOUNT, "INSERT INTO battlenet_accounts (`email`,`sha_pass_hash`) VALUES (?, ?)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_EMAIL_BY_ID, "SELECT email FROM battlenet_accounts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL, "SELECT id FROM battlenet_accounts WHERE email = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_PASSWORD, "UPDATE battlenet_accounts SET v = '', s = '', sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_PASSWORD, "UPDATE battlenet_accounts SET sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_CHECK_PASSWORD, "SELECT 1 FROM battlenet_accounts WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK, "UPDATE battlenet_accounts SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY, "UPDATE battlenet_accounts SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);

View File

@@ -111,12 +111,13 @@ enum LoginDatabaseStatements
LOGIN_SEL_ACCOUNT_MUTE_INFO,
LOGIN_SEL_BNET_ACCOUNT_INFO,
LOGIN_UPD_BNET_VS_FIELDS,
LOGIN_UPD_BNET_SESSION_KEY,
LOGIN_SEL_BNET_RECONNECT_INFO,
LOGIN_UPD_BNET_FAILED_LOGINS,
LOGIN_UPD_BNET_LAST_LOGIN_INFO,
LOGIN_SEL_BNET_CHARACTER_COUNTS,
LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO,
LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID,
LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID,
LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS,
LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS,
LOGIN_INS_BNET_LAST_PLAYER_CHARACTERS,
LOGIN_INS_BNET_ACCOUNT,
LOGIN_SEL_BNET_ACCOUNT_EMAIL_BY_ID,
LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL,

View File

@@ -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).

View File

@@ -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());
}

View File

@@ -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"

View File

@@ -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());
}

View File

@@ -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__

View File

@@ -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);

View File

@@ -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);

View File

@@ -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));

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -0,0 +1,695 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Login.proto
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "Login.pb.h"
#include <algorithm>
#include <utility>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
#include "Log.h"
// @@protoc_insertion_point(includes)
// Fix stupid windows.h included from Log.h->Common.h
#ifdef SendMessage
#undef SendMessage
#endif
namespace Battlenet {
namespace JSON {
namespace Login {
namespace {
const ::google::protobuf::Descriptor* FormInput_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FormInput_reflection_ = NULL;
const ::google::protobuf::Descriptor* FormInputs_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FormInputs_reflection_ = NULL;
const ::google::protobuf::Descriptor* FormInputValue_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FormInputValue_reflection_ = NULL;
const ::google::protobuf::Descriptor* LoginForm_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
LoginForm_reflection_ = NULL;
const ::google::protobuf::Descriptor* LoginResult_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
LoginResult_reflection_ = NULL;
const ::google::protobuf::EnumDescriptor* FormType_descriptor_ = NULL;
const ::google::protobuf::EnumDescriptor* AuthenticationState_descriptor_ = NULL;
} // namespace
void protobuf_AssignDesc_Login_2eproto() {
protobuf_AddDesc_Login_2eproto();
const ::google::protobuf::FileDescriptor* file =
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
"Login.proto");
GOOGLE_CHECK(file != NULL);
FormInput_descriptor_ = file->message_type(0);
static const int FormInput_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInput, input_id_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInput, type_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInput, label_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInput, max_length_),
};
FormInput_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
FormInput_descriptor_,
FormInput::default_instance_,
FormInput_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInput, _has_bits_[0]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInput, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(FormInput));
FormInputs_descriptor_ = file->message_type(1);
static const int FormInputs_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputs, type_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputs, inputs_),
};
FormInputs_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
FormInputs_descriptor_,
FormInputs::default_instance_,
FormInputs_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputs, _has_bits_[0]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputs, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(FormInputs));
FormInputValue_descriptor_ = file->message_type(2);
static const int FormInputValue_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputValue, input_id_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputValue, value_),
};
FormInputValue_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
FormInputValue_descriptor_,
FormInputValue::default_instance_,
FormInputValue_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputValue, _has_bits_[0]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FormInputValue, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(FormInputValue));
LoginForm_descriptor_ = file->message_type(3);
static const int LoginForm_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginForm, platform_id_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginForm, program_id_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginForm, version_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginForm, inputs_),
};
LoginForm_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
LoginForm_descriptor_,
LoginForm::default_instance_,
LoginForm_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginForm, _has_bits_[0]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginForm, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(LoginForm));
LoginResult_descriptor_ = file->message_type(4);
static const int LoginResult_offsets_[5] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, authentication_state_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, error_code_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, error_message_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, url_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, login_ticket_),
};
LoginResult_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
LoginResult_descriptor_,
LoginResult::default_instance_,
LoginResult_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, _has_bits_[0]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(LoginResult, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(LoginResult));
FormType_descriptor_ = file->enum_type(0);
AuthenticationState_descriptor_ = file->enum_type(1);
}
namespace {
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
inline void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
&protobuf_AssignDesc_Login_2eproto);
}
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
FormInput_descriptor_, &FormInput::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
FormInputs_descriptor_, &FormInputs::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
FormInputValue_descriptor_, &FormInputValue::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
LoginForm_descriptor_, &LoginForm::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
LoginResult_descriptor_, &LoginResult::default_instance());
}
} // namespace
void protobuf_ShutdownFile_Login_2eproto() {
delete FormInput::default_instance_;
delete FormInput_reflection_;
delete FormInputs::default_instance_;
delete FormInputs_reflection_;
delete FormInputValue::default_instance_;
delete FormInputValue_reflection_;
delete LoginForm::default_instance_;
delete LoginForm_reflection_;
delete LoginResult::default_instance_;
delete LoginResult_reflection_;
}
void protobuf_AddDesc_Login_2eproto() {
static bool already_here = false;
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION;
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\013Login.proto\022\024Battlenet.JSON.Login\"N\n\tF"
"ormInput\022\020\n\010input_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\t"
"\022\r\n\005label\030\003 \002(\t\022\022\n\nmax_length\030\004 \001(\r\"k\n\nF"
"ormInputs\022,\n\004type\030\001 \002(\0162\036.Battlenet.JSON"
".Login.FormType\022/\n\006inputs\030\002 \003(\0132\037.Battle"
"net.JSON.Login.FormInput\"1\n\016FormInputVal"
"ue\022\020\n\010input_id\030\001 \002(\t\022\r\n\005value\030\002 \002(\t\"{\n\tL"
"oginForm\022\023\n\013platform_id\030\001 \002(\t\022\022\n\nprogram"
"_id\030\002 \002(\t\022\017\n\007version\030\003 \002(\t\0224\n\006inputs\030\004 \003"
"(\0132$.Battlenet.JSON.Login.FormInputValue"
"\"\244\001\n\013LoginResult\022G\n\024authentication_state"
"\030\001 \002(\0162).Battlenet.JSON.Login.Authentica"
"tionState\022\022\n\nerror_code\030\002 \001(\t\022\025\n\rerror_m"
"essage\030\003 \001(\t\022\013\n\003url\030\004 \001(\t\022\024\n\014login_ticke"
"t\030\005 \001(\t*\032\n\010FormType\022\016\n\nLOGIN_FORM\020\001*H\n\023A"
"uthenticationState\022\t\n\005LOGIN\020\001\022\t\n\005LEGAL\020\002"
"\022\021\n\rAUTHENTICATOR\020\003\022\010\n\004DONE\020\004B\002H\002", 673);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"Login.proto", &protobuf_RegisterTypes);
FormInput::default_instance_ = new FormInput();
FormInputs::default_instance_ = new FormInputs();
FormInputValue::default_instance_ = new FormInputValue();
LoginForm::default_instance_ = new LoginForm();
LoginResult::default_instance_ = new LoginResult();
FormInput::default_instance_->InitAsDefaultInstance();
FormInputs::default_instance_->InitAsDefaultInstance();
FormInputValue::default_instance_->InitAsDefaultInstance();
LoginForm::default_instance_->InitAsDefaultInstance();
LoginResult::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_Login_2eproto);
}
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_Login_2eproto {
StaticDescriptorInitializer_Login_2eproto() {
protobuf_AddDesc_Login_2eproto();
}
} static_descriptor_initializer_Login_2eproto_;
const ::google::protobuf::EnumDescriptor* FormType_descriptor() {
protobuf_AssignDescriptorsOnce();
return FormType_descriptor_;
}
bool FormType_IsValid(int value) {
switch(value) {
case 1:
return true;
default:
return false;
}
}
const ::google::protobuf::EnumDescriptor* AuthenticationState_descriptor() {
protobuf_AssignDescriptorsOnce();
return AuthenticationState_descriptor_;
}
bool AuthenticationState_IsValid(int value) {
switch(value) {
case 1:
case 2:
case 3:
case 4:
return true;
default:
return false;
}
}
// ===================================================================
#ifndef _MSC_VER
const int FormInput::kInputIdFieldNumber;
const int FormInput::kTypeFieldNumber;
const int FormInput::kLabelFieldNumber;
const int FormInput::kMaxLengthFieldNumber;
#endif // !_MSC_VER
FormInput::FormInput()
: ::google::protobuf::Message() {
SharedCtor();
// @@protoc_insertion_point(constructor:Battlenet.JSON.Login.FormInput)
}
void FormInput::InitAsDefaultInstance() {
}
FormInput::FormInput(const FormInput& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:Battlenet.JSON.Login.FormInput)
}
void FormInput::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
input_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
label_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
max_length_ = 0u;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
FormInput::~FormInput() {
// @@protoc_insertion_point(destructor:Battlenet.JSON.Login.FormInput)
SharedDtor();
}
void FormInput::SharedDtor() {
if (input_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete input_id_;
}
if (type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete type_;
}
if (label_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete label_;
}
if (this != default_instance_) {
}
}
void FormInput::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* FormInput::descriptor() {
protobuf_AssignDescriptorsOnce();
return FormInput_descriptor_;
}
const FormInput& FormInput::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_Login_2eproto();
return *default_instance_;
}
FormInput* FormInput::default_instance_ = NULL;
FormInput* FormInput::New() const {
return new FormInput;
}
void FormInput::Swap(FormInput* other) {
if (other != this) {
GetReflection()->Swap(this, other);}
}
::google::protobuf::Metadata FormInput::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = FormInput_descriptor_;
metadata.reflection = FormInput_reflection_;
return metadata;
}
// ===================================================================
#ifndef _MSC_VER
const int FormInputs::kTypeFieldNumber;
const int FormInputs::kInputsFieldNumber;
#endif // !_MSC_VER
FormInputs::FormInputs()
: ::google::protobuf::Message() {
SharedCtor();
// @@protoc_insertion_point(constructor:Battlenet.JSON.Login.FormInputs)
}
void FormInputs::InitAsDefaultInstance() {
}
FormInputs::FormInputs(const FormInputs& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:Battlenet.JSON.Login.FormInputs)
}
void FormInputs::SharedCtor() {
_cached_size_ = 0;
type_ = 1;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
FormInputs::~FormInputs() {
// @@protoc_insertion_point(destructor:Battlenet.JSON.Login.FormInputs)
SharedDtor();
}
void FormInputs::SharedDtor() {
if (this != default_instance_) {
}
}
void FormInputs::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* FormInputs::descriptor() {
protobuf_AssignDescriptorsOnce();
return FormInputs_descriptor_;
}
const FormInputs& FormInputs::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_Login_2eproto();
return *default_instance_;
}
FormInputs* FormInputs::default_instance_ = NULL;
FormInputs* FormInputs::New() const {
return new FormInputs;
}
void FormInputs::Swap(FormInputs* other) {
if (other != this) {
GetReflection()->Swap(this, other);}
}
::google::protobuf::Metadata FormInputs::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = FormInputs_descriptor_;
metadata.reflection = FormInputs_reflection_;
return metadata;
}
// ===================================================================
#ifndef _MSC_VER
const int FormInputValue::kInputIdFieldNumber;
const int FormInputValue::kValueFieldNumber;
#endif // !_MSC_VER
FormInputValue::FormInputValue()
: ::google::protobuf::Message() {
SharedCtor();
// @@protoc_insertion_point(constructor:Battlenet.JSON.Login.FormInputValue)
}
void FormInputValue::InitAsDefaultInstance() {
}
FormInputValue::FormInputValue(const FormInputValue& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:Battlenet.JSON.Login.FormInputValue)
}
void FormInputValue::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
input_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
FormInputValue::~FormInputValue() {
// @@protoc_insertion_point(destructor:Battlenet.JSON.Login.FormInputValue)
SharedDtor();
}
void FormInputValue::SharedDtor() {
if (input_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete input_id_;
}
if (value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete value_;
}
if (this != default_instance_) {
}
}
void FormInputValue::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* FormInputValue::descriptor() {
protobuf_AssignDescriptorsOnce();
return FormInputValue_descriptor_;
}
const FormInputValue& FormInputValue::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_Login_2eproto();
return *default_instance_;
}
FormInputValue* FormInputValue::default_instance_ = NULL;
FormInputValue* FormInputValue::New() const {
return new FormInputValue;
}
void FormInputValue::Swap(FormInputValue* other) {
if (other != this) {
GetReflection()->Swap(this, other);}
}
::google::protobuf::Metadata FormInputValue::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = FormInputValue_descriptor_;
metadata.reflection = FormInputValue_reflection_;
return metadata;
}
// ===================================================================
#ifndef _MSC_VER
const int LoginForm::kPlatformIdFieldNumber;
const int LoginForm::kProgramIdFieldNumber;
const int LoginForm::kVersionFieldNumber;
const int LoginForm::kInputsFieldNumber;
#endif // !_MSC_VER
LoginForm::LoginForm()
: ::google::protobuf::Message() {
SharedCtor();
// @@protoc_insertion_point(constructor:Battlenet.JSON.Login.LoginForm)
}
void LoginForm::InitAsDefaultInstance() {
}
LoginForm::LoginForm(const LoginForm& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:Battlenet.JSON.Login.LoginForm)
}
void LoginForm::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
platform_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
program_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
version_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
LoginForm::~LoginForm() {
// @@protoc_insertion_point(destructor:Battlenet.JSON.Login.LoginForm)
SharedDtor();
}
void LoginForm::SharedDtor() {
if (platform_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete platform_id_;
}
if (program_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete program_id_;
}
if (version_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete version_;
}
if (this != default_instance_) {
}
}
void LoginForm::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* LoginForm::descriptor() {
protobuf_AssignDescriptorsOnce();
return LoginForm_descriptor_;
}
const LoginForm& LoginForm::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_Login_2eproto();
return *default_instance_;
}
LoginForm* LoginForm::default_instance_ = NULL;
LoginForm* LoginForm::New() const {
return new LoginForm;
}
void LoginForm::Swap(LoginForm* other) {
if (other != this) {
GetReflection()->Swap(this, other);}
}
::google::protobuf::Metadata LoginForm::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = LoginForm_descriptor_;
metadata.reflection = LoginForm_reflection_;
return metadata;
}
// ===================================================================
#ifndef _MSC_VER
const int LoginResult::kAuthenticationStateFieldNumber;
const int LoginResult::kErrorCodeFieldNumber;
const int LoginResult::kErrorMessageFieldNumber;
const int LoginResult::kUrlFieldNumber;
const int LoginResult::kLoginTicketFieldNumber;
#endif // !_MSC_VER
LoginResult::LoginResult()
: ::google::protobuf::Message() {
SharedCtor();
// @@protoc_insertion_point(constructor:Battlenet.JSON.Login.LoginResult)
}
void LoginResult::InitAsDefaultInstance() {
}
LoginResult::LoginResult(const LoginResult& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:Battlenet.JSON.Login.LoginResult)
}
void LoginResult::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
authentication_state_ = 1;
error_code_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
error_message_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
url_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
login_ticket_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
LoginResult::~LoginResult() {
// @@protoc_insertion_point(destructor:Battlenet.JSON.Login.LoginResult)
SharedDtor();
}
void LoginResult::SharedDtor() {
if (error_code_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete error_code_;
}
if (error_message_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete error_message_;
}
if (url_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete url_;
}
if (login_ticket_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete login_ticket_;
}
if (this != default_instance_) {
}
}
void LoginResult::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* LoginResult::descriptor() {
protobuf_AssignDescriptorsOnce();
return LoginResult_descriptor_;
}
const LoginResult& LoginResult::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_Login_2eproto();
return *default_instance_;
}
LoginResult* LoginResult::default_instance_ = NULL;
LoginResult* LoginResult::New() const {
return new LoginResult;
}
void LoginResult::Swap(LoginResult* other) {
if (other != this) {
GetReflection()->Swap(this, other);}
}
::google::protobuf::Metadata LoginResult::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = LoginResult_descriptor_;
metadata.reflection = LoginResult_reflection_;
return metadata;
}
// @@protoc_insertion_point(namespace_scope)
} // namespace Login
} // namespace JSON
} // namespace Battlenet
// @@protoc_insertion_point(global_scope)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
syntax = "proto2";
package Battlenet.JSON.Login;
option optimize_for = CODE_SIZE;
enum FormType {
LOGIN_FORM = 1;
}
message FormInput {
required string input_id = 1;
required string type = 2;
required string label = 3;
optional uint32 max_length = 4;
}
message FormInputs {
required FormType type = 1;
repeated FormInput inputs = 2;
}
message FormInputValue {
required string input_id = 1;
required string value = 2;
}
message LoginForm {
required string platform_id = 1;
required string program_id = 2;
required string version = 3;
repeated FormInputValue inputs = 4;
}
enum AuthenticationState {
LOGIN = 1;
LEGAL = 2;
AUTHENTICATOR = 3;
DONE = 4;
}
message LoginResult {
required AuthenticationState authentication_state = 1;
optional string error_code = 2;
optional string error_message = 3;
optional string url = 4;
optional string login_ticket = 5;
}

View File

@@ -11,3 +11,5 @@
#include "report_service.pb.h"
#include "resource_service.pb.h"
#include "user_manager_service.pb.h"
#include "Login.pb.h"
#include "RealmList.pb.h"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
syntax = "proto2";
package JSON.RealmList;
option optimize_for = CODE_SIZE;
message RealmListTicketIdentity {
required fixed32 gameAccountID = 1;
required uint32 gameAccountRegion = 2;
}
message ClientVersion {
required uint32 versionMajor = 1;
required uint32 versionMinor = 2;
required uint32 versionRevision = 3;
required fixed32 versionBuild = 4;
}
message ClientInformation {
required fixed32 platform = 1;
required string buildVariant = 2;
required fixed32 type = 3;
required string timeZone = 4;
required uint32 currentTime = 5;
required fixed32 textLocale = 6;
required fixed32 audioLocale = 7;
required fixed32 versionDataBuild = 8;
required ClientVersion version = 9;
required bytes secret = 10;
}
message RealmListTicketClientInformation {
required ClientInformation info = 1;
}
message RealmCharacterCountEntry {
required fixed32 wowRealmAddress = 1;
required uint32 count = 2;
}
message RealmCharacterCountList {
repeated RealmCharacterCountEntry counts = 1;
}
message RealmEntry {
required fixed32 wowRealmAddress = 1;
required uint32 cfgTimezonesID = 2;
required uint32 populationState = 3;
required uint32 cfgCategoriesID = 4;
required ClientVersion version = 5;
required uint32 cfgRealmsID = 6;
required uint32 flags = 7;
required string name = 8;
required uint32 cfgConfigsID = 9;
required uint32 cfgLanguagesID = 10;
}
message RealmState {
optional RealmEntry update = 1;
required bool deleting = 2;
}
message RealmListUpdates {
repeated RealmState updates = 1;
}
message IPAddress {
required string ip = 1;
required uint32 port = 2;
}
message RealmIPAddressFamily {
required uint32 family = 1;
repeated IPAddress addresses = 2;
}
message RealmListServerIPAddresses {
repeated RealmIPAddressFamily families = 1;
}

View File

@@ -44,7 +44,9 @@ target_link_libraries(shared
PUBLIC
database
rapidjson
proto)
proto
zlib
gsoap)
set_target_properties(shared
PROPERTIES

View File

@@ -0,0 +1,456 @@
/*
* 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 "ProtobufJSON.h"
#include "StringFormat.h"
#include "Common.h"
#include "Log.h"
#include <rapidjson/writer.h>
#include <rapidjson/reader.h>
#include <rapidjson/stringbuffer.h>
#include <stack>
class Serializer
{
public:
Serializer() : _writer(_buffer) { }
void WriteInt32(int32 value) { _writer.Int(value); }
void WriteInt64(int64 value) { _writer.Int64(value); }
void WriteUInt32(uint32 value) { _writer.Uint(value); }
void WriteUInt64(uint64 value) { _writer.Uint64(value); }
void WriteDouble(double value) { _writer.Double(value); }
void WriteFloat(float value) { _writer.Double(value); }
void WriteBool(bool value) { _writer.Bool(value); }
void WriteEnum(google::protobuf::EnumValueDescriptor const* value) { _writer.String(value->name()); }
void WriteString(std::string const& value) { _writer.String(value); }
void WriteMessage(google::protobuf::Message const& value);
std::string GetString() const { return std::string(_buffer.GetString(), _buffer.GetSize()); }
private:
void WriteMessageField(google::protobuf::Message const& value, google::protobuf::FieldDescriptor const* field);
void WriteSimpleMessageField(google::protobuf::Message const& value, google::protobuf::FieldDescriptor const* field);
void WriteRepeatedMessageField(google::protobuf::Message const& value, google::protobuf::FieldDescriptor const* field);
rapidjson::StringBuffer _buffer;
rapidjson::Writer<rapidjson::StringBuffer> _writer;
};
void Serializer::WriteMessage(google::protobuf::Message const& value)
{
google::protobuf::Reflection const* reflection = value.GetReflection();
std::vector<google::protobuf::FieldDescriptor const*> fields;
reflection->ListFields(value, &fields);
_writer.StartObject();
for (std::size_t i = 0; i < fields.size(); ++i)
WriteMessageField(value, fields[i]);
_writer.EndObject();
}
void Serializer::WriteMessageField(google::protobuf::Message const& value, google::protobuf::FieldDescriptor const* field)
{
_writer.Key(field->name().c_str());
if (field->is_repeated())
{
_writer.StartArray();
WriteRepeatedMessageField(value, field);
_writer.EndArray();
}
else
WriteSimpleMessageField(value, field);
}
void Serializer::WriteSimpleMessageField(google::protobuf::Message const& value, google::protobuf::FieldDescriptor const* field)
{
google::protobuf::Reflection const* reflection = value.GetReflection();
switch (field->cpp_type())
{
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
WriteInt32(reflection->GetInt32(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
WriteInt64(reflection->GetInt64(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
WriteUInt32(reflection->GetUInt32(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
WriteUInt64(reflection->GetUInt64(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
WriteDouble(reflection->GetDouble(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
WriteFloat(reflection->GetFloat(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
WriteBool(reflection->GetBool(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
WriteEnum(reflection->GetEnum(value, field));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
std::string strValue = reflection->GetString(value, field);
if (field->type() == google::protobuf::FieldDescriptor::TYPE_STRING)
WriteString(strValue);
else
{
_writer.StartArray();
for (std::size_t i = 0; i < strValue.length(); ++i)
WriteUInt32(uint32(strValue[i]));
_writer.EndArray();
}
break;
}
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
WriteMessage(reflection->GetMessage(value, field));
break;
default:
break;
}
}
void Serializer::WriteRepeatedMessageField(google::protobuf::Message const& value, google::protobuf::FieldDescriptor const* field)
{
google::protobuf::Reflection const* reflection = value.GetReflection();
for (int32 i = 0; i < reflection->FieldSize(value, field); ++i)
{
switch (field->cpp_type())
{
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
WriteInt32(reflection->GetRepeatedInt32(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
WriteInt64(reflection->GetRepeatedInt64(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
WriteUInt32(reflection->GetRepeatedUInt32(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
WriteUInt64(reflection->GetRepeatedUInt64(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
WriteDouble(reflection->GetRepeatedDouble(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
WriteFloat(reflection->GetRepeatedFloat(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
WriteBool(reflection->GetRepeatedBool(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
WriteEnum(reflection->GetRepeatedEnum(value, field, i));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
std::string strValue = reflection->GetRepeatedString(value, field, i);
if (field->type() == google::protobuf::FieldDescriptor::TYPE_STRING)
WriteString(strValue);
else
{
_writer.StartArray();
for (std::size_t j = 0; j < strValue.length(); ++j)
WriteUInt32(uint32(strValue[j]));
_writer.EndArray();
}
break;
}
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
WriteMessage(reflection->GetRepeatedMessage(value, field, i));
break;
default:
break;
}
}
}
class Deserializer : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, Deserializer>
{
public:
bool ReadMessage(std::string json, google::protobuf::Message* message);
bool Key(const Ch* str, rapidjson::SizeType length, bool copy);
bool Null();
bool Bool(bool b);
bool Int(int32 i);
bool Uint(uint32 i);
bool Int64(int64 i);
bool Uint64(uint64 i);
bool Double(double d);
bool String(const Ch* str, rapidjson::SizeType length, bool copy);
bool StartObject();
bool EndObject(rapidjson::SizeType memberCount);
bool StartArray();
bool EndArray(rapidjson::SizeType memberCount);
std::vector<std::string> const& GetErrors() const { return _errors; }
private:
bool CheckType(google::protobuf::FieldDescriptor::CppType expectedType);
rapidjson::Reader _reader;
std::stack<google::protobuf::FieldDescriptor const*> _state;
std::stack<google::protobuf::Message*> _objectState;
std::vector<std::string> _errors;
};
bool Deserializer::ReadMessage(std::string json, google::protobuf::Message* message)
{
rapidjson::StringStream ss(json.c_str());
_objectState.push(message);
rapidjson::ParseResult result = _reader.Parse(ss, *this);
ASSERT(result.IsError() || (_objectState.empty() && _state.empty()));
return !result.IsError() && _errors.empty();
}
bool Deserializer::Key(const Ch* str, rapidjson::SizeType /*length*/, bool /*copy*/)
{
google::protobuf::FieldDescriptor const* field = _objectState.top()->GetDescriptor()->FindFieldByName(str);
if (!field)
{
_errors.push_back(Trinity::StringFormat("Message %s has no field %s.", _objectState.top()->GetTypeName().c_str(), str));
return false;
}
_state.push(field);
return true;
}
bool Deserializer::Null()
{
_state.pop();
return true;
}
#define SET_FIELD(message, field, Type, val) do { \
if (!field->is_repeated()) \
message->GetReflection()->Set ## Type(message, field, val); \
else \
message->GetReflection()->Add ## Type(message, field, val); \
_state.pop(); \
} while (0)
bool Deserializer::Bool(bool b)
{
if (!CheckType(google::protobuf::FieldDescriptor::CPPTYPE_BOOL))
return false;
SET_FIELD(_objectState.top(), _state.top(), Bool, b);
return true;
}
bool Deserializer::Int(int32 i)
{
if (!CheckType(google::protobuf::FieldDescriptor::CPPTYPE_INT32))
return false;
SET_FIELD(_objectState.top(), _state.top(), Int32, i);
return true;
}
bool Deserializer::Uint(uint32 i)
{
google::protobuf::FieldDescriptor const* field = _state.top();
google::protobuf::Message* message = _objectState.top();
switch (field->cpp_type())
{
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
SET_FIELD(message, field, UInt32, i);
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
if (field->type() != google::protobuf::FieldDescriptor::TYPE_BYTES)
{
_errors.emplace_back("Expected field type to be bytes but got string instead.");
return false;
}
std::string currentValue = message->GetReflection()->GetString(*message, field);
currentValue.append(1, (char)i);
message->GetReflection()->SetString(message, field, currentValue);
break;
}
default:
_errors.push_back(Trinity::StringFormat("Expected field type to be uint32 or string but got %s instead.", _state.top()->cpp_type_name()));
return false;
}
return true;
}
bool Deserializer::Int64(int64 i)
{
if (!CheckType(google::protobuf::FieldDescriptor::CPPTYPE_INT64))
return false;
SET_FIELD(_objectState.top(), _state.top(), Int64, i);
return true;
}
bool Deserializer::Uint64(uint64 i)
{
if (!CheckType(google::protobuf::FieldDescriptor::CPPTYPE_UINT64))
return false;
SET_FIELD(_objectState.top(), _state.top(), UInt64, i);
return true;
}
bool Deserializer::Double(double d)
{
google::protobuf::FieldDescriptor const* field = _state.top();
google::protobuf::Message* message = _objectState.top();
switch (field->cpp_type())
{
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
SET_FIELD(message, field, Float, d);
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
SET_FIELD(message, field, Double, d);
break;
default:
_errors.push_back(Trinity::StringFormat("Expected field type to be float or double but got %s instead.", _state.top()->cpp_type_name()));
return false;
}
return true;
}
bool Deserializer::String(const Ch* str, rapidjson::SizeType /*length*/, bool /*copy*/)
{
google::protobuf::FieldDescriptor const* field = _state.top();
google::protobuf::Message* message = _objectState.top();
switch (field->cpp_type())
{
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
{
google::protobuf::EnumValueDescriptor const* enumValue = field->enum_type()->FindValueByName(str);
if (!enumValue)
{
_errors.push_back(Trinity::StringFormat("Field %s enum %s does not have a value named %s.", field->full_name().c_str(), field->enum_type()->full_name().c_str(), str));
return false;
}
SET_FIELD(message, field, Enum, enumValue);
break;
}
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
SET_FIELD(message, field, String, str);
break;
default:
_errors.push_back(Trinity::StringFormat("Expected field type to be string or enum but got %s instead.", _state.top()->cpp_type_name()));
return false;
}
return true;
}
bool Deserializer::StartObject()
{
// not a root object
if (!_state.empty())
{
if (_state.top()->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
{
_errors.push_back(Trinity::StringFormat("Expected field %s to be a message but got %s instead.", _state.top()->cpp_type_name()));
return false;
}
google::protobuf::Message* containingMessage = _objectState.top();
if (!_state.top()->is_repeated())
_objectState.push(containingMessage->GetReflection()->MutableMessage(containingMessage, _state.top()));
else
_objectState.push(containingMessage->GetReflection()->AddMessage(containingMessage, _state.top()));
}
else if (_objectState.size() != 1)
return false;
return true;
}
bool Deserializer::EndObject(rapidjson::SizeType /*memberCount*/)
{
if (!_state.empty() && !_state.top()->is_repeated())
_state.pop();
_objectState.pop();
return true;
}
bool Deserializer::StartArray()
{
if (_state.empty())
{
_errors.emplace_back("Root cannot be an array.");
return false;
}
if (_state.top()->is_repeated() ^ (_state.top()->type() != google::protobuf::FieldDescriptor::TYPE_BYTES))
{
_errors.push_back(Trinity::StringFormat("Expected field %s type to be exactly an array OR bytes but it was both or none.", _state.top()->full_name().c_str()));
return false;
}
return true;
}
bool Deserializer::CheckType(google::protobuf::FieldDescriptor::CppType expectedType)
{
if (_state.top()->cpp_type() != expectedType)
{
_errors.push_back(Trinity::StringFormat("Expected field %s type to be %s but got %s instead.",
_state.top()->full_name().c_str(), google::protobuf::FieldDescriptor::CppTypeName(expectedType), _state.top()->cpp_type_name()));
return false;
}
return true;
}
bool Deserializer::EndArray(rapidjson::SizeType /*memberCount*/)
{
_state.pop();
return true;
}
#undef SET_FIELD
std::string JSON::Serialize(google::protobuf::Message const& message)
{
Serializer serializer;
serializer.WriteMessage(message);
return serializer.GetString();
}
bool JSON::Deserialize(std::string json, google::protobuf::Message* message)
{
Deserializer deserializer;
if (!deserializer.ReadMessage(std::forward<std::string>(json), message))
{
for (std::size_t i = 0; i < deserializer.GetErrors().size(); ++i)
TC_LOG_ERROR("json", "%s", deserializer.GetErrors()[i].c_str());
return false;
}
return true;
}

View File

@@ -15,22 +15,17 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BattlenetPacketCrypt_h__
#define BattlenetPacketCrypt_h__
#ifndef ProtobufJSON_h__
#define ProtobufJSON_h__
#include "PacketCrypt.h"
#include "Define.h"
#include <google/protobuf/message.h>
#include <string>
class BigNumber;
namespace Battlenet
namespace JSON
{
class PacketCrypt : public ::PacketCrypt
{
public:
PacketCrypt();
void Init(BigNumber* K) override;
};
TC_SHARED_API std::string Serialize(google::protobuf::Message const& message);
TC_SHARED_API bool Deserialize(std::string json, google::protobuf::Message* message);
}
#endif // BattlenetPacketCrypt_h__
#endif // ProtobufJSON_h__

View File

@@ -61,3 +61,13 @@ uint32 const Realm::ConfigIdByType[MAX_CLIENT_REALM_TYPE] =
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
};
std::string Battlenet::RealmHandle::GetAddressString() const
{
return Trinity::StringFormat("%u-%u-%u", Region, Site, Realm);
}
std::string Battlenet::RealmHandle::GetSubRegionAddress() const
{
return Trinity::StringFormat("%u-%u-0", Region, Site);
}

View File

@@ -46,6 +46,7 @@ namespace Battlenet
RealmHandle() : Region(0), Site(0), Realm(0) { }
RealmHandle(uint8 region, uint8 battlegroup, uint32 index)
: Region(region), Site(battlegroup), Realm(index) { }
RealmHandle(uint32 realmAddress) : Region((realmAddress >> 24) & 0xFF), Site((realmAddress >> 16) & 0xFF), Realm(realmAddress & 0xFFFF) { }
uint8 Region;
uint8 Site;
@@ -56,7 +57,9 @@ namespace Battlenet
return Realm < r.Realm;
}
uint32 GetAddress() const { return ((Site << 16) & 0xFF0000) | uint16(Realm); }
uint32 GetAddress() const { return (Region << 24) | (Site << 16) | uint16(Realm); }
std::string GetAddressString() const;
std::string GetSubRegionAddress() const;
};
}

View File

@@ -16,11 +16,16 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Util.h"
#include "RealmList.h"
#include <boost/asio/ip/tcp.hpp>
#include "BattlenetRpcErrorCodes.h"
#include "Database/DatabaseEnv.h"
#include "ProtobufJSON.h"
#include "SHA256.h"
#include "BigNumber.h"
#include "Util.h"
#include "game_utilities_service.pb.h"
#include "RealmList.pb.h"
#include <zlib.h>
RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr)
{
@@ -53,16 +58,6 @@ void RealmList::Close()
_updateTimer->cancel();
}
template<typename FieldType>
inline void UpdateField(FieldType& out, FieldType const& in, bool& changed)
{
if (out != in)
{
out = in;
changed = true;
}
}
void RealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr,
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel,
float population)
@@ -163,6 +158,8 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag,
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
_subRegions.insert(Battlenet::RealmHandle{ region, battlegroup, 0 }.GetAddressString());
if (!existingRealms.count(id))
TC_LOG_INFO("realmlist", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port);
else
@@ -197,3 +194,208 @@ Realm const* RealmList::GetRealm(Battlenet::RealmHandle const& id) const
return NULL;
}
RealmBuildInfo const* RealmList::GetBuildInfo(uint32 build) const
{
// List of client builds for verbose version info in realmlist packet
static std::vector<RealmBuildInfo> const ClientBuilds =
{
{ 21355, 6, 2, 4, ' ' },
{ 20726, 6, 2, 3, ' ' },
{ 20574, 6, 2, 2, 'a' },
{ 20490, 6, 2, 2, 'a' },
{ 15595, 4, 3, 4, ' ' },
{ 14545, 4, 2, 2, ' ' },
{ 13623, 4, 0, 6, 'a' },
{ 13930, 3, 3, 5, 'a' }, // 3.3.5a China Mainland build
{ 12340, 3, 3, 5, 'a' },
{ 11723, 3, 3, 3, 'a' },
{ 11403, 3, 3, 2, ' ' },
{ 11159, 3, 3, 0, 'a' },
{ 10505, 3, 2, 2, 'a' },
{ 9947, 3, 1, 3, ' ' },
{ 8606, 2, 4, 3, ' ' },
{ 6141, 1, 12, 3, ' ' },
{ 6005, 1, 12, 2, ' ' },
{ 5875, 1, 12, 1, ' ' },
};
for (std::size_t i = 0; i < ClientBuilds.size(); ++i)
if (ClientBuilds[i].Build == build)
return &ClientBuilds[i];
return nullptr;
}
void RealmList::WriteSubRegions(bgs::protocol::game_utilities::v1::GetAllValuesForAttributeResponse* response) const
{
for (std::string const& subRegion : GetSubRegions())
response->add_attribute_value()->set_string_value(subRegion);
}
std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const
{
std::vector<uint8> compressed;
if (Realm const* realm = GetRealm(id))
{
if (!(realm->Flags & REALM_FLAG_OFFLINE) && realm->Build == build)
{
JSON::RealmList::RealmEntry realmEntry;
realmEntry.set_wowrealmaddress(realm->Id.GetAddress());
realmEntry.set_cfgtimezonesid(1);
realmEntry.set_populationstate(std::max(uint32(realm->PopulationLevel), 1u));
realmEntry.set_cfgcategoriesid(realm->Timezone);
JSON::RealmList::ClientVersion* version = realmEntry.mutable_version();
if (RealmBuildInfo const* buildInfo = GetBuildInfo(realm->Build))
{
version->set_versionmajor(buildInfo->MajorVersion);
version->set_versionminor(buildInfo->MinorVersion);
version->set_versionrevision(buildInfo->BugfixVersion);
version->set_versionbuild(buildInfo->Build);
}
else
{
version->set_versionmajor(6);
version->set_versionminor(2);
version->set_versionrevision(4);
version->set_versionbuild(realm->Build);
}
realmEntry.set_cfgrealmsid(realm->Id.Realm);
realmEntry.set_flags(realm->Flags);
realmEntry.set_name(realm->Name);
realmEntry.set_cfgconfigsid(realm->GetConfigId());
realmEntry.set_cfglanguagesid(1);
std::string json = "JamJSONRealmEntry:" + JSON::Serialize(realmEntry);
uLong compressedLength = compressBound(json.length());
compressed.resize(compressedLength + 4);
*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)
compressed.resize(compressedLength + 4);
else
compressed.clear();
}
}
return compressed;
}
std::vector<uint8> RealmList::GetRealmList(uint32 build, std::string const& subRegion) const
{
JSON::RealmList::RealmListUpdates realmList;
for (auto const& realm : _realms)
{
if (realm.second.Id.GetSubRegionAddress() != subRegion)
continue;
uint32 flag = realm.second.Flags;
if (realm.second.Build != build)
flag |= REALM_FLAG_VERSION_MISMATCH;
JSON::RealmList::RealmState* state = realmList.add_updates();
state->mutable_update()->set_wowrealmaddress(realm.second.Id.GetAddress());
state->mutable_update()->set_cfgtimezonesid(1);
state->mutable_update()->set_populationstate((realm.second.Flags & REALM_FLAG_OFFLINE) ? 0u : std::max(uint32(realm.second.PopulationLevel), 1u));
state->mutable_update()->set_cfgcategoriesid(realm.second.Timezone);
JSON::RealmList::ClientVersion* version = state->mutable_update()->mutable_version();
if (RealmBuildInfo const* buildInfo = GetBuildInfo(realm.second.Build))
{
version->set_versionmajor(buildInfo->MajorVersion);
version->set_versionminor(buildInfo->MinorVersion);
version->set_versionrevision(buildInfo->BugfixVersion);
version->set_versionbuild(buildInfo->Build);
}
else
{
version->set_versionmajor(6);
version->set_versionminor(2);
version->set_versionrevision(4);
version->set_versionbuild(realm.second.Build);
}
state->mutable_update()->set_cfgrealmsid(realm.second.Id.Realm);
state->mutable_update()->set_flags(flag);
state->mutable_update()->set_name(realm.second.Name);
state->mutable_update()->set_cfgconfigsid(realm.second.GetConfigId());
state->mutable_update()->set_cfglanguagesid(1);
state->set_deleting(false);
}
std::string json = "JSONRealmListUpdates:" + JSON::Serialize(realmList);
uLong compressedLength = compressBound(json.length());
std::vector<uint8> compressed;
compressed.resize(4 + compressedLength);
*reinterpret_cast<uint32*>(compressed.data()) = json.length() + 1;
compress(compressed.data() + 4, &compressedLength, reinterpret_cast<uint8 const*>(json.c_str()), json.length() + 1);
compressed.resize(compressedLength + 4);
return compressed;
}
uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::address const& clientAddress, std::array<uint8, 32> const& clientSecret,
LocaleConstant locale, std::string const& os, std::string accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const
{
if (Realm const* realm = GetRealm(Battlenet::RealmHandle(realmAddress)))
{
if (realm->Flags & REALM_FLAG_OFFLINE || realm->Build != build)
return ERROR_USER_SERVER_NOT_PERMITTED_ON_REALM;
JSON::RealmList::RealmListServerIPAddresses serverAddresses;
JSON::RealmList::RealmIPAddressFamily* addressFamily = serverAddresses.add_families();
addressFamily->set_family(1);
JSON::RealmList::IPAddress* address = addressFamily->add_addresses();
address->set_ip(realm->GetAddressForClient(clientAddress).address().to_string());
address->set_port(realm->Port);
std::string json = "JSONRealmListServerIPAddresses:" + JSON::Serialize(serverAddresses);
uLong compressedLength = compressBound(json.length());
std::vector<uint8> compressed;
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;
BigNumber serverSecret;
serverSecret.SetRand(8 * 32);
SHA256Hash wowSessionKey;
wowSessionKey.UpdateData(clientSecret.data(), clientSecret.size());
wowSessionKey.UpdateData(serverSecret.AsByteArray(32).get(), 32);
wowSessionKey.Finalize();
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO);
stmt->setString(0, ByteArrayToHexStr(wowSessionKey.GetDigest(), wowSessionKey.GetLength(), true));
stmt->setString(1, clientAddress.to_string());
stmt->setUInt8(2, locale);
stmt->setString(3, os);
stmt->setString(4, accountName);
LoginDatabase.DirectExecute(stmt);
bgs::protocol::Attribute* attribute = response->add_attribute();
attribute->set_name("Param_RealmJoinTicket");
attribute->mutable_value()->set_blob_value(accountName);
attribute = response->add_attribute();
attribute->set_name("Param_ServerAddresses");
attribute->mutable_value()->set_blob_value(compressed.data(), compressedLength + 4);
attribute = response->add_attribute();
attribute->set_name("Param_JoinSecret");
attribute->mutable_value()->set_blob_value(serverSecret.AsByteArray(32).get(), 32);
return ERROR_OK;
}
return ERROR_UTIL_SERVER_UNKNOWN_REALM;
}

View File

@@ -28,6 +28,38 @@
using namespace boost::asio;
struct RealmBuildInfo
{
uint32 Build;
uint32 MajorVersion;
uint32 MinorVersion;
uint32 BugfixVersion;
uint32 HotfixVersion;
};
namespace bgs
{
namespace protocol
{
namespace game_utilities
{
namespace v1
{
class ClientResponse;
class GetAllValuesForAttributeResponse;
}
}
}
}
namespace JSON
{
namespace RealmList
{
class RealmListUpdates;
}
}
/// Storage object for the list of realms on the server
class TC_SHARED_API RealmList
{
@@ -44,6 +76,14 @@ public:
RealmMap const& GetRealms() const { return _realms; }
Realm const* GetRealm(Battlenet::RealmHandle const& id) const;
RealmBuildInfo const* GetBuildInfo(uint32 build) const;
std::unordered_set<std::string> const& GetSubRegions() const { return _subRegions; }
void WriteSubRegions(bgs::protocol::game_utilities::v1::GetAllValuesForAttributeResponse* response) const;
std::vector<uint8> GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const;
std::vector<uint8> GetRealmList(uint32 build, std::string const& subRegion) const;
uint32 JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::address const& clientAddress, std::array<uint8, 32> const& clientSecret,
LocaleConstant locale, std::string const& os, std::string accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const;
private:
RealmList();
@@ -52,6 +92,7 @@ private:
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
RealmMap _realms;
std::unordered_set<std::string> _subRegions;
uint32 _updateInterval;
boost::asio::deadline_timer* _updateTimer;
boost::asio::ip::tcp::resolver* _resolver;

View File

@@ -48,7 +48,6 @@ set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAG
target_link_libraries(worldserver
PUBLIC
scripts
gsoap
readline)
CollectIncludeDirectories(

View File

@@ -41,7 +41,7 @@
#include "GitRevision.h"
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include "Realm/Realm.h"
#include "RealmList.h"
#include "DatabaseLoader.h"
#include "AppenderDB.h"
#include <openssl/opensslv.h>
@@ -49,6 +49,7 @@
#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/program_options.hpp>
#include <google/protobuf/stubs/common.h>
using namespace boost::program_options;
@@ -103,6 +104,8 @@ extern int main(int argc, char** argv)
if (vm.count("help") || vm.count("version"))
return 0;
GOOGLE_PROTOBUF_VERIFY_VERSION;
#ifdef _WIN32
if (configService.compare("install") == 0)
return WinServiceInstall() ? 0 : 1;
@@ -188,6 +191,8 @@ extern int main(int argc, char** argv)
// Set server offline (not connectable)
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm);
sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10));
LoadRealmInfo();
// Initialize the World
@@ -273,6 +278,7 @@ extern int main(int argc, char** argv)
// set server offline
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm);
sRealmList->Close();
// Clean up threads if any
if (soapThread != nullptr)
@@ -294,6 +300,8 @@ extern int main(int argc, char** argv)
OpenSSLCrypto::threadsCleanup();
google::protobuf::ShutdownProtobufLibrary();
// 0 - normal shutdown
// 1 - shutdown at error
// 2 - restart command used, this code can be used by restarter for restart Trinityd

View File

@@ -239,6 +239,14 @@ UseProcessors = 0
ProcessPriority = 0
#
# RealmsStateUpdateDelay
# Description: Time (in seconds) between realm list updates.
# Default: 10
# 0 - (Disabled)
RealmsStateUpdateDelay = 10
#
# Compression
# Description: Compression level for client update packages.