aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2014-06-08 14:54:37 +0200
committerShauren <shauren.trinity@gmail.com>2014-06-08 14:54:37 +0200
commit05c0524bf3d97ba29496fa13e93acd3b8d7d37a4 (patch)
treec7781f1cedac93cd2f7dba51bd716dcd759699fa
parent372f043a68788f1903232392546c0d386b9fc248 (diff)
Core/Battle.net: Refactored handling multiple game accounts
-rw-r--r--sql/base/auth_database.sql2
-rw-r--r--sql/updates/auth/2014_06_08_00_auth_account_434.sql3
-rw-r--r--src/server/authserver/Server/BattlenetPackets.cpp6
-rw-r--r--src/server/authserver/Server/BattlenetPackets.h4
-rw-r--r--src/server/authserver/Server/BattlenetSocket.cpp30
-rw-r--r--src/server/authserver/Server/BattlenetSocket.h1
-rw-r--r--src/server/game/Server/WorldSocket.cpp17
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp8
8 files changed, 52 insertions, 19 deletions
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index 7ab0c855f45..6dca9aa1e14 100644
--- a/sql/base/auth_database.sql
+++ b/sql/base/auth_database.sql
@@ -47,8 +47,10 @@ CREATE TABLE `account` (
`os` varchar(3) NOT NULL DEFAULT '',
`recruiter` int(10) unsigned NOT NULL DEFAULT '0',
`battlenet_account` int(10) unsigned DEFAULT NULL,
+ `battlenet_index` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`),
+ UNIQUE KEY `uk_bnet_acc` (`battlenet_account`, `battlenet_index`),
CONSTRAINT `fk_bnet_acc` FOREIGN KEY (`battlenet_account`) REFERENCES `battlenet_accounts` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account System';
/*!40101 SET character_set_client = @saved_cs_client */;
diff --git a/sql/updates/auth/2014_06_08_00_auth_account_434.sql b/sql/updates/auth/2014_06_08_00_auth_account_434.sql
new file mode 100644
index 00000000000..bc57136dc07
--- /dev/null
+++ b/sql/updates/auth/2014_06_08_00_auth_account_434.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `account`
+ ADD `battlenet_index` tinyint(3) unsigned DEFAULT NULL AFTER `battlenet_account`,
+ ADD UNIQUE KEY `uk_bnet_acc` (`battlenet_account`, `battlenet_index`);
diff --git a/src/server/authserver/Server/BattlenetPackets.cpp b/src/server/authserver/Server/BattlenetPackets.cpp
index 9997ea8d259..6a8e09090ef 100644
--- a/src/server/authserver/Server/BattlenetPackets.cpp
+++ b/src/server/authserver/Server/BattlenetPackets.cpp
@@ -202,7 +202,7 @@ void Battlenet::AuthComplete::Write()
_stream.WriteString(FirstName, 8); // First name
_stream.WriteString(LastName, 8); // Last name - not set for WoW
- _stream.Write(GameAccountId, 32);
+ _stream.Write(AccountId, 32);
_stream.Write(Region, 8);
_stream.Write(0, 64);
@@ -236,7 +236,7 @@ std::string Battlenet::AuthComplete::ToString() const
{
std::ostringstream stream;
stream << "Battlenet::AuthComplete AuthResult " << Result << " PingTimeout " << PingTimeout << " Threshold " << Threshold << " Rate " << Rate
- << " FirstName " << FirstName << " LastName " << LastName << " GameAccountId " << GameAccountId << " GameAccountName " << GameAccountName
+ << " FirstName " << FirstName << " LastName " << LastName << " AccountId " << AccountId << " Region " << uint32(Region) << " GameAccountName " << GameAccountName
<< " GameAccountFlags " << GameAccountFlags << " Modules " << Modules.size();
for (ModuleInfo const* module : Modules)
@@ -441,7 +441,7 @@ void Battlenet::RealmJoinResult::Write()
std::string Battlenet::RealmJoinResult::ToString() const
{
std::ostringstream stream;
- stream << "Battlenet::RealmJoinResult ServerSeed " << ServerSeed << " Addresses (IPv4)" << IPv4.size();
+ stream << "Battlenet::RealmJoinResult ServerSeed " << ServerSeed << " IPv4 Addresses " << IPv4.size();
for (ACE_INET_Addr const& addr : IPv4)
stream << std::endl << "Battlenet::RealmJoinResult::Address " << GetAddressString(addr);
diff --git a/src/server/authserver/Server/BattlenetPackets.h b/src/server/authserver/Server/BattlenetPackets.h
index 3fa628c2ba3..54fb50184a0 100644
--- a/src/server/authserver/Server/BattlenetPackets.h
+++ b/src/server/authserver/Server/BattlenetPackets.h
@@ -208,7 +208,7 @@ namespace Battlenet
public:
AuthComplete() : ServerPacket(PacketHeader(SMSG_AUTH_COMPLETE, AUTHENTICATION)),
Result(AUTH_OK), ErrorType(0), PingTimeout(120000), Threshold(25000000), Rate(1000),
- FirstName(""), LastName(""), Region(2), GameAccountId(0), GameAccountRegion(2), GameAccountName("")
+ FirstName(""), LastName(""), AccountId(0), Region(2), GameAccountRegion(2), GameAccountName("")
{
}
@@ -227,8 +227,8 @@ namespace Battlenet
uint32 Rate;
std::string FirstName;
std::string LastName;
+ uint32 AccountId;
uint8 Region;
- uint32 GameAccountId;
uint8 GameAccountRegion;
std::string GameAccountName;
uint64 GameAccountFlags;
diff --git a/src/server/authserver/Server/BattlenetSocket.cpp b/src/server/authserver/Server/BattlenetSocket.cpp
index 56744784167..eb8dc1158f0 100644
--- a/src/server/authserver/Server/BattlenetSocket.cpp
+++ b/src/server/authserver/Server/BattlenetSocket.cpp
@@ -59,7 +59,7 @@ Battlenet::Socket::ModuleHandler const Battlenet::Socket::ModuleHandlers[MODULE_
};
Battlenet::Socket::Socket(RealmSocket& socket) : _socket(socket), _accountId(0), _accountName(), _locale(),
- _os(), _build(0), _gameAccountId(0), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(),
+ _os(), _build(0), _gameAccountId(0), _gameAccountIndex(0), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(),
_reconnectProof(), _crypt(), _authed(false)
{
static uint8 const N_Bytes[] =
@@ -323,10 +323,12 @@ bool Battlenet::Socket::HandleAuthReconnect(PacketHeader& header, BitStream& pac
if (baseComponent != reconnect.Components.end())
_build = baseComponent->Build;
+ uint8 accountIndex = atol(reconnect.GameAccountName.substr(reconnect.GameAccountName.find_last_of('#') + 1).c_str());
+
Utf8ToUpperOnlyLatin(_accountName);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO);
stmt->setString(0, _accountName);
- stmt->setString(1, reconnect.GameAccountName.c_str());
+ stmt->setUInt8(1, accountIndex);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
{
@@ -341,6 +343,7 @@ bool Battlenet::Socket::HandleAuthReconnect(PacketHeader& header, BitStream& pac
_accountId = fields[0].GetUInt32();
K.SetHexStr(fields[1].GetString().c_str());
_gameAccountId = fields[2].GetUInt32();
+ _gameAccountIndex = accountIndex;
ModuleInfo* thumbprint = sBattlenetMgr->CreateModule(_os, "Thumbprint");
ModuleInfo* resume = sBattlenetMgr->CreateModule(_os, "Resume");
@@ -768,8 +771,10 @@ bool Battlenet::Socket::HandlePasswordModule(BitStream* dataStream, ServerPacket
do
{
fields = result->Fetch();
+ std::ostringstream name;
+ name << "WoW" << uint32(fields[0].GetUInt8());
accounts.Write(2, 8);
- accounts.WriteString(fields[0].GetString(), 8);
+ accounts.WriteString(name.str(), 8);
} while (result->NextRow());
ModuleInfo* selectGameAccount = sBattlenetMgr->CreateModule(_os, "SelectGameAccount");
@@ -801,7 +806,8 @@ bool Battlenet::Socket::HandlePasswordModule(BitStream* dataStream, ServerPacket
return false;
}
- _gameAccountId = (*result)[1].GetUInt32();
+ _gameAccountId = fields[1].GetUInt32();
+ _gameAccountIndex = fields[0].GetUInt8();
request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint"));
_modulesWaitingForData.push(MODULE_RISK_FINGERPRINT);
@@ -823,9 +829,18 @@ bool Battlenet::Socket::HandleSelectGameAccountModule(BitStream* dataStream, Ser
dataStream->Read<uint8>(8);
std::string account = dataStream->ReadString(8);
+ if (account.length() < 4)
+ {
+ AuthComplete* complete = new AuthComplete();
+ complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT);
+ ReplaceResponse(response, complete);
+ return false;
+ }
+
+ uint8 accountIndex = atol(account.substr(3).c_str());
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNT);
- stmt->setString(0, account);
+ stmt->setUInt8(0, accountIndex);
stmt->setUInt32(1, _accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
@@ -856,6 +871,7 @@ bool Battlenet::Socket::HandleSelectGameAccountModule(BitStream* dataStream, Ser
}
_gameAccountId = fields[0].GetUInt32();
+ _gameAccountIndex = accountIndex;
ProofRequest* request = new ProofRequest();
request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint"));
@@ -871,9 +887,9 @@ bool Battlenet::Socket::HandleRiskFingerprintModule(BitStream* dataStream, Serve
if (dataStream->Read<uint8>(8) == 1)
{
std::ostringstream str;
- str << _gameAccountId << "#1";
+ str << _accountId << "#" << uint32(_gameAccountIndex);
- complete->GameAccountId = _gameAccountId;
+ complete->AccountId = _accountId;
complete->GameAccountName = str.str();
complete->GameAccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK;
diff --git a/src/server/authserver/Server/BattlenetSocket.h b/src/server/authserver/Server/BattlenetSocket.h
index c634a81b517..ee399e26b09 100644
--- a/src/server/authserver/Server/BattlenetSocket.h
+++ b/src/server/authserver/Server/BattlenetSocket.h
@@ -92,6 +92,7 @@ namespace Battlenet
std::string _os;
uint32 _build;
uint32 _gameAccountId;
+ uint8 _gameAccountIndex;
AccountTypes _accountSecurityLevel;
BigNumber N;
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index cc839b5281c..1a93e7ae1d5 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -856,9 +856,20 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Get the account information from the realmd database
// 0 1 2 3 4 5 6 7 8
// SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(account.find('#') == std::string::npos ? LOGIN_SEL_ACCOUNT_INFO_BY_NAME : LOGIN_SEL_ACCOUNT_INFO_BY_BNET);
-
- stmt->setString(0, account);
+ size_t hashPos = account.find_last_of('#');
+ PreparedStatement* stmt;
+ if (hashPos != std::string::npos)
+ {
+ Tokenizer tokens(account, '#', 2);
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_BNET);
+ stmt->setUInt32(0, atol(tokens[0]));
+ stmt->setUInt8(1, atol(tokens[1]));
+ }
+ else
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
+ stmt->setString(0, account);
+ }
PreparedQueryResult result = LoginDatabase.Query(stmt);
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index abe733e55e2..1da8088ed36 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -44,7 +44,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_BNET, "SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE id = SUBSTRING_INDEX(?, '#', 1)", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_BNET, "SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE battlenet_account = ? AND battlenet_index = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_EMAIL, "SELECT id, username FROM account WHERE email = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_NUM_CHARS_ON_REALM, "SELECT numchars FROM realmcharacters WHERE realmid = ? AND acctid= ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_IP, "SELECT id, username FROM account WHERE last_ip = ?", CONNECTION_SYNCH);
@@ -108,9 +108,9 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN, "SELECT bandate, unbandate FROM battlenet_account_bans WHERE id = ? AND active = 1", CONNECTION_SYNCH);
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 = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_BNET_RECONNECT_INFO, "SELECT ba.id, ba.sessionKey, a.id FROM battlenet_accounts ba LEFT JOIN account a ON ba.id = a.battlenet_account WHERE ba.email = ? AND a.id = SUBSTRING_INDEX(?, '#', 1)", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNTS, "SELECT a.username, a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_account = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNT, "SELECT a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE username = ? AND battlenet_account = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_BNET_RECONNECT_INFO, "SELECT ba.id, ba.sessionKey, a.id FROM battlenet_accounts ba LEFT JOIN account a ON ba.id = a.battlenet_account WHERE ba.email = ? AND a.battlenet_index = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNTS, "SELECT a.battlenet_index, a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_account = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNT, "SELECT a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_index = ? AND battlenet_account = ?", 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_SYNCH);
PrepareStatement(LOGIN_INS_BNET_ACCOUNT, "INSERT INTO battlenet_accounts (`email`,`sha_pass_hash`) VALUES (?, ?)", CONNECTION_ASYNC);