fix compiling on arch (#6768)
Some checks failed
Build Desktop / Configure (push) Has been cancelled
Build Docker Image / amd64 & arm64 (push) Has been cancelled
Build Desktop / Debian 11 (push) Has been cancelled
Build Desktop / Debian 13 (push) Has been cancelled
Build Desktop / Debian 12 (push) Has been cancelled
Build Desktop / Fedora 43 (push) Has been cancelled
Build Desktop / Fedora 42 (push) Has been cancelled
Build Desktop / Servatrice_Debian 11 (push) Has been cancelled
Build Desktop / Ubuntu 24.04 (push) Has been cancelled
Build Desktop / Ubuntu 26.04 (push) Has been cancelled
Build Desktop / Ubuntu 22.04 (push) Has been cancelled
Build Desktop / Arch (push) Has been cancelled
Build Desktop / macOS 14 (push) Has been cancelled
Build Desktop / macOS 15 (push) Has been cancelled
Build Desktop / macOS 13 Intel (push) Has been cancelled
Build Desktop / macOS 15 Debug (push) Has been cancelled
Build Desktop / Windows 10 (push) Has been cancelled

* fix compiling on arch

* redo all the logging in affected files
This commit is contained in:
ebbit1q 2026-04-05 21:52:46 +02:00 committed by GitHub
parent a46ab5cd68
commit 3ec9ae9772
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 219 additions and 148 deletions

View file

@ -30,6 +30,8 @@
#include <libcockatrice/protocol/pb/response_replay_get_code.pb.h> #include <libcockatrice/protocol/pb/response_replay_get_code.pb.h>
#include <libcockatrice/protocol/pending_command.h> #include <libcockatrice/protocol/pending_command.h>
inline Q_LOGGING_CATEGORY(TabReplaysLog, "replays_tab");
TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User *currentUserInfo) TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User *currentUserInfo)
: Tab(_tabSupervisor), client(_client) : Tab(_tabSupervisor), client(_client)
{ {
@ -265,9 +267,11 @@ void TabReplays::actOpenLocalReplay()
f.close(); f.close();
GameReplay *replay = new GameReplay; GameReplay *replay = new GameReplay;
replay->ParseFromArray(_data.data(), _data.size()); if (replay->ParseFromArray(_data.data(), _data.size())) {
emit openReplay(replay);
emit openReplay(replay); } else {
qCWarning(TabReplaysLog) << "could not parse replay!";
}
} }
} }
@ -379,9 +383,12 @@ void TabReplays::openRemoteReplayFinished(const Response &r)
const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext); const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext);
GameReplay *replay = new GameReplay; GameReplay *replay = new GameReplay;
replay->ParseFromString(resp.replay_data()); if (replay->ParseFromString(resp.replay_data())) {
emit openReplay(replay); emit openReplay(replay);
} else {
qCWarning(TabReplaysLog) << "could not parse remote replay!";
}
} }
void TabReplays::actDownload() void TabReplays::actDownload()

View file

