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;
CoreIpcServer::CoreIpcServer(QObject *parent) : IpcServer(parent, kCoreIpcName)
CoreIpcServer::CoreIpcServer(QObject *parent) : IpcServer(parent, kCoreIpcName, "core")
{
assert(s_instance == nullptr);
s_instance = this;

View file

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

View file

@ -14,10 +14,11 @@
namespace deskflow::core::ipc {
IpcServer::IpcServer(QObject *parent, const QString &serverName)
IpcServer::IpcServer(QObject *parent, const QString &serverName, const QString &typeName)
: QObject(parent),
m_server{new QLocalServer(this)}, // NOSONAR - Qt memory
m_serverName(serverName)
m_serverName(serverName),
m_typeName(typeName.toUtf8())
{
// do nothing
}
@ -35,9 +36,9 @@ void IpcServer::listen()
connect(m_server, &QLocalServer::newConnection, this, &IpcServer::handleNewConnection);
QLocalServer::removeServer(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 {
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();
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;
}
LOG_DEBUG("ipc server got new connection");
LOG_DEBUG("%s ipc server got new connection", m_typeName.constData());
m_clients.insert(clientSocket);
connect(clientSocket, &QLocalSocket::readyRead, this, &IpcServer::handleReadyRead);
@ -60,17 +61,17 @@ void IpcServer::handleNewConnection()
void IpcServer::handleReadyRead()
{
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();
if (data.isEmpty()) {
LOG_WARN("ipc server got empty message");
LOG_WARN("%s ipc server got empty message", m_typeName.constData());
return;
}
// we don't handle incomplete messages yet; each socket read must have delimiters.
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;
}
@ -87,7 +88,7 @@ void IpcServer::handleReadyRead()
void IpcServer::handleDisconnected()
{
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);
clientSocket->deleteLater();
}
@ -95,17 +96,17 @@ void IpcServer::handleDisconnected()
void IpcServer::handleErrorOccurred()
{
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);
clientSocket->deleteLater();
}
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('=');
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");
return;
}
@ -113,29 +114,28 @@ void IpcServer::processMessage(QLocalSocket *clientSocket, const QString &messag
if (const auto &command = parts.at(0); command == "hello") {
const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha);
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) {
LOG_ERR(
"ipc client version mismatch (client: %s, server: %s)",
clientVersion.isEmpty() ? "unknown" : clientVersion.toUtf8().constData(), versionId.toUtf8().constData()
);
LOG_ERR("%s ipc client version mismatch (server: %s)", m_typeName.constData(), versionId.toUtf8().constData());
writeToClientSocket(clientSocket, "error");
clientSocket->flush();
clientSocket->disconnectFromServer();
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));
// Replay messages that were queued before any clients connected.
LOG_DEBUG1("ipc server replaying %d pending messages", m_pendingMessages.size());
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);
}
m_pendingMessages.clear();
} 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");
} else {
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;
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);
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)) {
writeToClientSocket(client, message);
client->flush();
@ -166,9 +171,11 @@ void IpcServer::writeToClientSocket(QLocalSocket *&clientSocket, const QString &
QByteArray messageData = message.toUtf8() + '\n';
qint64 bytesWritten = clientSocket->write(messageData);
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 {
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
public:
explicit IpcServer(QObject *parent, const QString &serverName);
explicit IpcServer(QObject *parent, const QString &serverName, const QString &typeName);
~IpcServer() override;
void listen();
@ -54,6 +54,7 @@ private:
QSet<QLocalSocket *> m_clients;
QString m_serverName;
QStringList m_pendingMessages;
QByteArray m_typeName;
};
} // namespace deskflow::core::ipc

View file

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

View file

@ -12,7 +12,7 @@
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 {
IpcClient::IpcClient(QObject *parent, const QString &socketName)
IpcClient::IpcClient(QObject *parent, const QString &socketName, const QString &typeName)
: QObject(parent),
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::errorOccurred, this, &IpcClient::handleErrorOccurred);
@ -27,17 +28,18 @@ IpcClient::IpcClient(QObject *parent, const QString &socketName)
void IpcClient::connectToServer()
{
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;
}
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();
}
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();
}
@ -50,16 +52,18 @@ void IpcClient::attemptConnection()
const auto kRetryLimit = 3;
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;
Q_EMIT connectionFailed();
return;
}
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 {
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;
@ -69,8 +73,8 @@ void IpcClient::attemptConnection()
m_socket, &QLocalSocket::connected, this,
[this] {
const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha);
m_socket->write(QString("hello=%1\n").arg(versionId).toUtf8());
qDebug() << "ipc client sent hello with version:" << versionId;
m_socket->write(QStringLiteral("hello=%1\n").arg(versionId).toUtf8());
qDebug().noquote() << QStringLiteral("%1 ipc client sent hello with version: %2").arg(m_typeName, versionId);
},
Qt::SingleShotConnection
);
@ -78,7 +82,8 @@ void IpcClient::attemptConnection()
connect(
m_socket, &QLocalSocket::errorOccurred, 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_state = State::Unconnected;
QTimer::singleShot(0, this, &IpcClient::attemptConnection);
@ -92,7 +97,7 @@ void IpcClient::attemptConnection()
void IpcClient::disconnectFromServer()
{
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_state = State::Unconnected;
}
@ -103,7 +108,7 @@ void IpcClient::handleDisconnected()
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;
m_state = State::Unconnected;
@ -118,7 +123,7 @@ void IpcClient::handleErrorOccurred()
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) {
disconnectFromServer();
@ -136,10 +141,10 @@ void IpcClient::handleReadyRead()
const auto message = QString::fromUtf8(data.left(index));
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('=');
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;
}
@ -165,26 +170,27 @@ void IpcClient::handleHandshakeMessage(const QStringList &parts)
const auto versionId = QStringLiteral("%1+%2").arg(kVersion, kVersionGitSha);
const auto serverVersion = parts.size() >= 2 ? parts.at(1) : QString();
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();
Q_EMIT connectionFailed();
return;
}
m_state = State::Connected;
qDebug() << "ipc client connected";
qDebug().noquote() << QStringLiteral("%1 ipc client connected").arg(m_typeName);
Q_EMIT connected();
}
void IpcClient::sendMessage(const QString &message)
{
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;
}
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

View file

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