feat(ipc): Differentiate between Daemon and Core IPC logs

This commit is contained in:
Nick Bolton 2026-03-31 10:06:00 +01:00
parent 682966fec0
commit 25f3eb3f22
8 changed files with 65 additions and 50 deletions

View file

@ -15,7 +15,7 @@ namespace deskflow::core::ipc {
static CoreIpcServer *s_instance = nullptr; static CoreIpcServer *s_instance = nullptr;
CoreIpcServer::CoreIpcServer(QObject *parent) : IpcServer(parent, kCoreIpcName) CoreIpcServer::CoreIpcServer(QObject *parent) : IpcServer(parent, kCoreIpcName, "core")
{ {
assert(s_instance == nullptr); assert(s_instance == nullptr);
s_instance = this; s_instance = this;

View file

@ -17,7 +17,7 @@ const auto kAckMessage = "ok";
const auto kErrorMessage = "error"; const auto kErrorMessage = "error";
DaemonIpcServer::DaemonIpcServer(QObject *parent, const QString &logFilename) DaemonIpcServer::DaemonIpcServer(QObject *parent, const QString &logFilename)
: IpcServer(parent, kDaemonIpcName), : IpcServer(parent, kDaemonIpcName, "daemon"),
m_logFilename(logFilename) m_logFilename(logFilename)
{ {
// do nothing // do nothing

View file

@ -14,10 +14,11 @@
namespace deskflow::core::ipc { namespace deskflow::core::ipc {
IpcServer::IpcServer(QObject *parent, const QString &serverName) IpcServer::IpcServer(QObject *parent, const QString &serverName, const QString &typeName)
: QObject(parent), : QObject(parent),
m_server{new QLocalServer(this)}, // NOSONAR - Qt memory m_server{new QLocalServer(this)}, // NOSONAR - Qt memory
m_serverName(serverName) m_serverName(serverName),
m_typeName(typeName.toUtf8())
{ {
// do nothing // do nothing
} }
@ -35,9 +36,9 @@ void IpcServer::listen()
connect(m_server, &QLocalServer::newConnection, this, &IpcServer::handleNewConnection); connect(m_server, &QLocalServer::newConnection, this, &IpcServer::handleNewConnection);
QLocalServer::removeServer(m_serverName); QLocalServer::removeServer(m_serverName);
if (m_server->listen(m_serverName)) { if (m_server->listen(m_serverName)) {
LOG_DEBUG("ipc server listening on: %s", m_serverName.toUtf8().constData()); LOG_DEBUG("%s ipc server listening on: %s", m_typeName.constData(), m_serverName.toUtf8().constData());
} else { } else {
LOG_ERR("ipc server failed to listen on: %s", m_serverName.toUtf8().constData()); LOG_ERR("%s ipc server failed to listen on: %s", m_typeName.constData(), m_serverName.toUtf8().constData());
} }
} }
@ -45,11 +46,11 @@ void IpcServer::handleNewConnection()
{ {
QLocalSocket *clientSocket = m_server->nextPendingConnection(); QLocalSocket *clientSocket = m_server->nextPendingConnection();
if (!clientSocket) { if (!clientSocket) {
LOG_ERR("ipc server failed to get new connection"); LOG_ERR("%s ipc server failed to get new connection", m_typeName.constData());
return; return;
} }
LOG_DEBUG("ipc server got new connection"); LOG_DEBUG("%s ipc server got new connection", m_typeName.constData());
m_clients.insert(clientSocket); m_clients.insert(clientSocket);
connect(clientSocket, &QLocalSocket::readyRead, this, &IpcServer::handleReadyRead); connect(clientSocket, &QLocalSocket::readyRead, this, &IpcServer::handleReadyRead);
@ -60,17 +61,17 @@ void IpcServer::handleNewConnection()
void IpcServer::handleReadyRead() void IpcServer::handleReadyRead()
{ {
const auto clientSocket = qobject_cast<QLocalSocket *>(sender()); const auto clientSocket = qobject_cast<QLocalSocket *>(sender());
LOG_DEBUG1("ipc server ready to read data"); LOG_DEBUG1("%s ipc server ready to read data", m_typeName.constData());
QByteArray data = clientSocket->readAll(); QByteArray data = clientSocket->readAll();
if (data.isEmpty()) { if (data.isEmpty()) {
LOG_WARN("ipc server got empty message"); LOG_WARN("%s ipc server got empty message", m_typeName.constData());
return; return;
} }
// we don't handle incomplete messages yet; each socket read must have delimiters. // we don't handle incomplete messages yet; each socket read must have delimiters.
if (!data.contains('\n')) { if (!data.contains('\n')) {
LOG_WARN("ipc server got incomplete message: %s", data.constData()); LOG_WARN("%s ipc server got incomplete message: %s", m_typeName.constData(), data.constData());
return; return;
} }
@ -87,7 +88,7 @@ void IpcServer::handleReadyRead()
void IpcServer::handleDisconnected() void IpcServer::handleDisconnected()
{ {
const auto clientSocket = qobject_cast<QLocalSocket *>(sender()); const auto clientSocket = qobject_cast<QLocalSocket *>(sender());
LOG_DEBUG("ipc server client disconnected"); LOG_DEBUG("%s ipc server client disconnected", m_typeName.constData());
m_clients.remove(clientSocket); m_clients.remove(clientSocket);
clientSocket->deleteLater(); clientSocket->deleteLater();
} }
@ -95,17 +96,17 @@ void IpcServer::handleDisconnected()
void IpcServer::handleErrorOccurred() void IpcServer::handleErrorOccurred()
{ {
const auto clientSocket = qobject_cast<QLocalSocket *>(sender()); const auto clientSocket = qobject_cast<QLocalSocket *>(sender());
LOG_ERR("ipc server client error: %s", clientSocket->errorString().toUtf8().constData()); LOG_ERR("%s ipc server client error: %s", m_typeName.constData(), clientSocket->errorString().toUtf8().constData());
m_clients.remove(clientSocket); m_clients.remove(clientSocket);
clientSocket->deleteLater(); clientSocket->deleteLater();
} }
void IpcServer::processMessage(QLocalSocket *clientSocket, const QString &message) void IpcServer::processMessage(QLocalSocket *clientSocket, const QString &message)
{ {
LOG_DEBUG1("ipc server got message: %s", message.toUtf8().constData()); LOG_DEBUG1("%s ipc server got message: %s", m_typeName.constData(), message.toUtf8().constData());
const auto parts = message.split('='); const auto parts = message.split('=');
if (parts.isEmpty()) { if (parts.isEmpty()) {
LOG_ERR("ipc server got invalid message: %s", message.toUtf8().constData()); LOG_ERR("%s ipc server got invalid message: %s", m_typeName.constData(), message.toUtf8().constData());
writeToClientSocket(clientSocket, "error"); writeToClientSocket(clientSocket, "error");
return; return;
} }
@ -113,29 +114,28 @@ void IpcServer::processMessage(QLocalSocket *clientSocket, const QString &messag
if (const auto &command = parts.at(0); command == "hello") { if (const auto &command = parts.at(0); command == "hello") {
const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha); const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha);
const auto clientVersion = parts.size() >= 2 ? parts.at(1) : QString(); const auto clientVersion = parts.size() >= 2 ? parts.at(1) : QString();
LOG_DEBUG("%s ipc server got hello message (version: %s)", m_typeName.constData(), versionId.toUtf8().constData());
if (clientVersion != versionId) { if (clientVersion != versionId) {
LOG_ERR( LOG_ERR("%s ipc client version mismatch (server: %s)", m_typeName.constData(), versionId.toUtf8().constData());
"ipc client version mismatch (client: %s, server: %s)",
clientVersion.isEmpty() ? "unknown" : clientVersion.toUtf8().constData(), versionId.toUtf8().constData()
);
writeToClientSocket(clientSocket, "error"); writeToClientSocket(clientSocket, "error");
clientSocket->flush(); clientSocket->flush();
clientSocket->disconnectFromServer(); clientSocket->disconnectFromServer();
return; return;
} }
LOG_DEBUG("ipc server got hello message, sending hello back"); LOG_DEBUG("%s ipc server sending hello back", m_typeName.constData());
writeToClientSocket(clientSocket, QString("hello=%1").arg(versionId)); writeToClientSocket(clientSocket, QString("hello=%1").arg(versionId));
// Replay messages that were queued before any clients connected. // Replay messages that were queued before any clients connected.
LOG_DEBUG1("ipc server replaying %d pending messages", m_pendingMessages.size()); LOG_DEBUG1("ipc server replaying %d pending messages", m_pendingMessages.size());
for (const auto &pending : std::as_const(m_pendingMessages)) { for (const auto &pending : std::as_const(m_pendingMessages)) {
LOG_DEBUG1("ipc server replaying: %s", pending.toUtf8().constData()); LOG_DEBUG1("%s ipc server replaying: %s", m_typeName.constData(), pending.toUtf8().constData());
writeToClientSocket(clientSocket, pending); writeToClientSocket(clientSocket, pending);
} }
m_pendingMessages.clear(); m_pendingMessages.clear();
} else if (command == "noop") { } else if (command == "noop") {
LOG_DEBUG("ipc server got noop message"); LOG_DEBUG("%s ipc server got noop message", m_typeName.constData());
writeToClientSocket(clientSocket, "ok"); writeToClientSocket(clientSocket, "ok");
} else { } else {
processCommand(clientSocket, command, parts); processCommand(clientSocket, command, parts);
@ -149,12 +149,17 @@ void IpcServer::broadcastCommand(const QString &command, const QString &args)
const auto message = args.isEmpty() ? command : command + "=" + args; const auto message = args.isEmpty() ? command : command + "=" + args;
if (m_clients.isEmpty()) { if (m_clients.isEmpty()) {
LOG_DEBUG1("ipc server has no clients, message queued: %s", message.toUtf8().constData()); LOG_DEBUG1(
"%s ipc server has no clients, message queued: %s", m_typeName.constData(), message.toUtf8().constData()
);
m_pendingMessages.append(message); m_pendingMessages.append(message);
return; return;
} }
LOG_DEBUG1("ipc server broadcasting message to %d clients: %s", m_clients.size(), message.toUtf8().constData()); LOG_DEBUG1(
"%s ipc server broadcasting message to %d clients: %s", m_typeName.constData(), m_clients.size(),
message.toUtf8().constData()
);
for (auto *client : std::as_const(m_clients)) { for (auto *client : std::as_const(m_clients)) {
writeToClientSocket(client, message); writeToClientSocket(client, message);
client->flush(); client->flush();
@ -166,9 +171,11 @@ void IpcServer::writeToClientSocket(QLocalSocket *&clientSocket, const QString &
QByteArray messageData = message.toUtf8() + '\n'; QByteArray messageData = message.toUtf8() + '\n';
qint64 bytesWritten = clientSocket->write(messageData); qint64 bytesWritten = clientSocket->write(messageData);
if (bytesWritten != messageData.size()) { if (bytesWritten != messageData.size()) {
LOG_ERR("ipc server failed to write full message to client socket"); LOG_ERR("%s ipc server failed to write full message to client socket", m_typeName.constData());
} else { } else {
LOG_DEBUG1("ipc server wrote message to client socket: %s", message.toUtf8().constData()); LOG_DEBUG1(
"%s ipc server wrote message to client socket: %s", m_typeName.constData(), message.toUtf8().constData()
);
} }
} }

View file

@ -19,7 +19,7 @@ class IpcServer : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit IpcServer(QObject *parent, const QString &serverName); explicit IpcServer(QObject *parent, const QString &serverName, const QString &typeName);
~IpcServer() override; ~IpcServer() override;
void listen(); void listen();
@ -54,6 +54,7 @@ private:
QSet<QLocalSocket *> m_clients; QSet<QLocalSocket *> m_clients;
QString m_serverName; QString m_serverName;
QStringList m_pendingMessages; QStringList m_pendingMessages;
QByteArray m_typeName;
}; };
} // namespace deskflow::core::ipc } // namespace deskflow::core::ipc

View file

@ -15,7 +15,7 @@
namespace deskflow::gui::ipc { namespace deskflow::gui::ipc {
CoreIpcClient::CoreIpcClient(QObject *parent) : IpcClient(parent, kCoreIpcName) CoreIpcClient::CoreIpcClient(QObject *parent) : IpcClient(parent, kCoreIpcName, "core")
{ {
// do nothing // do nothing
} }

View file

@ -12,7 +12,7 @@
namespace deskflow::gui::ipc { namespace deskflow::gui::ipc {
DaemonIpcClient::DaemonIpcClient(QObject *parent) : IpcClient(parent, kDaemonIpcName) DaemonIpcClient::DaemonIpcClient(QObject *parent) : IpcClient(parent, kDaemonIpcName, "daemon")
{ {
} }

View file

@ -14,10 +14,11 @@
namespace deskflow::gui::ipc { namespace deskflow::gui::ipc {
IpcClient::IpcClient(QObject *parent, const QString &socketName) IpcClient::IpcClient(QObject *parent, const QString &socketName, const QString &typeName)
: QObject(parent), : QObject(parent),
m_socket{new QLocalSocket(this)}, m_socket{new QLocalSocket(this)},
m_socketName(socketName) // NOSONAR - Qt memory m_socketName(socketName), // NOSONAR - Qt memory
m_typeName(typeName)
{ {
connect(m_socket, &QLocalSocket::disconnected, this, &IpcClient::handleDisconnected); connect(m_socket, &QLocalSocket::disconnected, this, &IpcClient::handleDisconnected);
connect(m_socket, &QLocalSocket::errorOccurred, this, &IpcClient::handleErrorOccurred); connect(m_socket, &QLocalSocket::errorOccurred, this, &IpcClient::handleErrorOccurred);
@ -27,17 +28,18 @@ IpcClient::IpcClient(QObject *parent, const QString &socketName)
void IpcClient::connectToServer() void IpcClient::connectToServer()
{ {
if (m_state == State::Connecting) { if (m_state == State::Connecting) {
qWarning() << "ipc client already connecting to server"; qWarning().noquote() << QStringLiteral("%1 ipc client already connecting to server").arg(m_typeName);
return; return;
} }
if (m_state != State::Unconnected) { if (m_state != State::Unconnected) {
qDebug() << "ipc client not in unconnected state, disconnecting"; qDebug().noquote() << QStringLiteral("%1 ipc client not in unconnected state, disconnecting").arg(m_typeName);
disconnectFromServer(); disconnectFromServer();
} }
if (m_socket->state() != QLocalSocket::UnconnectedState) { if (m_socket->state() != QLocalSocket::UnconnectedState) {
qWarning() << "ipc client socket not in unconnected state, disconnecting"; qWarning().noquote(
) << QStringLiteral("%1 ipc client socket not in unconnected state, disconnecting").arg(m_typeName);
disconnectFromServer(); disconnectFromServer();
} }
@ -50,16 +52,18 @@ void IpcClient::attemptConnection()
const auto kRetryLimit = 3; const auto kRetryLimit = 3;
if (m_retryCount >= kRetryLimit) { if (m_retryCount >= kRetryLimit) {
qWarning() << "ipc client failed to connect after" << kRetryLimit << "attempts"; qWarning().noquote() << QStringLiteral("%1 ipc client failed to connect after %2 attempts")
.arg(m_typeName, QString::number(kRetryLimit));
m_state = State::Unconnected; m_state = State::Unconnected;
Q_EMIT connectionFailed(); Q_EMIT connectionFailed();
return; return;
} }
if (m_retryCount == 0) { if (m_retryCount == 0) {
qDebug() << "ipc client connecting to server:" << m_socketName; qDebug().noquote() << QStringLiteral("%1 ipc client connecting to server: %2").arg(m_typeName, m_socketName);
} else { } else {
qDebug() << "ipc client retrying connection, attempt:" << m_retryCount + 1; qDebug().noquote() << QStringLiteral("%1 ipc client retrying connection, attempt: %2")
.arg(m_typeName, QString::number(m_retryCount + 1));
} }
m_state = State::Connecting; m_state = State::Connecting;
@ -69,8 +73,8 @@ void IpcClient::attemptConnection()
m_socket, &QLocalSocket::connected, this, m_socket, &QLocalSocket::connected, this,
[this] { [this] {
const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha); const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha);
m_socket->write(QString("hello=%1\n").arg(versionId).toUtf8()); m_socket->write(QStringLiteral("hello=%1\n").arg(versionId).toUtf8());
qDebug() << "ipc client sent hello with version:" << versionId; qDebug().noquote() << QStringLiteral("%1 ipc client sent hello with version: %2").arg(m_typeName, versionId);
}, },
Qt::SingleShotConnection Qt::SingleShotConnection
); );
@ -78,7 +82,8 @@ void IpcClient::attemptConnection()
connect( connect(
m_socket, &QLocalSocket::errorOccurred, this, m_socket, &QLocalSocket::errorOccurred, this,
[this] { [this] {
qWarning() << "ipc client failed to connect:" << m_socket->errorString(); qWarning().noquote(
) << QStringLiteral("%1 ipc client failed to connect: %2").arg(m_typeName, m_socket->errorString());
m_socket->disconnectFromServer(); m_socket->disconnectFromServer();
m_state = State::Unconnected; m_state = State::Unconnected;
QTimer::singleShot(0, this, &IpcClient::attemptConnection); QTimer::singleShot(0, this, &IpcClient::attemptConnection);
@ -92,7 +97,7 @@ void IpcClient::attemptConnection()
void IpcClient::disconnectFromServer() void IpcClient::disconnectFromServer()
{ {
m_state = State::Disconnecting; m_state = State::Disconnecting;
qDebug() << "ipc client disconnecting from server"; qDebug().noquote() << QStringLiteral("%1 ipc client disconnecting from server").arg(m_typeName);
m_socket->disconnectFromServer(); m_socket->disconnectFromServer();
m_state = State::Unconnected; m_state = State::Unconnected;
} }
@ -103,7 +108,7 @@ void IpcClient::handleDisconnected()
return; return;
} }
qDebug() << "ipc client disconnected from server"; qDebug().noquote() << QStringLiteral("%1 ipc client disconnected from server").arg(m_typeName);
const auto wasConnected = m_state == State::Connected; const auto wasConnected = m_state == State::Connected;
m_state = State::Unconnected; m_state = State::Unconnected;
@ -118,7 +123,7 @@ void IpcClient::handleErrorOccurred()
return; return;
} }
qWarning() << "ipc client error:" << m_socket->errorString(); qWarning().noquote() << QStringLiteral("%1 ipc client error: %2").arg(m_typeName, m_socket->errorString());
if (m_state == State::Connected) { if (m_state == State::Connected) {
disconnectFromServer(); disconnectFromServer();
@ -136,10 +141,10 @@ void IpcClient::handleReadyRead()
const auto message = QString::fromUtf8(data.left(index)); const auto message = QString::fromUtf8(data.left(index));
data.remove(0, index + 1); data.remove(0, index + 1);
qDebug("ipc client message: %s", message.toUtf8().constData()); qDebug().noquote() << QStringLiteral("%1 ipc client message: %2").arg(m_typeName, message);
const auto parts = message.split('='); const auto parts = message.split('=');
if (parts.isEmpty()) { if (parts.isEmpty()) {
qWarning("ipc client got invalid message: %s", message.toUtf8().constData()); qWarning().noquote() << QStringLiteral("%1 ipc client got invalid message: %2").arg(m_typeName, message);
continue; continue;
} }
@ -165,26 +170,27 @@ void IpcClient::handleHandshakeMessage(const QStringList &parts)
const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha); const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha);
const auto serverVersion = parts.size() >= 2 ? parts.at(1) : QString(); const auto serverVersion = parts.size() >= 2 ? parts.at(1) : QString();
if (serverVersion != versionId) { if (serverVersion != versionId) {
qCritical() << "ipc version mismatch (client:" << versionId << "server:" << serverVersion << ")"; qCritical().noquote(
) << QStringLiteral("%1 ipc version mismatch (client: %2 , server: %3)").arg(m_typeName, versionId, serverVersion);
disconnectFromServer(); disconnectFromServer();
Q_EMIT connectionFailed(); Q_EMIT connectionFailed();
return; return;
} }
m_state = State::Connected; m_state = State::Connected;
qDebug() << "ipc client connected"; qDebug().noquote() << QStringLiteral("%1 ipc client connected").arg(m_typeName);
Q_EMIT connected(); Q_EMIT connected();
} }
void IpcClient::sendMessage(const QString &message) void IpcClient::sendMessage(const QString &message)
{ {
if (m_state != State::Connected) { if (m_state != State::Connected) {
qWarning() << "cannot send command, ipc client not connected"; qWarning().noquote() << QStringLiteral("%1 cannot send command, ipc client not connected").arg(m_typeName);
return; return;
} }
m_socket->write(message.toUtf8() + "\n"); m_socket->write(message.toUtf8() + "\n");
qDebug() << "ipc client sent message:" << message; qDebug().noquote() << QStringLiteral("%1 ipc client sent message: %2").arg(m_typeName, message);
} }
} // namespace deskflow::gui::ipc } // namespace deskflow::gui::ipc

View file

@ -26,7 +26,7 @@ class IpcClient : public QObject
}; };
public: public:
explicit IpcClient(QObject *parent, const QString &socketName); explicit IpcClient(QObject *parent, const QString &socketName, const QString &typeName);
void connectToServer(); void connectToServer();
void disconnectFromServer(); void disconnectFromServer();
@ -62,6 +62,7 @@ private:
QString m_socketName; QString m_socketName;
QByteArray m_readBuffer; QByteArray m_readBuffer;
int m_retryCount{0}; int m_retryCount{0};
QString m_typeName;
}; };
} // namespace deskflow::gui::ipc } // namespace deskflow::gui::ipc