Add cUUID class (#3871)
This commit is contained in:
committed by
Alexander Harkness
parent
86d52c3e17
commit
f4f2fc7c3d
@@ -6,6 +6,7 @@
|
||||
#include "../Root.h"
|
||||
#include "../Server.h"
|
||||
#include "../ClientHandle.h"
|
||||
#include "../UUID.h"
|
||||
|
||||
#include "../IniFile.h"
|
||||
#include "json/json.h"
|
||||
@@ -119,11 +120,11 @@ void cAuthenticator::Execute(void)
|
||||
Lock.Unlock();
|
||||
|
||||
AString NewUserName = UserName;
|
||||
AString UUID;
|
||||
cUUID UUID;
|
||||
Json::Value Properties;
|
||||
if (AuthWithYggdrasil(NewUserName, ServerID, UUID, Properties))
|
||||
{
|
||||
LOGINFO("User %s authenticated with UUID %s", NewUserName.c_str(), UUID.c_str());
|
||||
LOGINFO("User %s authenticated with UUID %s", NewUserName.c_str(), UUID.ToShortString().c_str());
|
||||
cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID, Properties);
|
||||
}
|
||||
else
|
||||
@@ -137,7 +138,7 @@ void cAuthenticator::Execute(void)
|
||||
|
||||
|
||||
|
||||
bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties)
|
||||
bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, cUUID & a_UUID, Json::Value & a_Properties)
|
||||
{
|
||||
LOGD("Trying to authenticate user %s", a_UserName.c_str());
|
||||
|
||||
@@ -192,8 +193,12 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
||||
return false;
|
||||
}
|
||||
a_UserName = root.get("name", "Unknown").asString();
|
||||
a_UUID = cMojangAPI::MakeUUIDShort(root.get("id", "").asString());
|
||||
a_Properties = root["properties"];
|
||||
if (!a_UUID.FromString(root.get("id", "").asString()))
|
||||
{
|
||||
LOGWARNING("cAuthenticator: Recieved invalid UUID format");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the player's profile in the MojangAPI caches:
|
||||
cRoot::Get()->GetMojangAPI().AddPlayerProfile(a_UserName, a_UUID, a_Properties);
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
|
||||
#include "../OSSupport/IsThread.h"
|
||||
|
||||
// fwd:
|
||||
class cUUID;
|
||||
class cSettingsRepositoryInterface;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
@@ -90,7 +88,7 @@ private:
|
||||
|
||||
/** Returns true if the user authenticated okay, false on error
|
||||
Returns the case-corrected username, UUID, and properties (eg. skin). */
|
||||
bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties);
|
||||
bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, cUUID & a_UUID, Json::Value & a_Properties);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ static const AString & GetCACerts(void)
|
||||
|
||||
cMojangAPI::sProfile::sProfile(
|
||||
const AString & a_PlayerName,
|
||||
const AString & a_UUID,
|
||||
const cUUID & a_UUID,
|
||||
const Json::Value & a_Properties,
|
||||
Int64 a_DateTime
|
||||
) :
|
||||
@@ -291,7 +291,7 @@ void cMojangAPI::Start(cSettingsRepositoryInterface & a_Settings, bool a_ShouldA
|
||||
|
||||
|
||||
|
||||
AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached)
|
||||
cUUID cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached)
|
||||
{
|
||||
// Convert the playername to lowercase:
|
||||
AString lcPlayerName = StrToLower(a_PlayerName);
|
||||
@@ -299,8 +299,7 @@ AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_U
|
||||
// Request the cache to query the name if not yet cached:
|
||||
if (!a_UseOnlyCached)
|
||||
{
|
||||
AStringVector PlayerNames;
|
||||
PlayerNames.push_back(lcPlayerName);
|
||||
AStringVector PlayerNames{ lcPlayerName };
|
||||
CacheNamesToUUIDs(PlayerNames);
|
||||
}
|
||||
|
||||
@@ -310,7 +309,7 @@ AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_U
|
||||
if (itr == m_NameToUUID.end())
|
||||
{
|
||||
// No UUID found
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
return itr->second.m_UUID;
|
||||
}
|
||||
@@ -319,15 +318,12 @@ AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_U
|
||||
|
||||
|
||||
|
||||
AString cMojangAPI::GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnlyCached)
|
||||
AString cMojangAPI::GetPlayerNameFromUUID(const cUUID & a_UUID, bool a_UseOnlyCached)
|
||||
{
|
||||
// Normalize the UUID to lowercase short format that is used as the map key:
|
||||
AString UUID = MakeUUIDShort(a_UUID);
|
||||
|
||||
// Retrieve from caches:
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
cProfileMap::const_iterator itr = m_UUIDToProfile.find(UUID);
|
||||
auto itr = m_UUIDToProfile.find(a_UUID);
|
||||
if (itr != m_UUIDToProfile.end())
|
||||
{
|
||||
return itr->second.m_PlayerName;
|
||||
@@ -335,7 +331,7 @@ AString cMojangAPI::GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnly
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
cProfileMap::const_iterator itr = m_UUIDToName.find(UUID);
|
||||
auto itr = m_UUIDToName.find(a_UUID);
|
||||
if (itr != m_UUIDToName.end())
|
||||
{
|
||||
return itr->second.m_PlayerName;
|
||||
@@ -345,19 +341,19 @@ AString cMojangAPI::GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnly
|
||||
// Name not yet cached, request cache and retry:
|
||||
if (!a_UseOnlyCached)
|
||||
{
|
||||
CacheUUIDToProfile(UUID);
|
||||
CacheUUIDToProfile(a_UUID);
|
||||
return GetPlayerNameFromUUID(a_UUID, true);
|
||||
}
|
||||
|
||||
// No value found, none queried. Return an error:
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_PlayerNames, bool a_UseOnlyCached)
|
||||
std::vector<cUUID> cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_PlayerNames, bool a_UseOnlyCached)
|
||||
{
|
||||
// Convert all playernames to lowercase:
|
||||
AStringVector PlayerNames;
|
||||
@@ -374,7 +370,7 @@ AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_Player
|
||||
|
||||
// Retrieve from cache:
|
||||
size_t idx = 0;
|
||||
AStringVector res;
|
||||
std::vector<cUUID> res;
|
||||
res.resize(PlayerNames.size());
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (AStringVector::const_iterator itr = PlayerNames.begin(), end = PlayerNames.end(); itr != end; ++itr, ++idx)
|
||||
@@ -392,17 +388,16 @@ AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_Player
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID)
|
||||
void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const cUUID & a_UUID)
|
||||
{
|
||||
AString UUID = MakeUUIDShort(a_UUID);
|
||||
Int64 Now = time(nullptr);
|
||||
{
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, a_UUID, "", "", Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
m_UUIDToName[a_UUID] = sProfile(a_PlayerName, a_UUID, "", "", Now);
|
||||
}
|
||||
NotifyNameUUID(a_PlayerName, a_UUID);
|
||||
}
|
||||
@@ -411,21 +406,20 @@ void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::AddPlayerProfile(const AString & a_PlayerName, const AString & a_UUID, const Json::Value & a_Properties)
|
||||
void cMojangAPI::AddPlayerProfile(const AString & a_PlayerName, const cUUID & a_UUID, const Json::Value & a_Properties)
|
||||
{
|
||||
AString UUID = MakeUUIDShort(a_UUID);
|
||||
Int64 Now = time(nullptr);
|
||||
{
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, a_UUID, "", "", Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
m_UUIDToName[a_UUID] = sProfile(a_PlayerName, a_UUID, "", "", Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
m_UUIDToProfile[UUID] = sProfile(a_PlayerName, UUID, a_Properties, Now);
|
||||
m_UUIDToProfile[a_UUID] = sProfile(a_PlayerName, a_UUID, a_Properties, Now);
|
||||
}
|
||||
NotifyNameUUID(a_PlayerName, a_UUID);
|
||||
}
|
||||
@@ -488,74 +482,6 @@ bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_R
|
||||
|
||||
|
||||
|
||||
AString cMojangAPI::MakeUUIDShort(const AString & a_UUID)
|
||||
{
|
||||
// Note: we only check the string's length, not the actual content
|
||||
switch (a_UUID.size())
|
||||
{
|
||||
case 32:
|
||||
{
|
||||
// Already is a short UUID, only lowercase
|
||||
return StrToLower(a_UUID);
|
||||
}
|
||||
|
||||
case 36:
|
||||
{
|
||||
// Remove the dashes from the string by appending together the parts between them:
|
||||
AString res;
|
||||
res.reserve(32);
|
||||
res.append(a_UUID, 0, 8);
|
||||
res.append(a_UUID, 9, 4);
|
||||
res.append(a_UUID, 14, 4);
|
||||
res.append(a_UUID, 19, 4);
|
||||
res.append(a_UUID, 24, 12);
|
||||
return StrToLower(res);
|
||||
}
|
||||
}
|
||||
LOGWARNING("%s: Not an UUID: \"%s\".", __FUNCTION__, a_UUID.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AString cMojangAPI::MakeUUIDDashed(const AString & a_UUID)
|
||||
{
|
||||
// Note: we only check the string's length, not the actual content
|
||||
switch (a_UUID.size())
|
||||
{
|
||||
case 36:
|
||||
{
|
||||
// Already is a dashed UUID, only lowercase
|
||||
return StrToLower(a_UUID);
|
||||
}
|
||||
|
||||
case 32:
|
||||
{
|
||||
// Insert dashes at the proper positions:
|
||||
AString res;
|
||||
res.reserve(36);
|
||||
res.append(a_UUID, 0, 8);
|
||||
res.push_back('-');
|
||||
res.append(a_UUID, 8, 4);
|
||||
res.push_back('-');
|
||||
res.append(a_UUID, 12, 4);
|
||||
res.push_back('-');
|
||||
res.append(a_UUID, 16, 4);
|
||||
res.push_back('-');
|
||||
res.append(a_UUID, 20, 12);
|
||||
return StrToLower(res);
|
||||
}
|
||||
}
|
||||
LOGWARNING("%s: Not an UUID: \"%s\".", __FUNCTION__, a_UUID.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::LoadCachesFromDisk(void)
|
||||
{
|
||||
try
|
||||
@@ -571,9 +497,15 @@ void cMojangAPI::LoadCachesFromDisk(void)
|
||||
while (stmt.executeStep())
|
||||
{
|
||||
AString PlayerName = stmt.getColumn(0);
|
||||
AString UUID = stmt.getColumn(1);
|
||||
AString StringUUID = stmt.getColumn(1);
|
||||
Int64 DateTime = stmt.getColumn(2);
|
||||
UUID = MakeUUIDShort(UUID);
|
||||
|
||||
cUUID UUID;
|
||||
if (!UUID.FromString(StringUUID))
|
||||
{
|
||||
continue; // Invalid UUID
|
||||
}
|
||||
|
||||
m_NameToUUID[StrToLower(PlayerName)] = sProfile(PlayerName, UUID, "", "", DateTime);
|
||||
m_UUIDToName[UUID] = sProfile(PlayerName, UUID, "", "", DateTime);
|
||||
}
|
||||
@@ -583,11 +515,17 @@ void cMojangAPI::LoadCachesFromDisk(void)
|
||||
while (stmt.executeStep())
|
||||
{
|
||||
AString PlayerName = stmt.getColumn(0);
|
||||
AString UUID = stmt.getColumn(1);
|
||||
AString StringUUID = stmt.getColumn(1);
|
||||
AString Textures = stmt.getColumn(2);
|
||||
AString TexturesSignature = stmt.getColumn(2);
|
||||
Int64 DateTime = stmt.getColumn(4);
|
||||
UUID = MakeUUIDShort(UUID);
|
||||
|
||||
cUUID UUID;
|
||||
if (!UUID.FromString(StringUUID))
|
||||
{
|
||||
continue; // Invalid UUID
|
||||
}
|
||||
|
||||
m_UUIDToProfile[UUID] = sProfile(PlayerName, UUID, Textures, TexturesSignature, DateTime);
|
||||
}
|
||||
}
|
||||
@@ -620,16 +558,17 @@ void cMojangAPI::SaveCachesToDisk(void)
|
||||
{
|
||||
SQLite::Statement stmt(db, "INSERT INTO PlayerNameToUUID(PlayerName, UUID, DateTime) VALUES (?, ?, ?)");
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
|
||||
for (auto & NameToUUID : m_NameToUUID)
|
||||
{
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
auto & Profile = NameToUUID.second;
|
||||
if (Profile.m_DateTime < LimitDateTime)
|
||||
{
|
||||
// This item is too old, do not save
|
||||
continue;
|
||||
}
|
||||
stmt.bind(1, itr->second.m_PlayerName);
|
||||
stmt.bind(2, itr->second.m_UUID);
|
||||
stmt.bind(3, itr->second.m_DateTime);
|
||||
stmt.bind(1, Profile.m_PlayerName);
|
||||
stmt.bind(2, Profile.m_UUID.ToShortString());
|
||||
stmt.bind(3, Profile.m_DateTime);
|
||||
stmt.exec();
|
||||
stmt.reset();
|
||||
}
|
||||
@@ -639,18 +578,19 @@ void cMojangAPI::SaveCachesToDisk(void)
|
||||
{
|
||||
SQLite::Statement stmt(db, "INSERT INTO UUIDToProfile(UUID, PlayerName, Textures, TexturesSignature, DateTime) VALUES (?, ?, ?, ?, ?)");
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
|
||||
for (auto & UUIDToProfile : m_UUIDToProfile)
|
||||
{
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
auto & Profile = UUIDToProfile.second;
|
||||
if (Profile.m_DateTime < LimitDateTime)
|
||||
{
|
||||
// This item is too old, do not save
|
||||
continue;
|
||||
}
|
||||
stmt.bind(1, itr->second.m_UUID);
|
||||
stmt.bind(2, itr->second.m_PlayerName);
|
||||
stmt.bind(3, itr->second.m_Textures);
|
||||
stmt.bind(4, itr->second.m_TexturesSignature);
|
||||
stmt.bind(5, itr->second.m_DateTime);
|
||||
stmt.bind(1, Profile.m_UUID.ToShortString());
|
||||
stmt.bind(2, Profile.m_PlayerName);
|
||||
stmt.bind(3, Profile.m_Textures);
|
||||
stmt.bind(4, Profile.m_TexturesSignature);
|
||||
stmt.bind(5, Profile.m_DateTime);
|
||||
stmt.exec();
|
||||
stmt.reset();
|
||||
}
|
||||
@@ -762,8 +702,8 @@ void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
|
||||
{
|
||||
Json::Value & Val = root[idx];
|
||||
AString JsonName = Val.get("name", "").asString();
|
||||
AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString());
|
||||
if (JsonUUID.empty())
|
||||
cUUID JsonUUID;
|
||||
if (!JsonUUID.FromString(Val.get("id", "").asString()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -779,8 +719,8 @@ void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
|
||||
{
|
||||
Json::Value & Val = root[idx];
|
||||
AString JsonName = Val.get("name", "").asString();
|
||||
AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString());
|
||||
if (JsonUUID.empty())
|
||||
cUUID JsonUUID;
|
||||
if (!JsonUUID.FromString(Val.get("id", "").asString()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -794,10 +734,8 @@ void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
|
||||
void cMojangAPI::CacheUUIDToProfile(const cUUID & a_UUID)
|
||||
{
|
||||
ASSERT(a_UUID.size() == 32);
|
||||
|
||||
// Check if already present:
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
@@ -814,11 +752,11 @@ void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::QueryUUIDToProfile(const AString & a_UUID)
|
||||
void cMojangAPI::QueryUUIDToProfile(const cUUID & a_UUID)
|
||||
{
|
||||
// Create the request address:
|
||||
AString Address = m_UUIDToProfileAddress;
|
||||
ReplaceString(Address, "%UUID%", a_UUID);
|
||||
ReplaceString(Address, "%UUID%", a_UUID.ToShortString());
|
||||
|
||||
// Create the HTTP request:
|
||||
AString Request;
|
||||
@@ -909,7 +847,7 @@ void cMojangAPI::QueryUUIDToProfile(const AString & a_UUID)
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const AString & a_UUID)
|
||||
void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const cUUID & a_UUID)
|
||||
{
|
||||
// Notify the rank manager:
|
||||
cCSLock Lock(m_CSRankMgr);
|
||||
@@ -931,11 +869,11 @@ void cMojangAPI::Update(void)
|
||||
AStringVector PlayerNames;
|
||||
{
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
|
||||
for (const auto & NameToUUID : m_NameToUUID)
|
||||
{
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
if (NameToUUID.second.m_DateTime < LimitDateTime)
|
||||
{
|
||||
PlayerNames.push_back(itr->first);
|
||||
PlayerNames.push_back(NameToUUID.first);
|
||||
}
|
||||
} // for itr - m_NameToUUID[]
|
||||
}
|
||||
@@ -946,23 +884,23 @@ void cMojangAPI::Update(void)
|
||||
}
|
||||
|
||||
// Re-query all profiles that are stale:
|
||||
AStringVector ProfileUUIDs;
|
||||
std::vector<cUUID> ProfileUUIDs;
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
|
||||
for (auto & UUIDToProfile : m_UUIDToProfile)
|
||||
{
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
if (UUIDToProfile.second.m_DateTime < LimitDateTime)
|
||||
{
|
||||
ProfileUUIDs.push_back(itr->first);
|
||||
ProfileUUIDs.push_back(UUIDToProfile.first);
|
||||
}
|
||||
} // for itr - m_UUIDToProfile[]
|
||||
}
|
||||
if (!ProfileUUIDs.empty())
|
||||
{
|
||||
LOG("cMojangAPI: Updating uuid-to-profile cache for %u uuids", static_cast<unsigned>(ProfileUUIDs.size()));
|
||||
for (AStringVector::const_iterator itr = ProfileUUIDs.begin(), end = ProfileUUIDs.end(); itr != end; ++itr)
|
||||
for (const auto & UUID : ProfileUUIDs)
|
||||
{
|
||||
QueryUUIDToProfile(*itr);
|
||||
QueryUUIDToProfile(UUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../UUID.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,49 +47,38 @@ public:
|
||||
Returns true if all was successful, false on failure. */
|
||||
static bool SecureRequest(const AString & a_ServerName, const AString & a_Request, AString & a_Response);
|
||||
|
||||
/** Normalizes the given UUID to its short form (32 bytes, no dashes, lowercase).
|
||||
Logs a warning and returns empty string if not a UUID.
|
||||
Note: only checks the string's length, not the actual content. */
|
||||
static AString MakeUUIDShort(const AString & a_UUID);
|
||||
|
||||
/** Normalizes the given UUID to its dashed form (36 bytes, 4 dashes, lowercase).
|
||||
Logs a warning and returns empty string if not a UUID.
|
||||
Note: only checks the string's length, not the actual content. */
|
||||
static AString MakeUUIDDashed(const AString & a_UUID);
|
||||
|
||||
/** Converts a player name into a UUID.
|
||||
The UUID will be empty on error.
|
||||
The UUID will be nil on error.
|
||||
If a_UseOnlyCached is true, the function only consults the cached values.
|
||||
If a_UseOnlyCached is false and the name is not found in the cache, it is looked up online, which is a blocking
|
||||
operation, do not use this in world-tick thread!
|
||||
If you have multiple names to resolve, use the GetUUIDsFromPlayerNames() function, it uses a single request for multiple names. */
|
||||
AString GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached = false);
|
||||
cUUID GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached = false);
|
||||
|
||||
/** Converts a UUID into a playername.
|
||||
The returned playername will be empty on error.
|
||||
Both short and dashed UUID formats are accepted.
|
||||
Uses both m_UUIDToName and m_UUIDToProfile to search for the value. Uses m_UUIDToProfile for cache.
|
||||
If a_UseOnlyCached is true, the function only consults the cached values.
|
||||
If a_UseOnlyCached is false and the name is not found in the cache, it is looked up online, which is a blocking
|
||||
operation, do not use this in world-tick thread! */
|
||||
AString GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnlyCached = false);
|
||||
AString GetPlayerNameFromUUID(const cUUID & a_UUID, bool a_UseOnlyCached = false);
|
||||
|
||||
/** Converts the player names into UUIDs.
|
||||
a_PlayerName[idx] will be converted to UUID and returned as idx-th value
|
||||
The UUID will be empty on error.
|
||||
The UUID will be nil on error.
|
||||
If a_UseOnlyCached is true, only the cached values are returned.
|
||||
If a_UseOnlyCached is false, the names not found in the cache are looked up online, which is a blocking
|
||||
operation, do not use this in world-tick thread! */
|
||||
AStringVector GetUUIDsFromPlayerNames(const AStringVector & a_PlayerName, bool a_UseOnlyCached = false);
|
||||
std::vector<cUUID> GetUUIDsFromPlayerNames(const AStringVector & a_PlayerName, bool a_UseOnlyCached = false);
|
||||
|
||||
/** Called by the Authenticator to add a PlayerName -> UUID mapping that it has received from
|
||||
authenticating a user. This adds the cache item and "refreshes" it if existing, adjusting its datetime
|
||||
stamp to now. */
|
||||
void AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID);
|
||||
void AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const cUUID & a_UUID);
|
||||
|
||||
/** Called by the Authenticator to add a profile that it has received from authenticating a user. Adds
|
||||
the profile to the respective mapping caches and updtes their datetime stamp to now. */
|
||||
void AddPlayerProfile(const AString & a_PlayerName, const AString & a_UUID, const Json::Value & a_Properties);
|
||||
void AddPlayerProfile(const AString & a_PlayerName, const cUUID & a_UUID, const Json::Value & a_Properties);
|
||||
|
||||
/** Sets the m_RankMgr that is used for name-uuid notifications. Accepts nullptr to remove the binding. */
|
||||
void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; }
|
||||
@@ -101,7 +92,7 @@ protected:
|
||||
struct sProfile
|
||||
{
|
||||
AString m_PlayerName; // Case-correct playername
|
||||
AString m_UUID; // Short lowercased UUID
|
||||
cUUID m_UUID; // Player UUID
|
||||
AString m_Textures; // The Textures field of the profile properties
|
||||
AString m_TexturesSignature; // The signature of the Textures field of the profile properties
|
||||
Int64 m_DateTime; // UNIXtime of the profile lookup
|
||||
@@ -119,7 +110,7 @@ protected:
|
||||
/** Constructor for the storage creation. */
|
||||
sProfile(
|
||||
const AString & a_PlayerName,
|
||||
const AString & a_UUID,
|
||||
const cUUID & a_UUID,
|
||||
const AString & a_Textures,
|
||||
const AString & a_TexturesSignature,
|
||||
Int64 a_DateTime
|
||||
@@ -135,12 +126,13 @@ protected:
|
||||
/** Constructor that parses the values from the Json profile. */
|
||||
sProfile(
|
||||
const AString & a_PlayerName,
|
||||
const AString & a_UUID,
|
||||
const cUUID & a_UUID,
|
||||
const Json::Value & a_Properties,
|
||||
Int64 a_DateTime
|
||||
);
|
||||
};
|
||||
typedef std::map<AString, sProfile> cProfileMap;
|
||||
typedef std::map<cUUID, sProfile> cUUIDProfileMap;
|
||||
|
||||
|
||||
/** The server to connect to when converting player names to UUIDs. For example "api.mojang.com". */
|
||||
@@ -164,14 +156,14 @@ protected:
|
||||
cCriticalSection m_CSNameToUUID;
|
||||
|
||||
/** Cache for the Name-to-UUID lookups. The map key is lowercased short UUID. Protected by m_CSUUIDToName. */
|
||||
cProfileMap m_UUIDToName;
|
||||
cUUIDProfileMap m_UUIDToName;
|
||||
|
||||
/** Protects m_UUIDToName against simultaneous multi-threaded access. */
|
||||
cCriticalSection m_CSUUIDToName;
|
||||
|
||||
/** Cache for the UUID-to-profile lookups. The map key is lowercased short UUID.
|
||||
Protected by m_CSUUIDToProfile. */
|
||||
cProfileMap m_UUIDToProfile;
|
||||
cUUIDProfileMap m_UUIDToProfile;
|
||||
|
||||
/** Protects m_UUIDToProfile against simultaneous multi-threaded access. */
|
||||
cCriticalSection m_CSUUIDToProfile;
|
||||
@@ -204,18 +196,16 @@ protected:
|
||||
void QueryNamesToUUIDs(AStringVector & a_PlayerNames);
|
||||
|
||||
/** Makes sure the specified UUID is in the m_UUIDToProfile cache. If missing, downloads it from Mojang API servers.
|
||||
UUIDs that are not valid will not be added into the cache.
|
||||
ASSUMEs that a_UUID is a lowercased short UUID. */
|
||||
void CacheUUIDToProfile(const AString & a_UUID);
|
||||
UUIDs that are not valid will not be added into the cache. */
|
||||
void CacheUUIDToProfile(const cUUID & a_UUID);
|
||||
|
||||
/** Queries the specified UUID's profile and stores it in the m_UUIDToProfile cache. If already present, updates the cache entry.
|
||||
UUIDs that are not valid will not be added into the cache.
|
||||
ASSUMEs that a_UUID is a lowercased short UUID. */
|
||||
void QueryUUIDToProfile(const AString & a_UUID);
|
||||
UUIDs that are not valid will not be added into the cache. */
|
||||
void QueryUUIDToProfile(const cUUID & a_UUID);
|
||||
|
||||
/** Called for each name-uuid pairing that is discovered.
|
||||
If assigned, notifies the m_RankManager of the event. */
|
||||
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_PlayerUUID);
|
||||
void NotifyNameUUID(const AString & a_PlayerName, const cUUID & a_PlayerUUID);
|
||||
|
||||
/** Updates the stale values in the DB from the Mojang servers. Called from the cUpdateThread, blocks on the HTTPS API calls. */
|
||||
void Update(void);
|
||||
|
||||
@@ -5,46 +5,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Packetizer.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Converts the hex digit character to its value. */
|
||||
static UInt8 HexDigitValue(char a_Character)
|
||||
{
|
||||
switch (a_Character)
|
||||
{
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
case 'a': return 10;
|
||||
case 'b': return 11;
|
||||
case 'c': return 12;
|
||||
case 'd': return 13;
|
||||
case 'e': return 14;
|
||||
case 'f': return 15;
|
||||
case 'A': return 10;
|
||||
case 'B': return 11;
|
||||
case 'C': return 12;
|
||||
case 'D': return 13;
|
||||
case 'E': return 14;
|
||||
case 'F': return 15;
|
||||
default:
|
||||
{
|
||||
LOGWARNING("Bad hex digit: %c", a_Character);
|
||||
ASSERT(!"Bad hex digit");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "UUID.h"
|
||||
|
||||
|
||||
|
||||
@@ -80,18 +41,10 @@ void cPacketizer::WriteFPInt(double a_Value)
|
||||
|
||||
|
||||
|
||||
void cPacketizer::WriteUUID(const AString & a_UUID)
|
||||
void cPacketizer::WriteUUID(const cUUID & a_UUID)
|
||||
{
|
||||
if (a_UUID.length() != 32)
|
||||
for (auto val : a_UUID.ToRaw())
|
||||
{
|
||||
LOGWARNING("%s: Attempt to send a bad uuid (length isn't 32): %s", __FUNCTION__, a_UUID.c_str());
|
||||
ASSERT(!"Wrong uuid length!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 32; i += 2)
|
||||
{
|
||||
auto val = static_cast<UInt8>(HexDigitValue(a_UUID[i]) << 4 | HexDigitValue(a_UUID[i + 1]));
|
||||
VERIFY(m_Out.WriteBEUInt8(val));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
class cByteBuffer;
|
||||
|
||||
|
||||
// fwd:
|
||||
class cUUID;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -134,7 +138,7 @@ public:
|
||||
void WriteFPInt(double a_Value);
|
||||
|
||||
/** Writes the specified UUID as a 128-bit BigEndian integer. */
|
||||
void WriteUUID(const AString & a_UUID);
|
||||
void WriteUUID(const cUUID & a_UUID);
|
||||
|
||||
UInt32 GetPacketType(void) const { return m_PacketType; }
|
||||
|
||||
|
||||
@@ -619,7 +619,7 @@ void cProtocol_1_10_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity
|
||||
|
||||
// The new Block Entity format for a Mob Head. See: https://minecraft.gamepedia.com/Head#Block_entity
|
||||
Writer.BeginCompound("Owner");
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID());
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID().ToShortString());
|
||||
Writer.AddString("Name", MobHeadEntity.GetOwnerName());
|
||||
Writer.BeginCompound("Properties");
|
||||
Writer.BeginList("textures", TAG_Compound);
|
||||
|
||||
@@ -466,7 +466,7 @@ void cProtocol_1_11_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity
|
||||
|
||||
// The new Block Entity format for a Mob Head. See: https://minecraft.gamepedia.com/Head#Block_entity
|
||||
Writer.BeginCompound("Owner");
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID());
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID().ToShortString());
|
||||
Writer.AddString("Name", MobHeadEntity.GetOwnerName());
|
||||
Writer.BeginCompound("Properties");
|
||||
Writer.BeginList("textures", TAG_Compound);
|
||||
|
||||
@@ -22,6 +22,7 @@ Implements the 1.8 protocol classes:
|
||||
#include "../StringCompression.h"
|
||||
#include "../CompositeChat.h"
|
||||
#include "../Statistics.h"
|
||||
#include "../UUID.h"
|
||||
|
||||
#include "../WorldStorage/FastNBT.h"
|
||||
#include "../WorldStorage/EnchantmentSerializer.h"
|
||||
@@ -118,7 +119,11 @@ cProtocol_1_8_0::cProtocol_1_8_0(cClientHandle * a_Client, const AString & a_Ser
|
||||
LOGD("Player at %s connected via BungeeCord", Params[1].c_str());
|
||||
m_ServerAddress = Params[0];
|
||||
m_Client->SetIPString(Params[1]);
|
||||
m_Client->SetUUID(cMojangAPI::MakeUUIDShort(Params[2]));
|
||||
|
||||
cUUID UUID;
|
||||
UUID.FromString(Params[2]);
|
||||
m_Client->SetUUID(UUID);
|
||||
|
||||
m_Client->SetProperties(Params[3]);
|
||||
}
|
||||
|
||||
@@ -705,7 +710,7 @@ void cProtocol_1_8_0::SendLoginSuccess(void)
|
||||
|
||||
{
|
||||
cPacketizer Pkt(*this, 0x02); // Login success packet
|
||||
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID()));
|
||||
Pkt.WriteString(m_Client->GetUUID().ToLongString());
|
||||
Pkt.WriteString(m_Client->GetUsername());
|
||||
}
|
||||
}
|
||||
@@ -1071,7 +1076,7 @@ void cProtocol_1_8_0::SendPlayerSpawn(const cPlayer & a_Player)
|
||||
// Called to spawn another player for the client
|
||||
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
|
||||
Pkt.WriteVarInt32(a_Player.GetUniqueID());
|
||||
Pkt.WriteUUID(cMojangAPI::MakeUUIDShort(a_Player.GetUUID()));
|
||||
Pkt.WriteUUID(a_Player.GetUUID());
|
||||
Pkt.WriteFPInt(a_Player.GetPosX());
|
||||
Pkt.WriteFPInt(a_Player.GetPosY() + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on.
|
||||
Pkt.WriteFPInt(a_Player.GetPosZ());
|
||||
@@ -2551,7 +2556,7 @@ void cProtocol_1_8_0::HandlePacketSlotSelect(cByteBuffer & a_ByteBuffer)
|
||||
|
||||
void cProtocol_1_8_0::HandlePacketSpectate(cByteBuffer &a_ByteBuffer)
|
||||
{
|
||||
AString playerUUID;
|
||||
cUUID playerUUID;
|
||||
if (!a_ByteBuffer.ReadUUID(playerUUID))
|
||||
{
|
||||
return;
|
||||
@@ -3183,7 +3188,7 @@ void cProtocol_1_8_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity &
|
||||
|
||||
// The new Block Entity format for a Mob Head. See: https://minecraft.gamepedia.com/Head#Block_entity
|
||||
Writer.BeginCompound("Owner");
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID());
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID().ToShortString());
|
||||
Writer.AddString("Name", MobHeadEntity.GetOwnerName());
|
||||
Writer.BeginCompound("Properties");
|
||||
Writer.BeginList("textures", TAG_Compound);
|
||||
|
||||
@@ -133,7 +133,11 @@ cProtocol_1_9_0::cProtocol_1_9_0(cClientHandle * a_Client, const AString & a_Ser
|
||||
LOGD("Player at %s connected via BungeeCord", Params[1].c_str());
|
||||
m_ServerAddress = Params[0];
|
||||
m_Client->SetIPString(Params[1]);
|
||||
m_Client->SetUUID(cMojangAPI::MakeUUIDShort(Params[2]));
|
||||
|
||||
cUUID UUID;
|
||||
UUID.FromString(Params[2]);
|
||||
m_Client->SetUUID(UUID);
|
||||
|
||||
m_Client->SetProperties(Params[3]);
|
||||
}
|
||||
|
||||
@@ -720,7 +724,7 @@ void cProtocol_1_9_0::SendLoginSuccess(void)
|
||||
|
||||
{
|
||||
cPacketizer Pkt(*this, 0x02); // Login success packet
|
||||
Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID()));
|
||||
Pkt.WriteString(m_Client->GetUUID().ToLongString());
|
||||
Pkt.WriteString(m_Client->GetUsername());
|
||||
}
|
||||
}
|
||||
@@ -1094,7 +1098,7 @@ void cProtocol_1_9_0::SendPlayerSpawn(const cPlayer & a_Player)
|
||||
// Called to spawn another player for the client
|
||||
cPacketizer Pkt(*this, 0x05); // Spawn Player packet
|
||||
Pkt.WriteVarInt32(a_Player.GetUniqueID());
|
||||
Pkt.WriteUUID(cMojangAPI::MakeUUIDShort(a_Player.GetUUID()));
|
||||
Pkt.WriteUUID(a_Player.GetUUID());
|
||||
Pkt.WriteBEDouble(a_Player.GetPosX());
|
||||
Pkt.WriteBEDouble(a_Player.GetPosY() + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on.
|
||||
Pkt.WriteBEDouble(a_Player.GetPosZ());
|
||||
@@ -2624,7 +2628,7 @@ void cProtocol_1_9_0::HandlePacketSlotSelect(cByteBuffer & a_ByteBuffer)
|
||||
|
||||
void cProtocol_1_9_0::HandlePacketSpectate(cByteBuffer & a_ByteBuffer)
|
||||
{
|
||||
AString playerUUID;
|
||||
cUUID playerUUID;
|
||||
if (!a_ByteBuffer.ReadUUID(playerUUID))
|
||||
{
|
||||
return;
|
||||
@@ -3513,7 +3517,7 @@ void cProtocol_1_9_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity &
|
||||
|
||||
// The new Block Entity format for a Mob Head. See: https://minecraft.gamepedia.com/Head#Block_entity
|
||||
Writer.BeginCompound("Owner");
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID());
|
||||
Writer.AddString("Id", MobHeadEntity.GetOwnerUUID().ToShortString());
|
||||
Writer.AddString("Name", MobHeadEntity.GetOwnerName());
|
||||
Writer.BeginCompound("Properties");
|
||||
Writer.BeginList("textures", TAG_Compound);
|
||||
|
||||
Reference in New Issue
Block a user