diff options
Diffstat (limited to 'src/Core')
| -rw-r--r-- | src/Core/CoreObject/coreobject.cpp | 5 | ||||
| -rw-r--r-- | src/Core/CoreObject/coreobject.h | 30 | ||||
| -rw-r--r-- | src/Core/CoreObject/serverinfostructure.h | 31 | ||||
| -rw-r--r-- | src/Core/GameInfo/gameinfostructure.h | 24 | ||||
| -rw-r--r-- | src/Core/GameInfo/loadsupportedgames.cpp | 97 | ||||
| -rw-r--r-- | src/Core/GameInfo/loadsupportedgames.h | 16 | ||||
| -rw-r--r-- | src/Core/core.cpp | 15 | ||||
| -rw-r--r-- | src/Core/core.h | 43 | ||||
| -rw-r--r-- | src/Core/corerun.cpp | 75 | ||||
| -rw-r--r-- | src/Core/version.h | 43 |
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 |
