From f4f2fc7c3d76eb3dc5a91c5eefb36c10597d6cb7 Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Fri, 25 Aug 2017 13:43:18 +0100 Subject: Add cUUID class (#3871) --- src/Protocol/Authenticator.cpp | 13 ++- src/Protocol/Authenticator.h | 8 +- src/Protocol/MojangAPI.cpp | 192 ++++++++++++++--------------------------- src/Protocol/MojangAPI.h | 50 +++++------ src/Protocol/Packetizer.cpp | 53 +----------- src/Protocol/Packetizer.h | 6 +- src/Protocol/Protocol_1_10.cpp | 2 +- src/Protocol/Protocol_1_11.cpp | 2 +- src/Protocol/Protocol_1_8.cpp | 15 ++-- src/Protocol/Protocol_1_9.cpp | 14 +-- 10 files changed, 126 insertions(+), 229 deletions(-) (limited to 'src/Protocol') diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp index 12e963143..d46127d34 100644 --- a/src/Protocol/Authenticator.cpp +++ b/src/Protocol/Authenticator.cpp @@ -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); diff --git a/src/Protocol/Authenticator.h b/src/Protocol/Authenticator.h index 5ce06093c..98bf17512 100644 --- a/src/Protocol/Authenticator.h +++ b/src/Protocol/Authenticator.h @@ -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); }; diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp index 4d5361479..5a11356c1 100644 --- a/src/Protocol/MojangAPI.cpp +++ b/src/Protocol/MojangAPI.cpp @@ -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 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 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 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(ProfileUUIDs.size())); - for (AStringVector::const_iterator itr = ProfileUUIDs.begin(), end = ProfileUUIDs.end(); itr != end; ++itr) + for (const auto & UUID : ProfileUUIDs) { - QueryUUIDToProfile(*itr); + QueryUUIDToProfile(UUID); } } } diff --git a/src/Protocol/MojangAPI.h b/src/Protocol/MojangAPI.h index 3cd0376be..4d1751f1c 100644 --- a/src/Protocol/MojangAPI.h +++ b/src/Protocol/MojangAPI.h @@ -11,6 +11,8 @@ #include +#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 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 cProfileMap; + typedef std::map 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); diff --git a/src/Protocol/Packetizer.cpp b/src/Protocol/Packetizer.cpp index 0a84d4678..5cae1fad5 100644 --- a/src/Protocol/Packetizer.cpp +++ b/src/Protocol/Packetizer.cpp @@ -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) - { - 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) + for (auto val : a_UUID.ToRaw()) { - auto val = static_cast(HexDigitValue(a_UUID[i]) << 4 | HexDigitValue(a_UUID[i + 1])); VERIFY(m_Out.WriteBEUInt8(val)); } } diff --git a/src/Protocol/Packetizer.h b/src/Protocol/Packetizer.h index 26b3a7ec7..6d2284976 100644 --- a/src/Protocol/Packetizer.h +++ b/src/Protocol/Packetizer.h @@ -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; } diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index 650f9dd32..67b76872a 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -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); diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp index 9212e97ed..c562503bd 100644 --- a/src/Protocol/Protocol_1_11.cpp +++ b/src/Protocol/Protocol_1_11.cpp @@ -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); diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index 3e2f084c7..42e69fd43 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -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); diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 7921d3e36..0c5ac58f6 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -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); -- cgit v1.2.3