summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Protocol/MojangAPI.cpp135
-rw-r--r--src/Protocol/MojangAPI.h23
-rw-r--r--src/Protocol/Protocol.h2
-rw-r--r--src/Protocol/Protocol17x.cpp2
-rw-r--r--src/Protocol/Protocol17x.h2
-rw-r--r--src/Protocol/Protocol18x.cpp2
-rw-r--r--src/Protocol/Protocol18x.h2
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp2
-rw-r--r--src/Protocol/ProtocolRecognizer.h2
9 files changed, 144 insertions, 28 deletions
diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp
index 28da83c31..a4b4dbd3b 100644
--- a/src/Protocol/MojangAPI.cpp
+++ b/src/Protocol/MojangAPI.cpp
@@ -11,6 +11,8 @@
#include "json/json.h"
#include "PolarSSL++/BlockingSslClientSocket.h"
#include "../RankManager.h"
+#include "../OSSupport/IsThread.h"
+#include "../Root.h"
@@ -152,6 +154,41 @@ cMojangAPI::sProfile::sProfile(
////////////////////////////////////////////////////////////////////////////////
+// cMojangAPI::cUpdateThread:
+
+class cMojangAPI::cUpdateThread :
+ public cIsThread
+{
+ typedef cIsThread super;
+public:
+ cUpdateThread() :
+ super("cMojangAPI::cUpdateThread")
+ {
+ }
+
+ ~cUpdateThread()
+ {
+ m_evtNotify.Set();
+ Stop();
+ }
+
+protected:
+ cEvent m_evtNotify;
+
+ virtual void Execute(void) override
+ {
+ do
+ {
+ cRoot::Get()->GetMojangAPI().Update();
+ } while (!m_evtNotify.Wait(60 * 60 * 1000)); // Repeat every 60 minutes
+ }
+} ;
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cMojangAPI:
cMojangAPI::cMojangAPI(void) :
@@ -159,7 +196,8 @@ cMojangAPI::cMojangAPI(void) :
m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS),
m_UUIDToProfileServer(DEFAULT_UUID_TO_PROFILE_SERVER),
m_UUIDToProfileAddress(DEFAULT_UUID_TO_PROFILE_ADDRESS),
- m_RankMgr(NULL)
+ m_RankMgr(NULL),
+ m_UpdateThread(new cUpdateThread())
{
}
@@ -176,13 +214,17 @@ cMojangAPI::~cMojangAPI()
-void cMojangAPI::Start(cIniFile & a_SettingsIni)
+void cMojangAPI::Start(cIniFile & a_SettingsIni, bool a_ShouldAuth)
{
m_NameToUUIDServer = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER);
m_NameToUUIDAddress = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS);
m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
LoadCachesFromDisk();
+ if (a_ShouldAuth)
+ {
+ m_UpdateThread->Start();
+ }
}
@@ -465,21 +507,7 @@ void cMojangAPI::LoadCachesFromDisk(void)
db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
- // Clean up old entries:
- {
- SQLite::Statement stmt(db, "DELETE FROM PlayerNameToUUID WHERE DateTime < ?");
- Int64 LimitDateTime = time(NULL) - MAX_AGE;
- stmt.bind(1, LimitDateTime);
- stmt.exec();
- }
- {
- SQLite::Statement stmt(db, "DELETE FROM UUIDToProfile WHERE DateTime < ?");
- Int64 LimitDateTime = time(NULL) - MAX_AGE;
- stmt.bind(1, LimitDateTime);
- stmt.exec();
- }
-
- // Retrieve all remaining entries:
+ // Retrieve all entries:
{
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
while (stmt.executeStep())
@@ -596,18 +624,27 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
} // for itr - a_PlayerNames[]
} // Lock(m_CSNameToUUID)
- while (!NamesToQuery.empty())
+ QueryNamesToUUIDs(NamesToQuery);
+}
+
+
+
+
+
+void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
+{
+ while (!a_NamesToQuery.empty())
{
// Create the request body - a JSON containing up to MAX_PER_QUERY playernames:
Json::Value root;
int Count = 0;
- AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end();
+ AStringVector::iterator itr = a_NamesToQuery.begin(), end = a_NamesToQuery.end();
for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count)
{
Json::Value req(*itr);
root.append(req);
} // for itr - a_PlayerNames[]
- NamesToQuery.erase(NamesToQuery.begin(), itr);
+ a_NamesToQuery.erase(a_NamesToQuery.begin(), itr);
Json::FastWriter Writer;
AString RequestBody = Writer.write(root);
@@ -705,12 +742,22 @@ void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
// Check if already present:
{
+ cCSLock Lock(m_CSUUIDToProfile);
if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end())
{
return;
}
}
+ QueryUUIDToProfile(a_UUID);
+}
+
+
+
+
+
+void cMojangAPI::QueryUUIDToProfile(const AString & a_UUID)
+{
// Create the request address:
AString Address = m_UUIDToProfileAddress;
ReplaceString(Address, "%UUID%", a_UUID);
@@ -817,3 +864,51 @@ void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const AString & a_
+
+void cMojangAPI::Update(void)
+{
+ Int64 LimitDateTime = time(NULL) - MAX_AGE;
+
+ // Re-query all playernames that are stale:
+ AStringVector PlayerNames;
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
+ {
+ if (itr->second.m_DateTime < LimitDateTime)
+ {
+ PlayerNames.push_back(itr->first);
+ }
+ } // for itr - m_NameToUUID[]
+ }
+ if (!PlayerNames.empty())
+ {
+ LOG("cMojangAPI: Updating name-to-uuid cache for %u names", (unsigned)PlayerNames.size());
+ QueryNamesToUUIDs(PlayerNames);
+ }
+
+ // Re-query all profiles that are stale:
+ AStringVector ProfileUUIDs;
+ {
+ cCSLock Lock(m_CSUUIDToProfile);
+ for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
+ {
+ if (itr->second.m_DateTime < LimitDateTime)
+ {
+ ProfileUUIDs.push_back(itr->first);
+ }
+ } // for itr - m_UUIDToProfile[]
+ }
+ if (!ProfileUUIDs.empty())
+ {
+ LOG("cMojangAPI: Updating uuid-to-profile cache for %u uuids", (unsigned)ProfileUUIDs.size());
+ for (AStringVector::const_iterator itr = ProfileUUIDs.begin(), end = ProfileUUIDs.end(); itr != end; ++itr)
+ {
+ QueryUUIDToProfile(*itr);
+ }
+ }
+}
+
+
+
+
diff --git a/src/Protocol/MojangAPI.h b/src/Protocol/MojangAPI.h
index 252d32543..393fd4baa 100644
--- a/src/Protocol/MojangAPI.h
+++ b/src/Protocol/MojangAPI.h
@@ -38,7 +38,7 @@ public:
/** Initializes the API; reads the settings from the specified ini file.
Loads cached results from disk. */
- void Start(cIniFile & a_SettingsIni);
+ void Start(cIniFile & a_SettingsIni, bool a_ShouldAuth);
/** Connects to the specified server using SSL, sends the given request and receives the response.
Checks Mojang certificates using the hard-coded Starfield root CA certificate.
@@ -93,6 +93,10 @@ public:
void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; }
protected:
+ /** The thread that periodically checks for stale data and re-queries it from the server. */
+ class cUpdateThread;
+
+
/** Holds data for a single player profile. */
struct sProfile
{
@@ -177,6 +181,9 @@ protected:
/** Protects m_RankMgr agains simultaneous multi-threaded access. */
cCriticalSection m_CSRankMgr;
+
+ /** The thread that periodically updates the stale data in the DB from the Mojang servers. */
+ SharedPtr<cUpdateThread> m_UpdateThread;
/** Loads the caches from a disk storage. */
@@ -189,15 +196,29 @@ protected:
Names that are not valid are not added into the cache.
ASSUMEs that a_PlayerNames contains lowercased player names. */
void CacheNamesToUUIDs(const AStringVector & a_PlayerNames);
+
+ /** Queries all the specified names and stores them into the m_PlayerNameToUUID cache.
+ Names that are not valid are not added into the cache.
+ ASSUMEs that a_PlayerNames contans lowercased player names.
+ For performance reasons takes a non-const reference and modifies the list given to it, until empty. */
+ 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);
+ /** 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);
+
/** 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);
+
+ /** Updates the stale values in the DB from the Mojang servers. Called from the cUpdateThread, blocks on the HTTPS API calls. */
+ void Update(void);
} ; // tolua_export
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 7225f663d..02a8a52f6 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -130,7 +130,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) = 0;
virtual void SendWindowClose (const cWindow & a_Window) = 0;
virtual void SendWindowOpen (const cWindow & a_Window) = 0;
- virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) = 0;
+ virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) = 0;
/// Returns the ServerID used for authentication through session.minecraft.net
virtual AString GetAuthServerID(void) = 0;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 494413f63..9c3bac128 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1439,7 +1439,7 @@ void cProtocol172::SendWindowOpen(const cWindow & a_Window)
-void cProtocol172::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value)
+void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value)
{
ASSERT(m_State == 3); // In game mode?
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 7709df59d..f939bfb5e 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -134,7 +134,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override;
virtual void SendWindowOpen (const cWindow & a_Window) override;
- virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override;
+ virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override;
virtual AString GetAuthServerID(void) override { return m_AuthServerID; }
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index f37409744..b6f0618c0 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -1500,7 +1500,7 @@ void cProtocol180::SendWindowOpen(const cWindow & a_Window)
-void cProtocol180::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value)
+void cProtocol180::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value)
{
ASSERT(m_State == 3); // In game mode?
diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h
index 8c0b77a21..92d9825ef 100644
--- a/src/Protocol/Protocol18x.h
+++ b/src/Protocol/Protocol18x.h
@@ -133,7 +133,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override;
virtual void SendWindowOpen (const cWindow & a_Window) override;
- virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override;
+ virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override;
virtual AString GetAuthServerID(void) override { return m_AuthServerID; }
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 15bcd03b1..0c1e83b67 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -350,7 +350,7 @@ void cProtocolRecognizer::SendHealth(void)
-void cProtocolRecognizer::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value)
+void cProtocolRecognizer::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value)
{
ASSERT(m_Protocol != NULL);
m_Protocol->SendWindowProperty(a_Window, a_Property, a_Value);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index b42cfdec2..dcf653e75 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -121,7 +121,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override;
virtual void SendWindowOpen (const cWindow & a_Window) override;
- virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override;
+ virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override;
virtual AString GetAuthServerID(void) override;