diff --git a/cmake/NSIS.template.in b/cmake/NSIS.template.in index 5a931e19..093d6caa 100644 --- a/cmake/NSIS.template.in +++ b/cmake/NSIS.template.in @@ -75,12 +75,15 @@ Section Uninstall Delete "$INSTDIR\uninstall.exe" Delete "$INSTDIR\cockatrice.exe" Delete "$INSTDIR\oracle.exe" + Delete "$INSTDIR\servatrice.exe" Delete "$INSTDIR\Usermanual.pdf" Delete "$INSTDIR\libprotobuf.lib" Delete "$INSTDIR\Qt*.dll" Delete "$INSTDIR\icu*.dll" Delete "$INSTDIR\qt.conf" Delete "$INSTDIR\qdebug.txt" + Delete "$INSTDIR\servatrice.sql" + Delete "$INSTDIR\servatrice.ini.example" RMDir "$INSTDIR" RMDir "$SMPROGRAMS\Cockatrice" diff --git a/servatrice/CMakeLists.txt b/servatrice/CMakeLists.txt index 224e10d2..7bdf4721 100644 --- a/servatrice/CMakeLists.txt +++ b/servatrice/CMakeLists.txt @@ -12,6 +12,7 @@ SET(servatrice_SOURCES src/servatrice_database_interface.cpp src/server_logger.cpp src/serversocketinterface.cpp + src/settingscache.cpp src/isl_interface.cpp ${VERSION_STRING_CPP} ) diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index d90e0634..49b06b27 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -20,13 +20,14 @@ #include #include +#include #include #include -#include #include #include "passwordhasher.h" #include "servatrice.h" #include "server_logger.h" +#include "settingscache.h" #include "rng_sfmt.h" #include "version_string.h" #include @@ -37,6 +38,7 @@ RNG_Abstract *rng; ServerLogger *logger; QThread *loggerThread; +SettingsCache *settingsCache; /* Prototypes */ @@ -150,6 +152,10 @@ int main(int argc, char *argv[]) bool testRandom = args.contains("--test-random"); bool testHashFunction = args.contains("--test-hash"); bool logToConsole = args.contains("--log-to-console"); + QString configPath; + int hasConfigPath=args.indexOf("--config"); + if(hasConfigPath > -1 && args.count() > hasConfigPath + 1) + configPath = args.at(hasConfigPath + 1); qRegisterMetaType >("QList"); @@ -158,7 +164,9 @@ int main(int argc, char *argv[]) QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); #endif - QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); + configPath = SettingsCache::guessConfigurationPath(configPath); + qWarning() << "Using configuration file: " << configPath; + settingsCache = new SettingsCache(); loggerThread = new QThread; loggerThread->setObjectName("logger"); @@ -166,7 +174,7 @@ int main(int argc, char *argv[]) logger->moveToThread(loggerThread); loggerThread->start(); - QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settings->value("server/logfile").toString())); + QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settingsCache->value("server/logfile", QString("server.log")).toString())); #if QT_VERSION < 0x050000 if (logToConsole) @@ -209,7 +217,7 @@ int main(int argc, char *argv[]) if (testHashFunction) testHash(); - Servatrice *server = new Servatrice(settings); + Servatrice *server = new Servatrice(); QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection); int retval = 0; if (server->initServer()) { @@ -228,7 +236,7 @@ int main(int argc, char *argv[]) } delete rng; - delete settings; + delete settingsCache; logger->deleteLater(); loggerThread->wait(); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 4c9b4a06..c4590f5b 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -18,7 +18,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include -#include #include #include #include @@ -28,6 +27,7 @@ #include "servatrice_database_interface.h" #include "servatrice_connection_pool.h" #include "server_room.h" +#include "settingscache.h" #include "serversocketinterface.h" #include "isl_interface.h" #include "server_logger.h" @@ -120,8 +120,8 @@ void Servatrice_IslServer::incomingConnection(int socketDescriptor) QMetaObject::invokeMethod(interface, "initServer", Qt::QueuedConnection); } -Servatrice::Servatrice(QSettings *_settings, QObject *parent) - : Server(true, parent), settings(_settings), uptime(0), shutdownTimer(0) +Servatrice::Servatrice(QObject *parent) + : Server(true, parent), uptime(0), shutdownTimer(0) { qRegisterMetaType("QSqlDatabase"); } @@ -134,11 +134,11 @@ Servatrice::~Servatrice() bool Servatrice::initServer() { - serverName = settings->value("server/name").toString(); - serverId = settings->value("server/id", 0).toInt(); - bool regServerOnly = settings->value("server/regonly", 0).toBool(); + serverName = settingsCache->value("server/name", "My Cockatrice server").toString(); + serverId = settingsCache->value("server/id", 0).toInt(); + bool regServerOnly = settingsCache->value("server/regonly", 0).toBool(); - const QString authenticationMethodStr = settings->value("authentication/method").toString(); + const QString authenticationMethodStr = settingsCache->value("authentication/method").toString(); if (authenticationMethodStr == "sql") { authenticationMethod = AuthenticationSql; } else { @@ -149,7 +149,7 @@ bool Servatrice::initServer() authenticationMethod = AuthenticationNone; } - QString dbTypeStr = settings->value("database/type").toString(); + QString dbTypeStr = settingsCache->value("database/type").toString(); if (dbTypeStr == "mysql") databaseType = DatabaseMySql; else @@ -159,14 +159,14 @@ bool Servatrice::initServer() setDatabaseInterface(servatriceDatabaseInterface); if (databaseType != DatabaseNone) { - settings->beginGroup("database"); - dbPrefix = settings->value("prefix").toString(); + settingsCache->beginGroup("database"); + dbPrefix = settingsCache->value("prefix").toString(); servatriceDatabaseInterface->initDatabase("QMYSQL", - settings->value("hostname").toString(), - settings->value("database").toString(), - settings->value("user").toString(), - settings->value("password").toString()); - settings->endGroup(); + settingsCache->value("hostname").toString(), + settingsCache->value("database").toString(), + settingsCache->value("user").toString(), + settingsCache->value("password").toString()); + settingsCache->endGroup(); updateServerList(); @@ -174,7 +174,7 @@ bool Servatrice::initServer() servatriceDatabaseInterface->clearSessionTables(); } - const QString roomMethod = settings->value("rooms/method").toString(); + const QString roomMethod = settingsCache->value("rooms/method").toString(); if (roomMethod == "sql") { QSqlQuery query(servatriceDatabaseInterface->getDatabase()); query.prepare("select id, name, descr, auto_join, join_message from " + dbPrefix + "_rooms order by id asc"); @@ -198,47 +198,63 @@ bool Servatrice::initServer() )); } } else { - int size = settings->beginReadArray("rooms/roomlist"); + int size = settingsCache->beginReadArray("rooms/roomlist"); for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); + settingsCache->setArrayIndex(i); QStringList gameTypes; - int size2 = settings->beginReadArray("game_types"); + int size2 = settingsCache->beginReadArray("game_types"); for (int j = 0; j < size2; ++j) { - settings->setArrayIndex(j); - gameTypes.append(settings->value("name").toString()); + settingsCache->setArrayIndex(j); + gameTypes.append(settingsCache->value("name").toString()); } - settings->endArray(); + settingsCache->endArray(); Server_Room *newRoom = new Server_Room( i, - settings->value("name").toString(), - settings->value("description").toString(), - settings->value("autojoin").toBool(), - settings->value("joinmessage").toString(), + settingsCache->value("name").toString(), + settingsCache->value("description").toString(), + settingsCache->value("autojoin").toBool(), + settingsCache->value("joinmessage").toString(), gameTypes, this ); addRoom(newRoom); } - settings->endArray(); + + if(size==0) + { + // no room defined in config, add a dummy one + Server_Room *newRoom = new Server_Room( + 0, + "General room", + "Play anything here.", + true, + "", + QStringList("Standard"), + this + ); + addRoom(newRoom); + } + + settingsCache->endArray(); } updateLoginMessage(); - maxGameInactivityTime = settings->value("game/max_game_inactivity_time").toInt(); - maxPlayerInactivityTime = settings->value("game/max_player_inactivity_time").toInt(); + maxGameInactivityTime = settingsCache->value("game/max_game_inactivity_time", 120).toInt(); + maxPlayerInactivityTime = settingsCache->value("game/max_player_inactivity_time", 15).toInt(); - maxUsersPerAddress = settings->value("security/max_users_per_address").toInt(); - messageCountingInterval = settings->value("security/message_counting_interval").toInt(); - maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt(); - maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt(); - maxGamesPerUser = settings->value("security/max_games_per_user").toInt(); + maxUsersPerAddress = settingsCache->value("security/max_users_per_address", 4).toInt(); + messageCountingInterval = settingsCache->value("security/message_counting_interval", 10).toInt(); + maxMessageCountPerInterval = settingsCache->value("security/max_message_count_per_interval", 10).toInt(); + maxMessageSizePerInterval = settingsCache->value("security/max_message_size_per_interval", 1000).toInt(); + maxGamesPerUser = settingsCache->value("security/max_games_per_user", 5).toInt(); - try { if (settings->value("servernetwork/active", 0).toInt()) { + try { if (settingsCache->value("servernetwork/active", 0).toInt()) { qDebug() << "Connecting to ISL network."; - const QString certFileName = settings->value("servernetwork/ssl_cert").toString(); - const QString keyFileName = settings->value("servernetwork/ssl_key").toString(); + const QString certFileName = settingsCache->value("servernetwork/ssl_cert").toString(); + const QString keyFileName = settingsCache->value("servernetwork/ssl_key").toString(); qDebug() << "Loading certificate..."; QFile certFile(certFileName); if (!certFile.open(QIODevice::ReadOnly)) @@ -282,7 +298,7 @@ bool Servatrice::initServer() QMetaObject::invokeMethod(interface, "initClient", Qt::BlockingQueuedConnection); } - const int networkPort = settings->value("servernetwork/port", 14747).toInt(); + const int networkPort = settingsCache->value("servernetwork/port", 14747).toInt(); qDebug() << "Starting ISL server on port" << networkPort; islServer = new Servatrice_IslServer(this, cert, key, this); @@ -299,7 +315,7 @@ bool Servatrice::initServer() connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); pingClock->start(1000); - int statusUpdateTime = settings->value("server/statusupdate").toInt(); + int statusUpdateTime = settingsCache->value("server/statusupdate", 15000).toInt(); statusUpdateClock = new QTimer(this); connect(statusUpdateClock, SIGNAL(timeout()), this, SLOT(statusUpdate())); if (statusUpdateTime != 0) { @@ -307,10 +323,10 @@ bool Servatrice::initServer() statusUpdateClock->start(statusUpdateTime); } - const int numberPools = settings->value("server/number_pools", 1).toInt(); + const int numberPools = settingsCache->value("server/number_pools", 1).toInt(); gameServer = new Servatrice_GameServer(this, numberPools, servatriceDatabaseInterface->getDatabase(), this); gameServer->setMaxPendingConnections(1000); - const int gamePort = settings->value("server/port", 4747).toInt(); + const int gamePort = settingsCache->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << gamePort; if (gameServer->listen(QHostAddress::Any, gamePort)) qDebug() << "Server listening."; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 2b991512..86c36a5c 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -32,7 +32,6 @@ Q_DECLARE_METATYPE(QSqlDatabase) -class QSettings; class QSqlQuery; class QTimer; @@ -106,7 +105,6 @@ private: mutable QMutex loginMessageMutex; QString loginMessage; QString dbPrefix; - QSettings *settings; Servatrice_DatabaseInterface *servatriceDatabaseInterface; int serverId; int uptime; @@ -128,7 +126,7 @@ public slots: void scheduleShutdown(const QString &reason, int minutes); void updateLoginMessage(); public: - Servatrice(QSettings *_settings, QObject *parent = 0); + Servatrice(QObject *parent = 0); ~Servatrice(); bool initServer(); QString getServerName() const { return serverName; } diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index a3e92aff..1a1e4bed 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -1,9 +1,9 @@ #include "server_logger.h" +#include "settingscache.h" #include #include #include #include -#include #include #ifdef Q_OS_UNIX # include @@ -26,7 +26,7 @@ ServerLogger::~ServerLogger() void ServerLogger::startLog(const QString &logFileName) { if (!logFileName.isEmpty()) { - logFile = new QFile("server.log", this); + logFile = new QFile(logFileName, this); logFile->open(QIODevice::Append); #ifdef Q_OS_UNIX ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); @@ -50,9 +50,8 @@ void ServerLogger::logMessage(QString message, void *caller) callerString = QString::number((qulonglong) caller, 16) + " "; //filter out all log entries based on values in configuration file - QSettings settings("servatrice.ini", QSettings::IniFormat); - bool shouldWeWriteLog = settings.value("server/writelog").toBool(); - QString logFilters = settings.value("server/logfilters").toString(); + bool shouldWeWriteLog = settingsCache->value("server/writelog").toBool(); + QString logFilters = settingsCache->value("server/logfilters").toString(); QStringList listlogFilters = logFilters.split(",", QString::SkipEmptyParts); bool shouldWeSkipLine = false; diff --git a/servatrice/src/settingscache.cpp b/servatrice/src/settingscache.cpp new file mode 100644 index 00000000..10984dd6 --- /dev/null +++ b/servatrice/src/settingscache.cpp @@ -0,0 +1,37 @@ +#include "settingscache.h" +#include +#include +#if QT_VERSION >= 0x050000 + #include +#else + #include +#endif + +QString SettingsCache::guessConfigurationPath(QString & specificPath) +{ + const QString fileName="servatrice.ini"; + QString guessFileName; + + // specific path + if(!specificPath.isEmpty() && QFile::exists(specificPath)) + return specificPath; + + // application directory path + guessFileName = QCoreApplication::applicationDirPath() + "/" + fileName; + if(QFile::exists(guessFileName)) + return guessFileName; + +#ifdef Q_OS_UNIX + // /etc + guessFileName = "/etc/servatrice/" + fileName; + if(QFile::exists(guessFileName)) + return guessFileName; +#endif + +#if QT_VERSION >= 0x050000 + guessFileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + fileName; +#else + guessFileName = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/" + fileName; +#endif + return guessFileName; +} \ No newline at end of file diff --git a/servatrice/src/settingscache.h b/servatrice/src/settingscache.h new file mode 100644 index 00000000..945ab71f --- /dev/null +++ b/servatrice/src/settingscache.h @@ -0,0 +1,18 @@ +#ifndef SERVATRICE_SETTINGSCACHE_H +#define SERVATRICE_SETTINGSCACHE_H + +#include +#include + +class SettingsCache : public QSettings { + Q_OBJECT +private: + QSettings *settings; +public: + SettingsCache(const QString & fileName="servatrice.ini", QSettings::Format format=QSettings::IniFormat, QObject * parent = 0) { }; + static QString guessConfigurationPath(QString & specificPath); +}; + +extern SettingsCache *settingsCache; + +#endif