@ -84,6 +84,7 @@
const QString MainWindow::appName = "Cockatrice"; const QString MainWindow::appName = "Cockatrice";
const QStringList MainWindow::fileNameFilters = QStringList() << QObject::tr("Cockatrice card database (*.xml)") const QStringList MainWindow::fileNameFilters = QStringList() << QObject::tr("Cockatrice card database (*.xml)")
<< QObject::tr("All files (*.*)"); << QObject::tr("All files (*.*)");
inline Q_LOGGING_CATEGORY(MainWindowLog, "main_window");
/** /**
* Replaces the tab-specific menus that are shown in the menuBar. * Replaces the tab-specific menus that are shown in the menuBar.
@ -277,9 +278,11 @@ void MainWindow::actWatchReplay()
file.close(); file.close();
replay = new GameReplay; replay = new GameReplay;
replay->ParseFromArray(buf.data(), buf.size()); if (replay->ParseFromArray(buf.data(), buf.size())) {
tabSupervisor->openReplay(replay);
tabSupervisor->openReplay(replay); } else {
qCWarning(MainWindowLog) << "failed to parse replay!";
}
} }
void MainWindow::localGameEnded() void MainWindow::localGameEnded()

View file

@ -390,14 +390,18 @@ void RemoteClient::readData()
return; return;
ServerMessage newServerMessage; ServerMessage newServerMessage;
newServerMessage.ParseFromArray(inputBuffer.data(), messageLength); bool ok = newServerMessage.ParseFromArray(inputBuffer.data(), messageLength);
qCDebug(RemoteClientLog).noquote() << "IN" << getSafeDebugString(newServerMessage);
inputBuffer.remove(0, messageLength); inputBuffer.remove(0, messageLength);
messageInProgress = false; messageInProgress = false;
processProtocolItem(newServerMessage); if (ok) {
qCDebug(RemoteClientLog).noquote() << "IN" << getSafeDebugString(newServerMessage);
processProtocolItem(newServerMessage);
} else {
qCDebug(RemoteClientLog) << "parsing error!";
}
if (getStatus() == StatusDisconnecting) // use thread-safe getter if (getStatus() == StatusDisconnecting) // use thread-safe getter
doDisconnectFromServer(); doDisconnectFromServer();
@ -408,11 +412,13 @@ void RemoteClient::websocketMessageReceived(const QByteArray &message)
{ {
lastDataReceived = timeRunning; lastDataReceived = timeRunning;
ServerMessage newServerMessage; ServerMessage newServerMessage;
newServerMessage.ParseFromArray(message.data(), message.length()); if (newServerMessage.ParseFromArray(message.data(), message.length())) {
qCDebug(RemoteClientLog).noquote() << "IN" << getSafeDebugString(newServerMessage);
qCDebug(RemoteClientLog).noquote() << "IN" << getSafeDebugString(newServerMessage); processProtocolItem(newServerMessage);
} else {
processProtocolItem(newServerMessage); qCDebug(RemoteClientLog) << "parsing error!";
}
} }
void RemoteClient::sendCommandContainer(const CommandContainer &cont) void RemoteClient::sendCommandContainer(const CommandContainer &cont)
@ -426,19 +432,27 @@ void RemoteClient::sendCommandContainer(const CommandContainer &cont)
qCDebug(RemoteClientLog).noquote() << "OUT" << getSafeDebugString(cont); qCDebug(RemoteClientLog).noquote() << "OUT" << getSafeDebugString(cont);
QByteArray buf; QByteArray buf;
bool ok;
if (usingWebSocket) { if (usingWebSocket) {
buf.resize(size); buf.resize(size);
cont.SerializeToArray(buf.data(), size); ok = cont.SerializeToArray(buf.data(), size);
websocket->sendBinaryMessage(buf); if (ok) {
websocket->sendBinaryMessage(buf);
}
} else { } else {
buf.resize(size + 4); buf.resize(size + 4);
cont.SerializeToArray(buf.data() + 4, size); ok = cont.SerializeToArray(buf.data() + 4, size);
buf.data()[3] = (unsigned char)size; if (ok) {
buf.data()[2] = (unsigned char)(size >> 8); buf.data()[3] = (unsigned char)size;
buf.data()[1] = (unsigned char)(size >> 16); buf.data()[2] = (unsigned char)(size >> 8);
buf.data()[0] = (unsigned char)(size >> 24); buf.data()[1] = (unsigned char)(size >> 16);
buf.data()[0] = (unsigned char)(size >> 24);
socket->write(buf); socket->write(buf);
}
}
if (!ok) {
qCDebug(RemoteClientLog) << "transmit error!";
} }
} }

View file

@ -101,6 +101,10 @@ QString getSafeDebugString(const ::google::protobuf::Message &message)
#endif // GOOGLE_PROTOBUF_VERSION > 3004000 #endif // GOOGLE_PROTOBUF_VERSION > 3004000
std::string debug_string; std::string debug_string;
printer.PrintToString(message, &debug_string); bool ok = printer.PrintToString(message, &debug_string);
return QString::number(size) + " bytes " + QString::fromStdString(debug_string); if (ok) {
return QString::number(size) + " bytes " + QString::fromStdString(debug_string);
} else {
return "[could not convert message to string]";
}
} }

View file

@ -3,6 +3,7 @@
#include "main.h" #include "main.h"
#include "server_logger.h" #include "server_logger.h"
#include <QLoggingCategory>
#include <QSslSocket> #include <QSslSocket>
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
#include <libcockatrice/protocol/debug_pb_message.h> #include <libcockatrice/protocol/debug_pb_message.h>
@ -21,6 +22,8 @@
#include <server_protocolhandler.h> #include <server_protocolhandler.h>
#include <server_room.h> #include <server_room.h>
inline Q_LOGGING_CATEGORY(IslInterfaceLog, "isl_interface");
void IslInterface::sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey) void IslInterface::sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey)
{ {
socket = new QSslSocket(this); socket = new QSslSocket(this);
@ -113,10 +116,11 @@ void IslInterface::initServer()
socket->startServerEncryption(); socket->startServerEncryption();
if (!socket->waitForEncrypted(5000)) { if (!socket->waitForEncrypted(5000)) {
QList<QSslError> sslErrors(socket->sslHandshakeErrors()); QList<QSslError> sslErrors(socket->sslHandshakeErrors());
if (sslErrors.isEmpty()) if (sslErrors.isEmpty()) {
qDebug() << "[ISL] SSL handshake timeout, terminating connection"; qCDebug(IslInterfaceLog) << "SSL handshake timeout, terminating connection";
else } else {
qDebug() << "[ISL] SSL errors:" << sslErrors; qCWarning(IslInterfaceLog) << "SSL errors:" << sslErrors;
}
deleteLater(); deleteLater();
return; return;
} }
@ -157,7 +161,7 @@ void IslInterface::initServer()
server->islLock.lockForWrite(); server->islLock.lockForWrite();
if (server->islConnectionExists(serverId)) { if (server->islConnectionExists(serverId)) {
qDebug() << "[ISL] Duplicate connection to #" << serverId << "terminating connection"; qCDebug(IslInterfaceLog) << "Duplicate connection to #" << serverId << "terminating connection";
deleteLater(); deleteLater();
} else { } else {
transmitMessage(message); transmitMessage(message);
@ -180,27 +184,28 @@ void IslInterface::initClient()
expectedErrors.append(QSslError(QSslError::SelfSignedCertificate, peerCert)); expectedErrors.append(QSslError(QSslError::SelfSignedCertificate, peerCert));
socket->ignoreSslErrors(expectedErrors); socket->ignoreSslErrors(expectedErrors);
qDebug() << "[ISL] Connecting to #" << serverId << ":" << peerAddress << ":" << peerPort; qCDebug(IslInterfaceLog) << "Connecting to #" << serverId << ":" << peerAddress << ":" << peerPort;
socket->connectToHostEncrypted(peerAddress, peerPort, peerHostName); socket->connectToHostEncrypted(peerAddress, peerPort, peerHostName);
if (!socket->waitForConnected(5000)) { if (!socket->waitForConnected(5000)) {
qDebug() << "[ISL] Socket error:" << socket->errorString(); qCDebug(IslInterfaceLog) << "Socket error:" << socket->errorString();
deleteLater(); deleteLater();
return; return;
} }
if (!socket->waitForEncrypted(5000)) { if (!socket->waitForEncrypted(5000)) {
QList<QSslError> sslErrors(socket->sslHandshakeErrors()); QList<QSslError> sslErrors(socket->sslHandshakeErrors());
if (sslErrors.isEmpty()) if (sslErrors.isEmpty()) {
qDebug() << "[ISL] SSL handshake timeout, terminating connection"; qCDebug(IslInterfaceLog) << "SSL handshake timeout, terminating connection";
else } else {
qDebug() << "[ISL] SSL errors:" << sslErrors; qCWarning(IslInterfaceLog) << "SSL errors:" << sslErrors;
}
deleteLater(); deleteLater();
return; return;
} }
server->islLock.lockForWrite(); server->islLock.lockForWrite();
if (server->islConnectionExists(serverId)) { if (server->islConnectionExists(serverId)) {
qDebug() << "[ISL] Duplicate connection to #" << serverId << "terminating connection"; qCDebug(IslInterfaceLog) << "Duplicate connection to #" << serverId << "terminating connection";
deleteLater(); deleteLater();
return; return;
} }
@ -242,17 +247,21 @@ void IslInterface::readClient()
return; return;
IslMessage newMessage; IslMessage newMessage;
newMessage.ParseFromArray(inputBuffer.data(), messageLength); bool ok = newMessage.ParseFromArray(inputBuffer.data(), messageLength);
inputBuffer.remove(0, messageLength); inputBuffer.remove(0, messageLength);
messageInProgress = false; messageInProgress = false;
processMessage(newMessage); if (ok) {
processMessage(newMessage);
} else {
qCWarning(IslInterfaceLog) << "parsing error!";
}
} while (!inputBuffer.isEmpty()); } while (!inputBuffer.isEmpty());
} }
void IslInterface::catchSocketError(QAbstractSocket::SocketError socketError) void IslInterface::catchSocketError(QAbstractSocket::SocketError socketError)
{ {
qDebug() << "[ISL] Socket error:" << socketError; qCWarning(IslInterfaceLog) << "Socket error:" << socketError;
server->islLock.lockForWrite(); server->islLock.lockForWrite();
server->removeIslInterface(serverId); server->removeIslInterface(serverId);
@ -270,7 +279,10 @@ void IslInterface::transmitMessage(const IslMessage &item)
unsigned int size = static_cast<unsigned int>(item.ByteSize()); unsigned int size = static_cast<unsigned int>(item.ByteSize());
#endif #endif
buf.resize(size + 4); buf.resize(size + 4);
item.SerializeToArray(buf.data() + 4, size); if (!item.SerializeToArray(buf.data() + 4, size)) {
qCWarning(IslInterfaceLog) << "transmit error!";
return;
}
buf.data()[3] = (unsigned char)size; buf.data()[3] = (unsigned char)size;
buf.data()[2] = (unsigned char)(size >> 8); buf.data()[2] = (unsigned char)(size >> 8);
buf.data()[1] = (unsigned char)(size >> 16); buf.data()[1] = (unsigned char)(size >> 16);
@ -368,7 +380,7 @@ void IslInterface::processSessionEvent(const SessionEvent &event, qint64 session
QReadLocker clientsLocker(&server->clientsLock); QReadLocker clientsLocker(&server->clientsLock);
Server_AbstractUserInterface *client = server->getUsersBySessionId().value(sessionId); Server_AbstractUserInterface *client = server->getUsersBySessionId().value(sessionId);
if (!client) { if (!client) {
qDebug() << "IslInterface::processSessionEvent: session id" << sessionId << "not found"; qCDebug(IslInterfaceLog) << "IslInterface::processSessionEvent: session id" << sessionId << "not found";
break; break;
} }
const Event_GameJoined &gameJoined = event.GetExtension(Event_GameJoined::ext); const Event_GameJoined &gameJoined = event.GetExtension(Event_GameJoined::ext);
@ -382,7 +394,8 @@ void IslInterface::processSessionEvent(const SessionEvent &event, qint64 session
QReadLocker clientsLocker(&server->clientsLock); QReadLocker clientsLocker(&server->clientsLock);
Server_AbstractUserInterface *client = server->getUsersBySessionId().value(sessionId); Server_AbstractUserInterface *client = server->getUsersBySessionId().value(sessionId);
if (!client) { if (!client) {
qDebug() << "IslInterface::processSessionEvent: session id" << sessionId << "not found"; qCWarning(IslInterfaceLog)
<< "IslInterface::processSessionEvent: session id" << sessionId << "not found";
break; break;
} }
@ -430,7 +443,7 @@ void IslInterface::processRoomCommand(const CommandContainer &cont, qint64 sessi
void IslInterface::processMessage(const IslMessage &item) void IslInterface::processMessage(const IslMessage &item)
{ {
qDebug() << getSafeDebugString(item); qCDebug(IslInterfaceLog) << getSafeDebugString(item);
switch (item.message_type()) { switch (item.message_type()) {
case IslMessage::ROOM_COMMAND_CONTAINER: { case IslMessage::ROOM_COMMAND_CONTAINER: {

View file

@ -7,12 +7,15 @@
#include <QChar> #include <QChar>
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QLoggingCategory>
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
#include <libcockatrice/deck_list/deck_list.h> #include <libcockatrice/deck_list/deck_list.h>
#include <libcockatrice/protocol/pb/game_replay.pb.h> #include <libcockatrice/protocol/pb/game_replay.pb.h>
#include <libcockatrice/utility/passwordhasher.h> #include <libcockatrice/utility/passwordhasher.h>
inline Q_LOGGING_CATEGORY(DatabaseInterfaceLog, "database_interface");
Servatrice_DatabaseInterface::Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server) Servatrice_DatabaseInterface::Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server)
: instanceId(_instanceId), sqlDatabase(QSqlDatabase()), server(_server) : instanceId(_instanceId), sqlDatabase(QSqlDatabase()), server(_server)
{ {
@ -56,17 +59,16 @@ bool Servatrice_DatabaseInterface::openDatabase()
sqlDatabase.close(); sqlDatabase.close();
const QString poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId); const QString poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId);
qDebug().noquote() << QString("[%1] Opening database...").arg(poolStr); qCDebug(DatabaseInterfaceLog).noquote() << poolStr << "Opening database...";
if (!sqlDatabase.open()) { if (!sqlDatabase.open()) {
qCritical() << QString("[%1] Error opening database: %2").arg(poolStr).arg(sqlDatabase.lastError().text()); qCCritical(DatabaseInterfaceLog) << poolStr << "Error opening database:" << sqlDatabase.lastError().text();
return false; return false;
} }
QSqlQuery *versionQuery = prepareQuery("select version from {prefix}_schema_version limit 1"); QSqlQuery *versionQuery = prepareQuery("select version from {prefix}_schema_version limit 1");
if (!execSqlQuery(versionQuery)) { if (!execSqlQuery(versionQuery)) {
qCritical() << QString("[%1] Error opening database: unable to load database schema version (hint: ensure the " qCCritical(DatabaseInterfaceLog) << poolStr << "Error opening database: unable to load database schema version"
"cockatrice_schema_version exists)") << "(hint: ensure the cockatrice_schema_version exists)";
.arg(poolStr);
return false; return false;
} }
@ -74,24 +76,21 @@ bool Servatrice_DatabaseInterface::openDatabase()
const int dbversion = versionQuery->value(0).toInt(); const int dbversion = versionQuery->value(0).toInt();
const int expectedversion = DATABASE_SCHEMA_VERSION; const int expectedversion = DATABASE_SCHEMA_VERSION;
if (dbversion < expectedversion) { if (dbversion < expectedversion) {
qCritical() << QString("[%1] Error opening database: the database schema version is too old, you need to " qCCritical(DatabaseInterfaceLog) << poolStr
"run the migrations to update it from version %2 to version %3") << "Error opening database: the database schema version is too old, you "
.arg(poolStr) "need to run the migrations to update it from version"
.arg(dbversion) << dbversion << "to version" << expectedversion;
.arg(expectedversion);
return false; return false;
} else if (dbversion > expectedversion) { } else if (dbversion > expectedversion) {
qCritical() << QString("[%1] Error opening database: the database schema version %2 is too new, you need " qCCritical(DatabaseInterfaceLog) << poolStr << "Error opening database: the database schema version"
"to update servatrice (this servatrice actually uses version %3)") << dbversion << "is too new, you need to update servatrice"
.arg(poolStr) << "(this servatrice actually uses version" << expectedversion << ")";
.arg(dbversion)
.arg(expectedversion);
return false; return false;
} }
} else { } else {
qCritical() << QString("[%1] Error opening database: unable to load database schema version (hint: ensure the " qCCritical(DatabaseInterfaceLog) << poolStr
"cockatrice_schema_version contains a single record)") << "Error opening database: unable to load database schema version (hint: "
.arg(poolStr); "ensure the cockatrice_schema_version contains a single record)";
return false; return false;
} }
@ -114,9 +113,7 @@ bool Servatrice_DatabaseInterface::checkSql()
if (query.lastError().isValid()) { if (query.lastError().isValid()) {
const auto &poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId); const auto &poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId);
qCritical() << QString("[%1] Error executing query: %2, resetting connection") qCCritical(DatabaseInterfaceLog) << poolStr << "Error executing query:" << query.lastError().text();
.arg(poolStr)
.arg(query.lastError().text());
sqlDatabase.close(); sqlDatabase.close();
return openDatabase(); return openDatabase();
@ -145,7 +142,7 @@ bool Servatrice_DatabaseInterface::execSqlQuery(QSqlQuery *query)
if (query->exec()) if (query->exec())
return true; return true;
const QString poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId); const QString poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId);
qCritical() << QString("[%1] Error executing query: %2").arg(poolStr).arg(query->lastError().text()); qCCritical(DatabaseInterfaceLog) << poolStr << "Error executing query:" << query->lastError().text();
sqlDatabase.close(); sqlDatabase.close();
openDatabase(); openDatabase();
return false; return false;
@ -252,7 +249,8 @@ bool Servatrice_DatabaseInterface::registerUser(const QString &userName,
query->bindValue(":token", token); query->bindValue(":token", token);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug() << "Failed to insert user: " << query->lastError() << " sql: " << query->lastQuery(); qCWarning(DatabaseInterfaceLog) << "Failed to insert user: " << query->lastError()
<< " sql: " << query->lastQuery();
return false; return false;
} }
@ -270,8 +268,8 @@ bool Servatrice_DatabaseInterface::activateUser(const QString &userName, const Q
activateQuery->bindValue(":username", userName); activateQuery->bindValue(":username", userName);
activateQuery->bindValue(":token", token); activateQuery->bindValue(":token", token);
if (!execSqlQuery(activateQuery)) { if (!execSqlQuery(activateQuery)) {
qDebug() << "Account activation failed: SQL error." << activateQuery->lastError() qCWarning(DatabaseInterfaceLog) << "Account activation failed: SQL error." << activateQuery->lastError()
<< " sql: " << activateQuery->lastQuery(); << " sql: " << activateQuery->lastQuery();
return false; return false;
} }
@ -284,7 +282,8 @@ bool Servatrice_DatabaseInterface::activateUser(const QString &userName, const Q
query->bindValue(":userName", userName); query->bindValue(":userName", userName);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug() << "Failed to activate user: " << query->lastError() << " sql: " << query->lastQuery(); qCWarning(DatabaseInterfaceLog)
<< "Failed to activate user: " << query->lastError() << " sql: " << query->lastQuery();
return false; return false;
} }
@ -326,7 +325,7 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
prepareQuery("select password_sha512, active from {prefix}_users where name = :name"); prepareQuery("select password_sha512, active from {prefix}_users where name = :name");
passwordQuery->bindValue(":name", user); passwordQuery->bindValue(":name", user);
if (!execSqlQuery(passwordQuery)) { if (!execSqlQuery(passwordQuery)) {
qDebug("Login denied: SQL error"); qCWarning(DatabaseInterfaceLog) << "Login denied: SQL error";
return NotLoggedIn; return NotLoggedIn;
} }
@ -334,7 +333,7 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
const QString correctPasswordSha512 = passwordQuery->value(0).toString(); const QString correctPasswordSha512 = passwordQuery->value(0).toString();
const bool userIsActive = passwordQuery->value(1).toBool(); const bool userIsActive = passwordQuery->value(1).toBool();
if (!userIsActive) { if (!userIsActive) {
qDebug("Login denied: user not active"); qCWarning(DatabaseInterfaceLog) << "Login denied: user not active";
return UserIsInactive; return UserIsInactive;
} }
QString hashedPassword; QString hashedPassword;
@ -344,14 +343,14 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
hashedPassword = password; hashedPassword = password;
} }
if (correctPasswordSha512 == hashedPassword) { if (correctPasswordSha512 == hashedPassword) {
qDebug("Login accepted: password right"); qCDebug(DatabaseInterfaceLog) << "Login accepted: password right";
return PasswordRight; return PasswordRight;
} else { } else {
qDebug("Login denied: password wrong"); qCDebug(DatabaseInterfaceLog) << "Login denied: password wrong";
return NotLoggedIn; return NotLoggedIn;
} }
} else { } else {
qDebug("Login accepted: unknown user"); qCDebug(DatabaseInterfaceLog) << "Login accepted: unknown user";
return UnknownUser; return UnknownUser;
} }
} }
@ -369,7 +368,7 @@ bool Servatrice_DatabaseInterface::checkUserIsBanned(const QString &ipAddress,
return false; return false;
if (!checkSql()) { if (!checkSql()) {
qDebug("Failed to check if user is banned. Database invalid."); qCWarning(DatabaseInterfaceLog) << "Failed to check if user is banned. Database invalid.";
return false; return false;
} }
@ -400,7 +399,7 @@ bool Servatrice_DatabaseInterface::checkUserIsIdBanned(const QString &clientId,
idBanQuery->bindValue(":id", clientId); idBanQuery->bindValue(":id", clientId);
idBanQuery->bindValue(":id2", clientId); idBanQuery->bindValue(":id2", clientId);
if (!execSqlQuery(idBanQuery)) { if (!execSqlQuery(idBanQuery)) {
qDebug() << "Id ban check failed: SQL error." << idBanQuery->lastError(); qCWarning(DatabaseInterfaceLog) << "Id ban check failed: SQL error." << idBanQuery->lastError();
return false; return false;
} }
@ -410,7 +409,7 @@ bool Servatrice_DatabaseInterface::checkUserIsIdBanned(const QString &clientId,
if ((secondsLeft > 0) || permanentBan) { if ((secondsLeft > 0) || permanentBan) {
banReason = idBanQuery->value(2).toString(); banReason = idBanQuery->value(2).toString();
banSecondsRemaining = permanentBan ? 0 : secondsLeft; banSecondsRemaining = permanentBan ? 0 : secondsLeft;
qDebug() << "User is banned by client id" << clientId; qCDebug(DatabaseInterfaceLog) << "User is banned by client id" << clientId;
return true; return true;
} }
} }
@ -428,7 +427,7 @@ bool Servatrice_DatabaseInterface::checkUserIsNameBanned(const QString &userName
nameBanQuery->bindValue(":name1", userName); nameBanQuery->bindValue(":name1", userName);
nameBanQuery->bindValue(":name2", userName); nameBanQuery->bindValue(":name2", userName);
if (!execSqlQuery(nameBanQuery)) { if (!execSqlQuery(nameBanQuery)) {
qDebug() << "Name ban check failed: SQL error" << nameBanQuery->lastError(); qCWarning(DatabaseInterfaceLog) << "Name ban check failed: SQL error" << nameBanQuery->lastError();
return false; return false;
} }
@ -438,7 +437,7 @@ bool Servatrice_DatabaseInterface::checkUserIsNameBanned(const QString &userName
if ((secondsLeft > 0) || permanentBan) { if ((secondsLeft > 0) || permanentBan) {
banReason = nameBanQuery->value(2).toString(); banReason = nameBanQuery->value(2).toString();
banSecondsRemaining = permanentBan ? 0 : secondsLeft; banSecondsRemaining = permanentBan ? 0 : secondsLeft;
qDebug() << "Username" << userName << "is banned by name"; qCDebug(DatabaseInterfaceLog) << "Username" << userName << "is banned by name";
return true; return true;
} }
} }
@ -464,7 +463,7 @@ bool Servatrice_DatabaseInterface::checkUserIsIpBanned(const QString &ipAddress,
ipBanQuery->bindValue(":address", ipAddress); ipBanQuery->bindValue(":address", ipAddress);
ipBanQuery->bindValue(":address2", ipAddress); ipBanQuery->bindValue(":address2", ipAddress);
if (!execSqlQuery(ipBanQuery)) { if (!execSqlQuery(ipBanQuery)) {
qDebug() << "IP ban check failed: SQL error." << ipBanQuery->lastError(); qCWarning(DatabaseInterfaceLog) << "IP ban check failed: SQL error." << ipBanQuery->lastError();
return false; return false;
} }
@ -474,7 +473,7 @@ bool Servatrice_DatabaseInterface::checkUserIsIpBanned(const QString &ipAddress,
if ((secondsLeft > 0) || permanentBan) { if ((secondsLeft > 0) || permanentBan) {
banReason = ipBanQuery->value(2).toString(); banReason = ipBanQuery->value(2).toString();
banSecondsRemaining = permanentBan ? 0 : secondsLeft; banSecondsRemaining = permanentBan ? 0 : secondsLeft;
qDebug() << "User is banned by address" << ipAddress; qCDebug(DatabaseInterfaceLog) << "User is banned by address" << ipAddress;
return true; return true;
} }
} }
@ -865,12 +864,17 @@ void Servatrice_DatabaseInterface::storeGameInformation(const QString &roomName,
const unsigned int size = static_cast<unsigned int>(replayList[i]->ByteSize()); const unsigned int size = static_cast<unsigned int>(replayList[i]->ByteSize());
#endif #endif
blob.resize(size); blob.resize(size);
replayList[i]->SerializeToArray(blob.data(), size); qulonglong replayId = replayList[i]->replay_id();
if (replayList[i]->SerializeToArray(blob.data(), size)) {
replayIds.append(QVariant((qulonglong)replayList[i]->replay_id())); replayIds.append(QVariant(replayId));
replayGameIds.append(gameInfo.game_id()); replayGameIds.append(gameInfo.game_id());
replayDurations.append(replayList[i]->duration_seconds()); replayDurations.append(replayList[i]->duration_seconds());
replayBlobs.append(blob); replayBlobs.append(blob);
} else {
qCWarning(DatabaseInterfaceLog)
<< "failed to serialise replay, id:" << replayId << "game:" << gameInfo.game_id();
}
} }
{ {
@ -1017,7 +1021,7 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user,
passwordQuery->bindValue(":name", user); passwordQuery->bindValue(":name", user);
if (!execSqlQuery(passwordQuery)) { if (!execSqlQuery(passwordQuery)) {
qDebug("Change password denied: SQL error"); qCWarning(DatabaseInterfaceLog) << "Change password denied: SQL error";
return false; return false;
} }
@ -1084,7 +1088,7 @@ void Servatrice_DatabaseInterface::updateUsersLastLoginData(const QString &userN
QSqlQuery *query = prepareQuery("select id from {prefix}_users where name = :user_name"); QSqlQuery *query = prepareQuery("select id from {prefix}_users where name = :user_name");
query->bindValue(":user_name", userName); query->bindValue(":user_name", userName);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug("Failed to locate user id when updating users last login data: SQL Error"); qCWarning(DatabaseInterfaceLog) << "Failed to locate user id when updating users last login data: SQL Error";
return; return;
} }
@ -1133,7 +1137,7 @@ QList<ServerInfo_Ban> Servatrice_DatabaseInterface::getUserBanHistory(const QStr
query->bindValue(":user_name", userName); query->bindValue(":user_name", userName);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug("Failed to collect ban history information: SQL Error"); qCWarning(DatabaseInterfaceLog) << "Failed to collect ban history information: SQL Error";
return results; return results;
} }
@ -1168,7 +1172,7 @@ bool Servatrice_DatabaseInterface::addWarning(const QString userName,
query->bindValue(":warn_reason", warningReason); query->bindValue(":warn_reason", warningReason);
query->bindValue(":client_id", clientID); query->bindValue(":client_id", clientID);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug("Failed to collect create warning history information: SQL Error"); qCWarning(DatabaseInterfaceLog) << "Failed to collect create warning history information: SQL Error";
return false; return false;
} }
@ -1189,7 +1193,7 @@ QList<ServerInfo_Warning> Servatrice_DatabaseInterface::getUserWarnHistory(const
query->bindValue(":user_id", userID); query->bindValue(":user_id", userID);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug("Failed to collect warning history information: SQL Error"); qCWarning(DatabaseInterfaceLog) << "Failed to collect warning history information: SQL Error";
return results; return results;
} }
@ -1296,7 +1300,7 @@ QList<ServerInfo_ChatMessage> Servatrice_DatabaseInterface::getMessageLogHistory
} }
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug("Failed to collect log history information: SQL Error"); qCWarning(DatabaseInterfaceLog) << "Failed to collect log history information: SQL Error";
return results; return results;
} }
@ -1324,7 +1328,8 @@ int Servatrice_DatabaseInterface::checkNumberOfUserAccounts(const QString &email
query->bindValue(":user_email", email); query->bindValue(":user_email", email);
if (!execSqlQuery(query)) { if (!execSqlQuery(query)) {
qDebug("Failed to identify the number of users accounts for users email address: SQL Error"); qCWarning(DatabaseInterfaceLog)
<< "Failed to identify the number of users accounts for users email address: SQL Error";
return 0; return 0;
} }

View file

@ -31,6 +31,7 @@
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QHostAddress> #include <QHostAddress>
#include <QLoggingCategory>
#include <QRegularExpression> #include <QRegularExpression>
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
@ -83,6 +84,10 @@
#include <server_room.h> #include <server_room.h>
#include <string> #include <string>
inline Q_LOGGING_CATEGORY(AbstractServerSocketInterfaceLog, "abstract_server_socket_interface");
inline Q_LOGGING_CATEGORY(TcpServerSocketInterfaceLog, "tcp_server_socket_interface");
inline Q_LOGGING_CATEGORY(WebsocketServerSocketInterfaceLog, "websocket_server_socket_interface");
static const int protocolVersion = 14; static const int protocolVersion = 14;
AbstractServerSocketInterface::AbstractServerSocketInterface(Servatrice *_server, AbstractServerSocketInterface::AbstractServerSocketInterface(Servatrice *_server,
@ -130,7 +135,7 @@ bool AbstractServerSocketInterface::initSession()
void AbstractServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socketError) void AbstractServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socketError)
{ {
qDebug() << "Socket error:" << socketError; qCWarning(AbstractServerSocketInterfaceLog) << "Socket error:" << socketError;
prepareDestroy(); prepareDestroy();
} }
@ -1100,7 +1105,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com
clientIdQuery->bindValue(":client_id", nameFromStdString(cmd.clientid())); clientIdQuery->bindValue(":client_id", nameFromStdString(cmd.clientid()));
sqlInterface->execSqlQuery(clientIdQuery); sqlInterface->execSqlQuery(clientIdQuery);
if (!sqlInterface->execSqlQuery(clientIdQuery)) { if (!sqlInterface->execSqlQuery(clientIdQuery)) {
qDebug("ClientID username ban lookup failed: SQL Error"); qCWarning(AbstractServerSocketInterfaceLog) << "ClientID username ban lookup failed: SQL Error";
} else { } else {
while (clientIdQuery->next()) { while (clientIdQuery->next()) {
userName = clientIdQuery->value(0).toString(); userName = clientIdQuery->value(0).toString();
@ -1152,7 +1157,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
{ {
QString userName = nameFromStdString(cmd.user_name()); QString userName = nameFromStdString(cmd.user_name());
QString clientId = nameFromStdString(cmd.clientid()); QString clientId = nameFromStdString(cmd.clientid());
qDebug() << "Got register command for user:" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Got register command for user:" << userName;
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool(); bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
if (!registrationEnabled) { if (!registrationEnabled) {
@ -1289,7 +1294,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
country, !requireEmailActivation); country, !requireEmailActivation);
if (regSucceeded) { if (regSucceeded) {
qDebug() << "Accepted register command for user:" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Accepted register command for user:" << userName;
if (requireEmailActivation) { if (requireEmailActivation) {
QSqlQuery *query = QSqlQuery *query =
sqlInterface->prepareQuery("insert into {prefix}_activation_emails (name) values(:name)"); sqlInterface->prepareQuery("insert into {prefix}_activation_emails (name) values(:name)");
@ -1337,7 +1342,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdActivateAccount(const C
clientId = "UNKNOWN"; clientId = "UNKNOWN";
if (sqlInterface->activateUser(userName, token)) { if (sqlInterface->activateUser(userName, token)) {
qDebug() << "Accepted activation for user" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Accepted activation for user" << userName;
if (servatrice->getEnableRegistrationAudit()) if (servatrice->getEnableRegistrationAudit())
sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(),
@ -1345,7 +1350,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdActivateAccount(const C
return Response::RespActivationAccepted; return Response::RespActivationAccepted;
} else { } else {
qDebug() << "Failed activation for user" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Failed activation for user" << userName;
if (servatrice->getEnableRegistrationAudit()) if (servatrice->getEnableRegistrationAudit())
sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(),
@ -1493,7 +1498,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(c
const QString userName = nameFromStdString(cmd.user_name()); const QString userName = nameFromStdString(cmd.user_name());
const QString clientId = nameFromStdString(cmd.clientid()); const QString clientId = nameFromStdString(cmd.clientid());
qDebug() << "Received reset password request from user:" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Received reset password request from user:" << userName;
if (!servatrice->getEnableForgotPassword()) { if (!servatrice->getEnableForgotPassword()) {
if (servatrice->getEnableForgotPasswordAudit()) if (servatrice->getEnableForgotPasswordAudit())
@ -1575,7 +1580,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordReset(con
Q_UNUSED(rc); Q_UNUSED(rc);
QString userName = nameFromStdString(cmd.user_name()); QString userName = nameFromStdString(cmd.user_name());
QString clientId = nameFromStdString(cmd.clientid()); QString clientId = nameFromStdString(cmd.clientid());
qDebug() << "Received reset password reset from user:" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Received reset password reset from user:" << userName;
if (!sqlInterface->doesForgotPasswordExist(userName)) { if (!sqlInterface->doesForgotPasswordExist(userName)) {
if (servatrice->getEnableForgotPasswordAudit()) if (servatrice->getEnableForgotPasswordAudit())
@ -1626,7 +1631,7 @@ AbstractServerSocketInterface::cmdForgotPasswordChallenge(const Command_ForgotPa
const QString userName = nameFromStdString(cmd.user_name()); const QString userName = nameFromStdString(cmd.user_name());
const QString clientId = nameFromStdString(cmd.clientid()); const QString clientId = nameFromStdString(cmd.clientid());
qDebug() << "Received reset password challenge from user:" << userName; qCDebug(AbstractServerSocketInterfaceLog) << "Received reset password challenge from user:" << userName;
if (!servatrice->getEnableForgotPasswordChallenge()) { if (!servatrice->getEnableForgotPasswordChallenge()) {
if (servatrice->getEnableForgotPasswordAudit()) { if (servatrice->getEnableForgotPasswordAudit()) {
@ -1971,13 +1976,16 @@ void TcpServerSocketInterface::flushOutputQueue()
unsigned int size = static_cast<unsigned int>(item.ByteSize()); unsigned int size = static_cast<unsigned int>(item.ByteSize());
#endif #endif
buf.resize(size + 4); buf.resize(size + 4);
item.SerializeToArray(buf.data() + 4, size); if (item.SerializeToArray(buf.data() + 4, size)) {
buf.data()[3] = (unsigned char)size; buf.data()[3] = (unsigned char)size;
buf.data()[2] = (unsigned char)(size >> 8); buf.data()[2] = (unsigned char)(size >> 8);
buf.data()[1] = (unsigned char)(size >> 16); buf.data()[1] = (unsigned char)(size >> 16);
buf.data()[0] = (unsigned char)(size >> 24); buf.data()[0] = (unsigned char)(size >> 24);
// In case socket->write() calls catchSocketError(), the mutex must not be locked during this call. // In case socket->write() calls catchSocketError(), the mutex must not be locked during this call.
writeToSocket(buf); writeToSocket(buf);
} else {
qCWarning(TcpServerSocketInterfaceLog) << "serialisation error!";
}
totalBytes += size + 4; totalBytes += size + 4;
locker.relock(); locker.relock();
@ -2010,41 +2018,48 @@ void TcpServerSocketInterface::readClient()
return; return;
CommandContainer newCommandContainer; CommandContainer newCommandContainer;
bool ok;
try { try {
newCommandContainer.ParseFromArray(inputBuffer.data(), messageLength); ok = newCommandContainer.ParseFromArray(inputBuffer.data(), messageLength);
} catch (std::exception &e) { } catch (std::exception &e) {
qDebug() << "Caught std::exception in" << __FILE__ << __LINE__ << qCWarning(TcpServerSocketInterfaceLog) << "Caught std::exception in" << __FILE__ << __LINE__ <<
#ifdef _MSC_VER // Visual Studio #ifdef _MSC_VER // Visual Studio
__FUNCTION__; __FUNCTION__
#else #else
__PRETTY_FUNCTION__; __PRETTY_FUNCTION__
#endif #endif
qDebug() << "Exception:" << e.what(); << Qt::endl
qDebug() << "Message coming from:" << getAddress(); << "Exception:" << e.what() << Qt::endl
qDebug() << "Message length:" << messageLength; << "Message coming from:" << getAddress() << Qt::endl
qDebug() << "Message content:" << inputBuffer.toHex(); << "Message length:" << messageLength << Qt::endl
<< "Message content:" << inputBuffer.toHex();
} catch (...) { } catch (...) {
qDebug() << "Unhandled exception in" << __FILE__ << __LINE__ << qCWarning(TcpServerSocketInterfaceLog) << "Unhandled exception in" << __FILE__ << __LINE__ <<
#ifdef _MSC_VER // Visual Studio #ifdef _MSC_VER // Visual Studio
__FUNCTION__; __FUNCTION__
#else #else
__PRETTY_FUNCTION__; __PRETTY_FUNCTION__
#endif #endif
qDebug() << "Message coming from:" << getAddress(); << Qt::endl
<< "Message coming from:" << getAddress();
} }
inputBuffer.remove(0, messageLength); inputBuffer.remove(0, messageLength);
messageInProgress = false; messageInProgress = false;
// dirty hack to make v13 client display the correct error message if (ok) {
if (handshakeStarted) // dirty hack to make v13 client display the correct error message
processCommandContainer(newCommandContainer); if (handshakeStarted)
else if (!newCommandContainer.has_cmd_id()) { processCommandContainer(newCommandContainer);
handshakeStarted = true; else if (!newCommandContainer.has_cmd_id()) {
if (!initTcpSession()) handshakeStarted = true;
prepareDestroy(); if (!initTcpSession())
prepareDestroy();
}
// end of hack
} else {
qCWarning(TcpServerSocketInterfaceLog) << "parsing error!";
} }
// end of hack
} while (!inputBuffer.isEmpty()); } while (!inputBuffer.isEmpty());
} }
@ -2172,9 +2187,12 @@ void WebsocketServerSocketInterface::flushOutputQueue()
unsigned int size = static_cast<unsigned int>(item.ByteSize()); unsigned int size = static_cast<unsigned int>(item.ByteSize());
#endif #endif
buf.resize(size); buf.resize(size);
item.SerializeToArray(buf.data(), size); if (item.SerializeToArray(buf.data(), size)) {
// In case socket->write() calls catchSocketError(), the mutex must not be locked during this call. // In case socket->write() calls catchSocketError(), the mutex must not be locked during this call.
writeToSocket(buf); writeToSocket(buf);
} else {
qCWarning(TcpServerSocketInterfaceLog) << "serialisation error!";
}
totalBytes += size; totalBytes += size;
locker.relock(); locker.relock();
@ -2190,30 +2208,37 @@ void WebsocketServerSocketInterface::binaryMessageReceived(const QByteArray &mes
servatrice->incRxBytes(message.size()); servatrice->incRxBytes(message.size());
CommandContainer newCommandContainer; CommandContainer newCommandContainer;
bool ok;
try { try {
newCommandContainer.ParseFromArray(message.data(), message.size()); ok = newCommandContainer.ParseFromArray(message.data(), message.size());
} catch (std::exception &e) { } catch (std::exception &e) {
qDebug() << "Caught std::exception in" << __FILE__ << __LINE__ << qCWarning(WebsocketServerSocketInterfaceLog) << "Caught std::exception in" << __FILE__ << __LINE__ <<
#ifdef _MSC_VER // Visual Studio #ifdef _MSC_VER // Visual Studio
__FUNCTION__; __FUNCTION__
#else #else
__PRETTY_FUNCTION__; __PRETTY_FUNCTION__
#endif #endif
qDebug() << "Exception:" << e.what(); << Qt::endl
qDebug() << "Message coming from:" << getAddress(); << "Exception:" << e.what() << Qt::endl
qDebug() << "Message length:" << message.size(); << "Message coming from:" << getAddress() << Qt::endl
qDebug() << "Message content:" << message.toHex(); << "Message length:" << message.size() << Qt::endl
<< "Message content:" << message.toHex();
} catch (...) { } catch (...) {
qDebug() << "Unhandled exception in" << __FILE__ << __LINE__ << qCWarning(WebsocketServerSocketInterfaceLog) << "Unhandled exception in" << __FILE__ << __LINE__ <<
#ifdef _MSC_VER // Visual Studio #ifdef _MSC_VER // Visual Studio
__FUNCTION__; __FUNCTION__
#else #else
__PRETTY_FUNCTION__; __PRETTY_FUNCTION__
#endif #endif
qDebug() << "Message coming from:" << getAddress(); << Qt::endl
<< "Message coming from:" << getAddress();
} }
processCommandContainer(newCommandContainer); if (ok) {
processCommandContainer(newCommandContainer);
} else {
qCWarning(WebsocketServerSocketInterfaceLog) << "parsing error!";
}
} }
bool AbstractServerSocketInterface::isPasswordLongEnough(const int passwordLength) bool AbstractServerSocketInterface::isPasswordLongEnough(const int passwordLength)