improved logging, improved server multithreading
This commit is contained in:
parent
8edc5b0635
commit
fd7593edc1
11 changed files with 128 additions and 31 deletions
|
@ -353,6 +353,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC
|
||||||
return RespNameNotFound;
|
return RespNameNotFound;
|
||||||
|
|
||||||
r->addClient(this);
|
r->addClient(this);
|
||||||
|
connect(r, SIGNAL(gameCreated(Server_Game *)), this, SLOT(gameCreated(Server_Game *)));
|
||||||
rooms.insert(r->getId(), r);
|
rooms.insert(r->getId(), r);
|
||||||
|
|
||||||
enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage()));
|
enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage()));
|
||||||
|
@ -420,13 +421,17 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm
|
||||||
for (int i = 0; i < gameTypeList.size(); ++i)
|
for (int i = 0; i < gameTypeList.size(); ++i)
|
||||||
gameTypes.append(gameTypeList[i]->getData());
|
gameTypes.append(gameTypeList[i]->getData());
|
||||||
|
|
||||||
Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this);
|
room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this);
|
||||||
|
return RespOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server_ProtocolHandler::gameCreated(Server_Game *game)
|
||||||
|
{
|
||||||
Server_Player *creator = game->getPlayers().values().first();
|
Server_Player *creator = game->getPlayers().values().first();
|
||||||
games.insert(game->getGameId(), QPair<Server_Game *, Server_Player *>(game, creator));
|
games.insert(game->getGameId(), QPair<Server_Game *, Server_Player *>(game, creator));
|
||||||
|
|
||||||
enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false));
|
sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false));
|
||||||
enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId()));
|
sendProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId()));
|
||||||
return RespOk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandContainer * /*cont*/, Server_Room *room)
|
ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandContainer * /*cont*/, Server_Room *room)
|
||||||
|
|
|
@ -91,6 +91,7 @@ private:
|
||||||
ResponseCode processCommandHelper(Command *command, CommandContainer *cont);
|
ResponseCode processCommandHelper(Command *command, CommandContainer *cont);
|
||||||
private slots:
|
private slots:
|
||||||
void pingClockTimeout();
|
void pingClockTimeout();
|
||||||
|
void gameCreated(Server_Game *game);
|
||||||
public:
|
public:
|
||||||
Server_ProtocolHandler(Server *_server, QObject *parent = 0);
|
Server_ProtocolHandler(Server *_server, QObject *parent = 0);
|
||||||
~Server_ProtocolHandler();
|
~Server_ProtocolHandler();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent)
|
Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent)
|
||||||
: QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes)
|
: QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes)
|
||||||
{
|
{
|
||||||
|
connect(this, SIGNAL(sigCreateGame(const QString &, const QString &, int, const QList<int> &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *)), this, SLOT(doCreateGame(const QString &, const QString &, int, const QList<int> &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Server *Server_Room::getServer() const
|
Server *Server_Room::getServer() const
|
||||||
|
@ -68,7 +69,7 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game)
|
||||||
delete event;
|
delete event;
|
||||||
}
|
}
|
||||||
|
|
||||||
Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator)
|
void Server_Room::doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator)
|
||||||
{
|
{
|
||||||
Server_Game *newGame = new Server_Game(creator, static_cast<Server *>(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this);
|
Server_Game *newGame = new Server_Game(creator, static_cast<Server *>(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this);
|
||||||
games.insert(newGame->getGameId(), newGame);
|
games.insert(newGame->getGameId(), newGame);
|
||||||
|
@ -78,8 +79,11 @@ Server_Game *Server_Room::createGame(const QString &description, const QString &
|
||||||
|
|
||||||
emit gameCreated(newGame);
|
emit gameCreated(newGame);
|
||||||
emit roomInfoChanged();
|
emit roomInfoChanged();
|
||||||
|
}
|
||||||
return newGame;
|
|
||||||
|
void Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator)
|
||||||
|
{
|
||||||
|
emit sigCreateGame(description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server_Room::removeGame()
|
void Server_Room::removeGame()
|
||||||
|
|
|
@ -19,6 +19,8 @@ signals:
|
||||||
void roomInfoChanged();
|
void roomInfoChanged();
|
||||||
void gameCreated(Server_Game *game);
|
void gameCreated(Server_Game *game);
|
||||||
void gameClosing(int gameId);
|
void gameClosing(int gameId);
|
||||||
|
|
||||||
|
void sigCreateGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator);
|
||||||
private:
|
private:
|
||||||
int id;
|
int id;
|
||||||
QString name;
|
QString name;
|
||||||
|
@ -28,6 +30,7 @@ private:
|
||||||
QStringList gameTypes;
|
QStringList gameTypes;
|
||||||
QMap<int, Server_Game *> games;
|
QMap<int, Server_Game *> games;
|
||||||
private slots:
|
private slots:
|
||||||
|
void doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator);
|
||||||
void removeGame();
|
void removeGame();
|
||||||
public:
|
public:
|
||||||
Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent);
|
Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent);
|
||||||
|
@ -44,7 +47,7 @@ public:
|
||||||
void removeClient(Server_ProtocolHandler *client);
|
void removeClient(Server_ProtocolHandler *client);
|
||||||
void say(Server_ProtocolHandler *client, const QString &s);
|
void say(Server_ProtocolHandler *client, const QString &s);
|
||||||
void broadcastGameListUpdate(Server_Game *game);
|
void broadcastGameListUpdate(Server_Game *game);
|
||||||
Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator);
|
void createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator);
|
||||||
|
|
||||||
void sendRoomEvent(RoomEvent *event);
|
void sendRoomEvent(RoomEvent *event);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,7 @@ HEADERS += src/main.h \
|
||||||
src/servatrice.h \
|
src/servatrice.h \
|
||||||
src/serversocketinterface.h \
|
src/serversocketinterface.h \
|
||||||
src/server_logger.h \
|
src/server_logger.h \
|
||||||
|
src/serversocketthread.h \
|
||||||
../common/color.h \
|
../common/color.h \
|
||||||
../common/serializable_item.h \
|
../common/serializable_item.h \
|
||||||
../common/decklist.h \
|
../common/decklist.h \
|
||||||
|
@ -40,6 +41,7 @@ SOURCES += src/main.cpp \
|
||||||
src/servatrice.cpp \
|
src/servatrice.cpp \
|
||||||
src/serversocketinterface.cpp \
|
src/serversocketinterface.cpp \
|
||||||
src/server_logger.cpp \
|
src/server_logger.cpp \
|
||||||
|
src/serversocketthread.cpp \
|
||||||
../common/serializable_item.cpp \
|
../common/serializable_item.cpp \
|
||||||
../common/decklist.cpp \
|
../common/decklist.cpp \
|
||||||
../common/protocol.cpp \
|
../common/protocol.cpp \
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <QSettings>
|
||||||
#include "servatrice.h"
|
#include "servatrice.h"
|
||||||
#include "server_logger.h"
|
#include "server_logger.h"
|
||||||
#include "rng_sfmt.h"
|
#include "rng_sfmt.h"
|
||||||
|
@ -65,14 +67,27 @@ void testRNG()
|
||||||
std::cerr << std::endl << std::endl;
|
std::cerr << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void myMessageOutput(QtMsgType /*type*/, const char *msg)
|
||||||
|
{
|
||||||
|
logger->logMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
app.setOrganizationName("Cockatrice");
|
app.setOrganizationName("Cockatrice");
|
||||||
app.setApplicationName("Servatrice");
|
app.setApplicationName("Servatrice");
|
||||||
|
|
||||||
|
QStringList args = app.arguments();
|
||||||
|
bool testRandom = args.contains("--test-random");
|
||||||
|
|
||||||
|
qRegisterMetaType<QList<int> >("QList<int>");
|
||||||
|
|
||||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
logger = new ServerLogger;
|
|
||||||
|
QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat);
|
||||||
|
logger = new ServerLogger(settings->value("server/logfile").toString());
|
||||||
|
qInstallMsgHandler(myMessageOutput);
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
struct sigaction hup;
|
struct sigaction hup;
|
||||||
hup.sa_handler = ServerLogger::hupSignalHandler;
|
hup.sa_handler = ServerLogger::hupSignalHandler;
|
||||||
|
@ -85,10 +100,11 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
std::cerr << "Servatrice " << Servatrice::versionString.toStdString() << " starting." << std::endl;
|
std::cerr << "Servatrice " << Servatrice::versionString.toStdString() << " starting." << std::endl;
|
||||||
std::cerr << "-------------------------" << std::endl;
|
std::cerr << "-------------------------" << std::endl;
|
||||||
|
|
||||||
testRNG();
|
|
||||||
|
|
||||||
Servatrice server;
|
if (testRandom)
|
||||||
|
testRNG();
|
||||||
|
|
||||||
|
Servatrice server(settings);
|
||||||
|
|
||||||
std::cerr << "-------------------------" << std::endl;
|
std::cerr << "-------------------------" << std::endl;
|
||||||
std::cerr << "Server initialized." << std::endl;
|
std::cerr << "Server initialized." << std::endl;
|
||||||
|
@ -96,6 +112,7 @@ int main(int argc, char *argv[])
|
||||||
int retval = app.exec();
|
int retval = app.exec();
|
||||||
|
|
||||||
delete rng;
|
delete rng;
|
||||||
|
delete settings;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,18 @@
|
||||||
#include "servatrice.h"
|
#include "servatrice.h"
|
||||||
#include "server_room.h"
|
#include "server_room.h"
|
||||||
#include "serversocketinterface.h"
|
#include "serversocketinterface.h"
|
||||||
|
#include "serversocketthread.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
|
||||||
Servatrice::Servatrice(QObject *parent)
|
void Servatrice_TcpServer::incomingConnection(int socketDescriptor)
|
||||||
: Server(parent), uptime(0)
|
{
|
||||||
|
ServerSocketThread *sst = new ServerSocketThread(socketDescriptor, server, this);
|
||||||
|
connect(sst, SIGNAL(clientAdded(ServerSocketInterface *)), this, SIGNAL(clientAdded(ServerSocketInterface *)));
|
||||||
|
sst->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Servatrice::Servatrice(QSettings *_settings, QObject *parent)
|
||||||
|
: Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0)
|
||||||
{
|
{
|
||||||
pingClock = new QTimer(this);
|
pingClock = new QTimer(this);
|
||||||
connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout()));
|
connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout()));
|
||||||
|
@ -38,7 +46,6 @@ Servatrice::Servatrice(QObject *parent)
|
||||||
banTimeoutClock->start(60000);
|
banTimeoutClock->start(60000);
|
||||||
|
|
||||||
ProtocolItem::initializeHash();
|
ProtocolItem::initializeHash();
|
||||||
settings = new QSettings("servatrice.ini", QSettings::IniFormat, this);
|
|
||||||
|
|
||||||
int statusUpdateTime = settings->value("server/statusupdate").toInt();
|
int statusUpdateTime = settings->value("server/statusupdate").toInt();
|
||||||
statusUpdateClock = new QTimer(this);
|
statusUpdateClock = new QTimer(this);
|
||||||
|
@ -48,8 +55,8 @@ Servatrice::Servatrice(QObject *parent)
|
||||||
statusUpdateClock->start(statusUpdateTime);
|
statusUpdateClock->start(statusUpdateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpServer = new QTcpServer(this);
|
tcpServer = new Servatrice_TcpServer(this);
|
||||||
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
|
connect(tcpServer, SIGNAL(clientAdded(ServerSocketInterface *)), this, SLOT(newConnection(ServerSocketInterface *)));
|
||||||
int port = settings->value("server/port", 4747).toInt();
|
int port = settings->value("server/port", 4747).toInt();
|
||||||
qDebug() << "Starting server on port" << port;
|
qDebug() << "Starting server on port" << port;
|
||||||
tcpServer->listen(QHostAddress::Any, port);
|
tcpServer->listen(QHostAddress::Any, port);
|
||||||
|
@ -133,6 +140,7 @@ bool Servatrice::openDatabase()
|
||||||
|
|
||||||
void Servatrice::checkSql()
|
void Servatrice::checkSql()
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
if (!QSqlDatabase::database().exec("select 1").isActive())
|
if (!QSqlDatabase::database().exec("select 1").isActive())
|
||||||
openDatabase();
|
openDatabase();
|
||||||
}
|
}
|
||||||
|
@ -145,15 +153,14 @@ bool Servatrice::execSqlQuery(QSqlQuery &query)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servatrice::newConnection()
|
void Servatrice::newConnection(ServerSocketInterface *client)
|
||||||
{
|
{
|
||||||
QTcpSocket *socket = tcpServer->nextPendingConnection();
|
addClient(client);
|
||||||
ServerSocketInterface *ssi = new ServerSocketInterface(this, socket);
|
|
||||||
addClient(ssi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QString &password)
|
AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QString &password)
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
const QString method = settings->value("authentication/method").toString();
|
const QString method = settings->value("authentication/method").toString();
|
||||||
if (method == "none")
|
if (method == "none")
|
||||||
return UnknownUser;
|
return UnknownUser;
|
||||||
|
@ -181,6 +188,7 @@ AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QS
|
||||||
|
|
||||||
bool Servatrice::userExists(const QString &user)
|
bool Servatrice::userExists(const QString &user)
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
const QString method = settings->value("authentication/method").toString();
|
const QString method = settings->value("authentication/method").toString();
|
||||||
if (method == "sql") {
|
if (method == "sql") {
|
||||||
checkSql();
|
checkSql();
|
||||||
|
@ -219,6 +227,7 @@ ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool co
|
||||||
|
|
||||||
ServerInfo_User *Servatrice::getUserData(const QString &name)
|
ServerInfo_User *Servatrice::getUserData(const QString &name)
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
const QString method = settings->value("authentication/method").toString();
|
const QString method = settings->value("authentication/method").toString();
|
||||||
if (method == "sql") {
|
if (method == "sql") {
|
||||||
checkSql();
|
checkSql();
|
||||||
|
@ -248,6 +257,7 @@ int Servatrice::getUsersWithAddress(const QHostAddress &address) const
|
||||||
|
|
||||||
QMap<QString, ServerInfo_User *> Servatrice::getBuddyList(const QString &name)
|
QMap<QString, ServerInfo_User *> Servatrice::getBuddyList(const QString &name)
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
QMap<QString, ServerInfo_User *> result;
|
QMap<QString, ServerInfo_User *> result;
|
||||||
|
|
||||||
const QString method = settings->value("authentication/method").toString();
|
const QString method = settings->value("authentication/method").toString();
|
||||||
|
@ -270,6 +280,7 @@ QMap<QString, ServerInfo_User *> Servatrice::getBuddyList(const QString &name)
|
||||||
|
|
||||||
QMap<QString, ServerInfo_User *> Servatrice::getIgnoreList(const QString &name)
|
QMap<QString, ServerInfo_User *> Servatrice::getIgnoreList(const QString &name)
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
QMap<QString, ServerInfo_User *> result;
|
QMap<QString, ServerInfo_User *> result;
|
||||||
|
|
||||||
const QString method = settings->value("authentication/method").toString();
|
const QString method = settings->value("authentication/method").toString();
|
||||||
|
@ -318,6 +329,7 @@ void Servatrice::updateBanTimer()
|
||||||
|
|
||||||
void Servatrice::updateLoginMessage()
|
void Servatrice::updateLoginMessage()
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
checkSql();
|
checkSql();
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("select message from " + dbPrefix + "_servermessages order by timest desc limit 1");
|
query.prepare("select message from " + dbPrefix + "_servermessages order by timest desc limit 1");
|
||||||
|
@ -336,6 +348,7 @@ void Servatrice::updateLoginMessage()
|
||||||
|
|
||||||
void Servatrice::statusUpdate()
|
void Servatrice::statusUpdate()
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&dbMutex);
|
||||||
uptime += statusUpdateClock->interval() / 1000;
|
uptime += statusUpdateClock->interval() / 1000;
|
||||||
|
|
||||||
checkSql();
|
checkSql();
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define SERVATRICE_H
|
#define SERVATRICE_H
|
||||||
|
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
|
#include <QMutex>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
class QSqlDatabase;
|
class QSqlDatabase;
|
||||||
|
@ -28,16 +29,33 @@ class QSettings;
|
||||||
class QSqlQuery;
|
class QSqlQuery;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
|
class Servatrice;
|
||||||
|
class ServerSocketInterface;
|
||||||
|
|
||||||
|
class Servatrice_TcpServer : public QTcpServer {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
Servatrice *server;
|
||||||
|
public:
|
||||||
|
Servatrice_TcpServer(Servatrice *_server, QObject *parent = 0)
|
||||||
|
: QTcpServer(parent), server(_server) { }
|
||||||
|
protected:
|
||||||
|
void incomingConnection(int socketDescriptor);
|
||||||
|
signals:
|
||||||
|
void clientAdded(ServerSocketInterface *client);
|
||||||
|
};
|
||||||
|
|
||||||
class Servatrice : public Server
|
class Servatrice : public Server
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private slots:
|
private slots:
|
||||||
void newConnection();
|
void newConnection(ServerSocketInterface *client);
|
||||||
void statusUpdate();
|
void statusUpdate();
|
||||||
void updateBanTimer();
|
void updateBanTimer();
|
||||||
public:
|
public:
|
||||||
|
QMutex dbMutex;
|
||||||
static const QString versionString;
|
static const QString versionString;
|
||||||
Servatrice(QObject *parent = 0);
|
Servatrice(QSettings *_settings, QObject *parent = 0);
|
||||||
~Servatrice();
|
~Servatrice();
|
||||||
bool openDatabase();
|
bool openDatabase();
|
||||||
void checkSql();
|
void checkSql();
|
||||||
|
|
|
@ -2,19 +2,27 @@
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QThread>
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
ServerLogger::ServerLogger(QObject *parent)
|
ServerLogger::ServerLogger(const QString &logFileName, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
logFile = new QFile("server.log", this);
|
if (!logFileName.isEmpty()) {
|
||||||
logFile->open(QIODevice::Append);
|
logFile = new QFile(logFileName, this);
|
||||||
|
logFile->open(QIODevice::Append);
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD);
|
::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD);
|
||||||
#endif
|
#endif
|
||||||
snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this);
|
snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this);
|
||||||
connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup()));
|
connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup()));
|
||||||
|
} else
|
||||||
|
logFile = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerLogger::~ServerLogger()
|
ServerLogger::~ServerLogger()
|
||||||
|
@ -23,18 +31,30 @@ ServerLogger::~ServerLogger()
|
||||||
|
|
||||||
void ServerLogger::logMessage(QString message)
|
void ServerLogger::logMessage(QString message)
|
||||||
{
|
{
|
||||||
|
if (!logFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static QMutex mutex;
|
||||||
|
mutex.lock();
|
||||||
QTextStream stream(logFile);
|
QTextStream stream(logFile);
|
||||||
stream << message << "\n";
|
stream << QDateTime::currentDateTime().toString() << " " << ((void *) QThread::currentThread()) << " " << message << "\n";
|
||||||
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerLogger::hupSignalHandler(int /*unused*/)
|
void ServerLogger::hupSignalHandler(int /*unused*/)
|
||||||
{
|
{
|
||||||
|
if (!logFile)
|
||||||
|
return;
|
||||||
|
|
||||||
char a = 1;
|
char a = 1;
|
||||||
::write(sigHupFD[0], &a, sizeof(a));
|
::write(sigHupFD[0], &a, sizeof(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerLogger::handleSigHup()
|
void ServerLogger::handleSigHup()
|
||||||
{
|
{
|
||||||
|
if (!logFile)
|
||||||
|
return;
|
||||||
|
|
||||||
snHup->setEnabled(false);
|
snHup->setEnabled(false);
|
||||||
char tmp;
|
char tmp;
|
||||||
::read(sigHupFD[1], &tmp, sizeof(tmp));
|
::read(sigHupFD[1], &tmp, sizeof(tmp));
|
||||||
|
|
|
@ -9,7 +9,7 @@ class QFile;
|
||||||
class ServerLogger : public QObject {
|
class ServerLogger : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ServerLogger(QObject *parent = 0);
|
ServerLogger(const QString &logFileName, QObject *parent = 0);
|
||||||
~ServerLogger();
|
~ServerLogger();
|
||||||
static void hupSignalHandler(int unused);
|
static void hupSignalHandler(int unused);
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -101,14 +101,18 @@ void ServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socket
|
||||||
|
|
||||||
void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem)
|
void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem)
|
||||||
{
|
{
|
||||||
|
static QMutex mutex;
|
||||||
|
mutex.lock();
|
||||||
item->write(xmlWriter);
|
item->write(xmlWriter);
|
||||||
socket->flush();
|
socket->flush();
|
||||||
|
mutex.unlock();
|
||||||
if (deleteItem)
|
if (deleteItem)
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ServerSocketInterface::getUserIdInDB(const QString &name) const
|
int ServerSocketInterface::getUserIdInDB(const QString &name) const
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("select id from " + servatrice->getDbPrefix() + "_users where name = :name");
|
query.prepare("select id from " + servatrice->getDbPrefix() + "_users where name = :name");
|
||||||
query.bindValue(":name", name);
|
query.bindValue(":name", name);
|
||||||
|
@ -142,6 +146,7 @@ ResponseCode ServerSocketInterface::cmdAddToList(Command_AddToList *cmd, Command
|
||||||
if (id1 == id2)
|
if (id1 == id2)
|
||||||
return RespContextError;
|
return RespContextError;
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("insert into " + servatrice->getDbPrefix() + "_" + list + "list (id_user1, id_user2) values(:id1, :id2)");
|
query.prepare("insert into " + servatrice->getDbPrefix() + "_" + list + "list (id_user1, id_user2) values(:id1, :id2)");
|
||||||
query.bindValue(":id1", id1);
|
query.bindValue(":id1", id1);
|
||||||
|
@ -180,6 +185,7 @@ ResponseCode ServerSocketInterface::cmdRemoveFromList(Command_RemoveFromList *cm
|
||||||
if (id2 < 0)
|
if (id2 < 0)
|
||||||
return RespNameNotFound;
|
return RespNameNotFound;
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("delete from " + servatrice->getDbPrefix() + "_" + list + "list where id_user1 = :id1 and id_user2 = :id2");
|
query.prepare("delete from " + servatrice->getDbPrefix() + "_" + list + "list where id_user1 = :id1 and id_user2 = :id2");
|
||||||
query.bindValue(":id1", id1);
|
query.bindValue(":id1", id1);
|
||||||
|
@ -206,6 +212,7 @@ int ServerSocketInterface::getDeckPathId(int basePathId, QStringList path)
|
||||||
if (path[0].isEmpty())
|
if (path[0].isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and name = :name and user = :user");
|
query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and name = :name and user = :user");
|
||||||
query.bindValue(":id_parent", basePathId);
|
query.bindValue(":id_parent", basePathId);
|
||||||
|
@ -229,6 +236,7 @@ int ServerSocketInterface::getDeckPathId(const QString &path)
|
||||||
|
|
||||||
bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder)
|
bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder)
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("select id, name from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and user = :user");
|
query.prepare("select id, name from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and user = :user");
|
||||||
query.bindValue(":id_parent", folder->getId());
|
query.bindValue(":id_parent", folder->getId());
|
||||||
|
@ -288,6 +296,7 @@ ResponseCode ServerSocketInterface::cmdDeckNewDir(Command_DeckNewDir *cmd, Comma
|
||||||
if (folderId == -1)
|
if (folderId == -1)
|
||||||
return RespNameNotFound;
|
return RespNameNotFound;
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_folders (id_parent, user, name) values(:id_parent, :user, :name)");
|
query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_folders (id_parent, user, name) values(:id_parent, :user, :name)");
|
||||||
query.bindValue(":id_parent", folderId);
|
query.bindValue(":id_parent", folderId);
|
||||||
|
@ -302,6 +311,7 @@ void ServerSocketInterface::deckDelDirHelper(int basePathId)
|
||||||
{
|
{
|
||||||
servatrice->checkSql();
|
servatrice->checkSql();
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
|
|
||||||
query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent");
|
query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent");
|
||||||
|
@ -340,6 +350,7 @@ ResponseCode ServerSocketInterface::cmdDeckDel(Command_DeckDel *cmd, CommandCont
|
||||||
|
|
||||||
servatrice->checkSql();
|
servatrice->checkSql();
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
|
|
||||||
query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user");
|
query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user");
|
||||||
|
@ -379,6 +390,7 @@ ResponseCode ServerSocketInterface::cmdDeckUpload(Command_DeckUpload *cmd, Comma
|
||||||
if (deckName.isEmpty())
|
if (deckName.isEmpty())
|
||||||
deckName = "Unnamed deck";
|
deckName = "Unnamed deck";
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_files (id_folder, user, name, upload_time, content) values(:id_folder, :user, :name, NOW(), :content)");
|
query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_files (id_folder, user, name, upload_time, content) values(:id_folder, :user, :name, NOW(), :content)");
|
||||||
query.bindValue(":id_folder", folderId);
|
query.bindValue(":id_folder", folderId);
|
||||||
|
@ -395,6 +407,7 @@ DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId)
|
||||||
{
|
{
|
||||||
servatrice->checkSql();
|
servatrice->checkSql();
|
||||||
|
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
|
|
||||||
query.prepare("select content from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user");
|
query.prepare("select content from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user");
|
||||||
|
@ -447,6 +460,7 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd,
|
||||||
if (user->getUserInfo()->getUserLevel() & ServerInfo_User::IsRegistered) {
|
if (user->getUserInfo()->getUserLevel() & ServerInfo_User::IsRegistered) {
|
||||||
// Registered users can be banned by name.
|
// Registered users can be banned by name.
|
||||||
if (minutes == 0) {
|
if (minutes == 0) {
|
||||||
|
QMutexLocker locker(&servatrice->dbMutex);
|
||||||
QSqlQuery query;
|
QSqlQuery query;
|
||||||
query.prepare("update " + servatrice->getDbPrefix() + "_users set banned=1 where name = :name");
|
query.prepare("update " + servatrice->getDbPrefix() + "_users set banned=1 where name = :name");
|
||||||
query.bindValue(":name", userName);
|
query.bindValue(":name", userName);
|
||||||
|
|
Loading…
Reference in a new issue