aboutsummaryrefslogtreecommitdiff
path: root/src/Core
diff options
context:
space:
mode:
authorDark1-dev <shansarkar272@gmail.com>2023-03-01 21:32:53 +0600
committerGitHub <noreply@github.com>2023-03-01 21:32:53 +0600
commitde57bc38217c09a0ae4a143f631896652368ecc3 (patch)
tree635e3f429a5a6e00744b6817533615e41c6db5e2 /src/Core
parent60a301a93b6057bb2c54ac04a7c38c38389037b3 (diff)
downloadMasterserver-Qt5-de57bc38217c09a0ae4a143f631896652368ecc3.tar.gz
Masterserver-Qt5-de57bc38217c09a0ae4a143f631896652368ecc3.zip
Add files via upload
Diffstat (limited to 'src/Core')
-rw-r--r--src/Core/CoreObject/coreobject.cpp5
-rw-r--r--src/Core/CoreObject/coreobject.h30
-rw-r--r--src/Core/CoreObject/serverinfostructure.h31
-rw-r--r--src/Core/GameInfo/gameinfostructure.h24
-rw-r--r--src/Core/GameInfo/loadsupportedgames.cpp97
-rw-r--r--src/Core/GameInfo/loadsupportedgames.h16
-rw-r--r--src/Core/core.cpp15
-rw-r--r--src/Core/core.h43
-rw-r--r--src/Core/corerun.cpp75
-rw-r--r--src/Core/version.h43
10 files changed, 379 insertions, 0 deletions
diff --git a/src/Core/CoreObject/coreobject.cpp b/src/Core/CoreObject/coreobject.cpp
new file mode 100644
index 0000000..11d1ab6
--- /dev/null
+++ b/src/Core/CoreObject/coreobject.cpp
@@ -0,0 +1,5 @@
+#include "coreobject.h"
+
+CoreObject::CoreObject()
+{
+}
diff --git a/src/Core/CoreObject/coreobject.h b/src/Core/CoreObject/coreobject.h
new file mode 100644
index 0000000..91bd33b
--- /dev/null
+++ b/src/Core/CoreObject/coreobject.h
@@ -0,0 +1,30 @@
+#ifndef COREOBJECT_H
+#define COREOBJECT_H
+
+#include "Core/CoreObject/serverinfostructure.h"
+#include "Core/GameInfo/gameinfostructure.h"
+#include "Logger/logger.h"
+#include "Settings/settingstructure.h"
+
+class CoreObject
+{
+public:
+ CoreObject();
+
+ // struct with internal and external settings
+ SettingStructure Settings;
+
+ // list of game details: gamename, cipher
+ QHash<QString, GameInfo> SupportedGames;
+
+ // logging functions
+ Logger Log;
+
+ // server address list acquired through third party masterservers
+ QList<ServerInfo> PendingServers;
+
+ // generate our session/identification string, to prevent self-syncing
+ QString masterserverIdentity; // msid value
+};
+
+#endif // COREOBJECT_H
diff --git a/src/Core/CoreObject/serverinfostructure.h b/src/Core/CoreObject/serverinfostructure.h
new file mode 100644
index 0000000..4f86adb
--- /dev/null
+++ b/src/Core/CoreObject/serverinfostructure.h
@@ -0,0 +1,31 @@
+#ifndef SERVERINFOSTRUCTURE_H
+#define SERVERINFOSTRUCTURE_H
+
+#include <QDateTime>
+#include <QHostAddress>
+
+struct ServerInfo
+{
+ // server address
+ QHostAddress ip;
+
+ // server port
+ unsigned short port = 0;
+
+ // gamename
+ QString gamename = "";
+
+ // date that the serverinfo was added or last updated
+ qint64 time = QDateTime::currentSecsSinceEpoch();
+};
+
+// compare operator
+inline bool operator== (const ServerInfo serverInfo1, const ServerInfo serverInfo2)
+{
+ // compare address, port and gamename. ignore time.
+ return ( serverInfo1.ip.isEqual(serverInfo2.ip) and
+ serverInfo1.port == serverInfo2.port and
+ serverInfo1.gamename == serverInfo2.gamename );
+}
+
+#endif // SERVERINFOSTRUCTURE_H
diff --git a/src/Core/GameInfo/gameinfostructure.h b/src/Core/GameInfo/gameinfostructure.h
new file mode 100644
index 0000000..b73e9ef
--- /dev/null
+++ b/src/Core/GameInfo/gameinfostructure.h
@@ -0,0 +1,24 @@
+#ifndef STRUCTGAMEINFO_H
+#define STRUCTGAMEINFO_H
+
+#include <QString>
+
+struct GameInfo
+{
+ // gamename is the unique identifier
+ QString gamename;
+
+ // 6-byte GameSpy identifier
+ QString cipher;
+
+ // game label
+ QString label;
+
+ // default port
+ unsigned short port = 0;
+
+ // known protocol
+ QString protocol;
+};
+
+#endif // STRUCTGAMEINFO_H
diff --git a/src/Core/GameInfo/loadsupportedgames.cpp b/src/Core/GameInfo/loadsupportedgames.cpp
new file mode 100644
index 0000000..9a73947
--- /dev/null
+++ b/src/Core/GameInfo/loadsupportedgames.cpp
@@ -0,0 +1,97 @@
+#include "loadsupportedgames.h"
+
+QHash<QString, GameInfo> loadSupportedGames (const QString &applicationPath)
+{
+ // return hash
+ QHash<QString, GameInfo> supportedGames;
+
+ // supported games file path (following README structure)
+ const QString supportPath = applicationPath + "/" + _supportedPath;
+
+ // determine if file exists
+ if ( ! QFile(supportPath).exists() )
+ {
+ // no game info file exists
+ logPrimitive() << "No games file found at " << supportPath << endl
+ << "Please provide the correct file . " << endl;
+ return supportedGames;
+ }
+
+ // load config file
+ QFile supportedFile(supportPath);
+ if ( ! supportedFile.open(QIODevice::ReadOnly) )
+ {
+ // error occurred. report and quit.
+ logPrimitive() << "Unable to open the game file. Is the file open or in use?" << endl;
+ return supportedGames;
+ }
+
+ // stats
+ int total = 0;
+
+ // load as json object
+ QJsonDocument supportedJsonData(QJsonDocument::fromJson(supportedFile.readAll()));
+
+ /* Optimisation for web interface: add games to the database.
+ *
+ * If database/json data do not match, replace database table
+ * with json data. This should only occur during database creation
+ * or when manual changes were made to the json file (which is rare).
+ */
+ bool dbInsert = supportedJsonData.array().count() != getNumGames(0).value("numTotal", 0);
+ QSqlQuery q;
+ if (dbInsert)
+ {
+ // no game info file exists
+ logPrimitive() << "Game info mismatch in database. Reloading json data. ("
+ << supportedJsonData.array().count() << "/"
+ << getNumGames(0).value("numTotal", 0) << ")" << endl;
+
+ // void existing data
+ q.prepare("DELETE FROM gameinfo");
+ if ( ! q.exec() )
+ reportQuery(q);
+ }
+
+ for (int i = 0; i < supportedJsonData.array().count(); i++)
+ {
+ // get the game object
+ QJsonObject thisGame = supportedJsonData.array().at(i).toObject();
+
+ GameInfo gameInfo;
+ gameInfo.gamename = thisGame.value("gamename").toString("");
+ gameInfo.cipher = thisGame.value("cipher").toString("");
+ gameInfo.port = static_cast<unsigned short>(thisGame.value("port").toDouble(0));
+ gameInfo.label = thisGame.value("label").toString("");
+
+ // insert in db if needed
+ if (dbInsert)
+ {
+ QString insertString = "INSERT INTO gameinfo (gamename, label) "
+ "VALUES (:gamename, :label)";
+
+ q.prepare(insertString);
+ q.bindValue(":gamename", gameInfo.gamename );
+ q.bindValue(":label", gameInfo.label);
+
+ if ( ! q.exec() )
+ reportQuery(q);
+ }
+
+ // add to list
+ supportedGames.insert(gameInfo.gamename, gameInfo);
+ total++;
+ }
+
+ // no games found? report this!
+ if (total <= 0)
+ {
+ // no game info exists
+ logPrimitive() << "No game info found in file at " << supportPath << endl
+ << "Please provide the correct file . " << endl;
+ return supportedGames;
+ }
+
+ // all games parsed. done.
+ return supportedGames;
+}
diff --git a/src/Core/GameInfo/loadsupportedgames.h b/src/Core/GameInfo/loadsupportedgames.h
new file mode 100644
index 0000000..333dd0b
--- /dev/null
+++ b/src/Core/GameInfo/loadsupportedgames.h
@@ -0,0 +1,16 @@
+#ifndef LOADSUPPORTEDGAMES_H
+#define LOADSUPPORTEDGAMES_H
+
+#include <QFile>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include "Database/Common/commonactions.h"
+#include "gameinfostructure.h"
+
+// load supported games from json file
+
+const QString _supportedPath = "../data/SupportedGames.json";
+QHash<QString, GameInfo> loadSupportedGames (const QString &applicationPath);
+
+#endif // LOADSUPPORTEDGAMES_H
diff --git a/src/Core/core.cpp b/src/Core/core.cpp
new file mode 100644
index 0000000..04c7e53
--- /dev/null
+++ b/src/Core/core.cpp
@@ -0,0 +1,15 @@
+#include "core.h"
+
+Core::Core(QString applicationPath)
+{
+ _applicationPath = applicationPath;
+}
+
+// TODO
+void Core::shutdown()
+{
+ logPrimitive() << "[stop] quitting masterserver application" << endl;
+
+ // end application
+ exit(0);
+}
diff --git a/src/Core/core.h b/src/Core/core.h
new file mode 100644
index 0000000..bde3a04
--- /dev/null
+++ b/src/Core/core.h
@@ -0,0 +1,43 @@
+#ifndef CORE_H
+#define CORE_H
+
+#include "Core/CoreObject/coreobject.h"
+#include "Core/GameInfo/loadsupportedgames.h"
+#include "Core/version.h"
+#include "Database/databaseinterface.h"
+#include "Settings/loadsettings.h"
+#include "Maintenance/maintenance.h"
+#include "Protocols/GameSpy0/securevalidate.h"
+#include "UdpTasks/BeaconServer/beaconserver.h"
+#include "UdpTasks/StatusChecker/statuschecker.h"
+#include "TcpTasks/ListenServer/listenserver.h"
+#include "TcpTasks/Updater/syncupdater.h"
+
+class Core : public QObject
+{
+ Q_OBJECT
+public:
+ Core(QString applicationPath);
+ void run();
+ void shutdown();
+
+private:
+ // root path
+ QString _applicationPath = "";
+
+ // internal dataobject
+ QSharedPointer<CoreObject> _coreObject = QSharedPointer<CoreObject>(new CoreObject);
+
+ // Networking services
+ QSharedPointer<BeaconServer> _udpBeaconServer = QSharedPointer<BeaconServer>(new BeaconServer(_coreObject));
+ QSharedPointer<ListenServer> _tcpListenServer = QSharedPointer<ListenServer>(new ListenServer(_coreObject));
+
+ // Updaters
+ QSharedPointer<SyncUpdater> _syncUpdater = QSharedPointer<SyncUpdater> (new SyncUpdater (_coreObject));
+ QSharedPointer<StatusChecker> _statusChecker = QSharedPointer<StatusChecker>(new StatusChecker(_coreObject));
+
+ // Maintenance
+ QSharedPointer<Maintenance> _maintenance = QSharedPointer<Maintenance>(new Maintenance(_coreObject));
+};
+
+#endif // CORE_H
diff --git a/src/Core/corerun.cpp b/src/Core/corerun.cpp
new file mode 100644
index 0000000..c978026
--- /dev/null
+++ b/src/Core/corerun.cpp
@@ -0,0 +1,75 @@
+#include "core.h"
+
+void Core::run()
+{
+ // randomize
+ qsrand(static_cast<unsigned int>(QDateTime::currentMSecsSinceEpoch()));
+
+ // announce startup
+ logPrimitive() << "*** Starting 333networks Master Server v" << BUILD_VERSION << " ***" << endl;
+
+ // can not set file paths
+ if (_applicationPath.length() <= 0)
+ this->shutdown();
+
+ // debug info (hardcoded disable for releases)
+ if ( false )
+ logPrimitive() << "Using Qt " << qVersion() << endl;
+
+ // set our own 12-byte identifier
+ _coreObject->masterserverIdentity = genChallengeString(12, true);
+
+ // load config settings from file
+ _coreObject->Settings = loadSettings(_applicationPath);
+ if ( ! _coreObject->Settings.init )
+ this->shutdown();
+
+ // initialise database
+ if ( ! initDatabase(_applicationPath) )
+ this->shutdown();
+
+ // load game info from file and into database
+ _coreObject->SupportedGames = loadSupportedGames(_applicationPath);
+ if ( _coreObject->SupportedGames.count() <= 0 )
+ this->shutdown();
+
+ // logger init
+ if ( ! _coreObject->Log.init(_applicationPath, _coreObject->Settings) )
+ this->shutdown();
+
+ /*
+ * enter runmode
+ */
+
+ // udp beacon server
+ if ( ! _udpBeaconServer->listen() )
+ this->shutdown();
+
+ // tcp listen server
+ if ( ! _tcpListenServer->listen() )
+ this->shutdown();
+
+ /*
+ * advanced functionality
+ */
+
+ // maintenance and statistics
+ if ( _coreObject->Settings.MaintenanceSettings.doMaintenance )
+ _maintenance->scheduleMaintenance();
+
+ // udp uplink broadcast every X minutes
+ if ( _coreObject->Settings.BeaconServerSettings.doUplink )
+ _udpBeaconServer->uplink();
+
+ // syncing with other masterservers
+ if ( _coreObject->Settings.SyncerSettings.doSync )
+ _syncUpdater->scheduleUpdater();
+
+ // server checker
+ if ( _coreObject->Settings.CheckerSettings.doCheck )
+ _statusChecker->startTicker();
+
+ /*
+ * all services running
+ */
+}
diff --git a/src/Core/version.h b/src/Core/version.h
new file mode 100644
index 0000000..6dbc808
--- /dev/null
+++ b/src/Core/version.h
@@ -0,0 +1,43 @@
+#ifndef VERSION_H
+#define VERSION_H
+
+#include <QString>
+
+/*
+ * Version and author information
+ *
+ * Only when you make (significant) modifications to the master server source
+ * code, you should edit these variables to reflect your changes.
+ *
+ * For example,
+ * if you limit functionality to only one game, you should change the variable
+ * BUILD_TYPE and SHORT_VER to something that reflects the change in function.
+ *
+ * In addition, if you have the actual interest to go through all this source
+ * code to end up here, consider sending Darkelarious (the original author) a
+ * postcard or (e)mail with your compliments. Or buy us a coffee. We like the
+ * appreciation.
+ */
+
+// gamename for the 333networks-type MasterServer
+#define TYPE_GAMENAME QString("333networks")
+
+// build type: type of software
+#define BUILD_TYPE QString("MasterServer Qt5")
+
+// software version (of this particular type)
+#define BUILD_VERSION QString("0.27")
+
+// short version (in query) -- Qt v0.n
+#define SHORT_VER QString("Qt-" + BUILD_VERSION)
+
+// build time/date
+#define BUILD_TIME QStringLiteral("%1 %2").arg(__DATE__).arg(__TIME__)
+
+// software author, contact
+#define BUILD_AUTHOR QString("Darkelarious <darkelarious@333networks.com>")
+
+// minimum required database version
+#define DATABASE_VERSION 0.27
+
+#endif // VERSION_H