refactor: Send log level to daemon over IPC instead of when sending command
This commit is contained in:
@ -296,6 +296,7 @@ void MainWindow::connectSlots()
|
||||
|
||||
connect(&m_appConfig, &AppConfig::tlsChanged, this, &MainWindow::appConfigTlsChanged);
|
||||
connect(&m_appConfig, &AppConfig::screenNameChanged, this, &MainWindow::updateScreenName);
|
||||
connect(&m_appConfig, &AppConfig::logLevelChanged, &m_coreProcess, &CoreProcess::applyLogLevel);
|
||||
|
||||
connect(&m_coreProcess, &CoreProcess::starting, this, &MainWindow::coreProcessStarting, Qt::DirectConnection);
|
||||
connect(&m_coreProcess, &CoreProcess::error, this, &MainWindow::coreProcessError);
|
||||
@ -631,6 +632,8 @@ void MainWindow::open()
|
||||
qDebug() << "update check disabled";
|
||||
}
|
||||
|
||||
m_coreProcess.applyLogLevel();
|
||||
|
||||
if (m_appConfig.startedBefore()) {
|
||||
m_coreProcess.start();
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QVariant>
|
||||
|
||||
#include <functional>
|
||||
|
||||
using namespace deskflow::gui;
|
||||
@ -680,7 +681,10 @@ void AppConfig::setNetworkInterface(const QString &s)
|
||||
|
||||
void AppConfig::setLogLevel(int i)
|
||||
{
|
||||
const auto changed = (m_LogLevel != i);
|
||||
m_LogLevel = i;
|
||||
if (changed)
|
||||
Q_EMIT logLevelChanged();
|
||||
}
|
||||
|
||||
void AppConfig::setLogToFile(bool b)
|
||||
|
||||
@ -342,4 +342,5 @@ private:
|
||||
signals:
|
||||
void tlsChanged();
|
||||
void screenNameChanged();
|
||||
void logLevelChanged();
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2016 - 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
@ -9,20 +9,20 @@
|
||||
/**
|
||||
* @brief The elevate mode tristate determines two behaviors on Windows.
|
||||
*
|
||||
* The first, switch-on-desk-switch (SodS), passed through deskflowd as a
|
||||
* command line argument to deskflow core, determines if the server restarts
|
||||
* when switching Windows desktops (e.g. when Windows UAC dialog pops up).
|
||||
* The second, passed as a boolean flag to Deskflowd over the IPC inside
|
||||
* IpcMessageType::CommandMessage, determines whether Deskflow should be started
|
||||
* with elevated privileges.
|
||||
*
|
||||
* The matrix for these two behaviors is as follows:
|
||||
*
|
||||
* | SodS | Elevate |
|
||||
* | sods | elevate |
|
||||
* |-----------|------------|
|
||||
* kAutomatic | true | false |
|
||||
* kAlways | false | true |
|
||||
* kNever | false | false |
|
||||
*
|
||||
* The first, --stop-on-desk-switch (sods), is passed through the daemon as a
|
||||
* command line argument to the server/client, and determines if it restarts
|
||||
* when switching Windows desktops (e.g. when Windows UAC dialog pops up).
|
||||
*
|
||||
* The second, elevate, is passed as a boolean flag to the daemon over IPC,
|
||||
* and determines whether the server/client should be started with elevated privileges.
|
||||
*/
|
||||
enum class ElevateMode
|
||||
{
|
||||
|
||||
@ -242,6 +242,16 @@ void CoreProcess::onProcessFinished(int exitCode, QProcess::ExitStatus)
|
||||
}
|
||||
}
|
||||
|
||||
void CoreProcess::applyLogLevel()
|
||||
{
|
||||
if (m_appConfig.processMode() == ProcessMode::kService) {
|
||||
qDebug() << "setting daemon log level:" << m_appConfig.logLevelText();
|
||||
if (!m_daemonIpcClient->sendLogLevel(m_appConfig.logLevelText())) {
|
||||
qCritical() << "failed to set daemon ipc log level";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoreProcess::startForegroundProcess(const QString &app, const QStringList &args)
|
||||
{
|
||||
using enum ProcessState;
|
||||
@ -280,7 +290,12 @@ void CoreProcess::startProcessFromDaemon(const QString &app, const QStringList &
|
||||
QString commandQuoted = makeQuotedArgs(app, args);
|
||||
|
||||
qInfo("running command: %s", qPrintable(commandQuoted));
|
||||
m_daemonIpcClient->sendCommand(commandQuoted, m_appConfig.elevateMode());
|
||||
|
||||
if (!m_daemonIpcClient->sendCommand(commandQuoted, m_appConfig.elevateMode())) {
|
||||
qCritical("aborting process start, ipc connect failed");
|
||||
return;
|
||||
}
|
||||
|
||||
setProcessState(Started);
|
||||
}
|
||||
|
||||
|
||||
@ -90,6 +90,7 @@ public:
|
||||
void stop(std::optional<ProcessMode> processMode = std::nullopt);
|
||||
void restart();
|
||||
void cleanup();
|
||||
void applyLogLevel();
|
||||
|
||||
// getters
|
||||
Mode mode() const
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <QDebug>
|
||||
#include <QLocalSocket>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace deskflow::gui::ipc {
|
||||
|
||||
@ -20,27 +21,27 @@ DaemonIpcClient::DaemonIpcClient(QObject *parent) : QObject(parent), m_socket{ne
|
||||
{
|
||||
}
|
||||
|
||||
DaemonIpcClient::~DaemonIpcClient()
|
||||
{
|
||||
}
|
||||
|
||||
void DaemonIpcClient::connectToServer()
|
||||
bool DaemonIpcClient::connectToServer()
|
||||
{
|
||||
qInfo("connecting to daemon ipc");
|
||||
|
||||
m_socket->connectToServer(kDaemonIpcName);
|
||||
if (!m_socket->waitForConnected(kTimeout)) {
|
||||
qCritical() << "ipc client failed to connect to server:" << kDaemonIpcName;
|
||||
return;
|
||||
qWarning() << "ipc client failed to connect to server:" << kDaemonIpcName;
|
||||
return false;
|
||||
}
|
||||
|
||||
sendMessage("hello", "hello", false);
|
||||
if (!sendMessage("hello", "hello", false)) {
|
||||
qWarning() << "ipc client failed to send hello";
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(m_socket, &QLocalSocket::disconnected, this, &DaemonIpcClient::handleDisconnected);
|
||||
connect(m_socket, &QLocalSocket::errorOccurred, this, &DaemonIpcClient::handleErrorOccurred);
|
||||
|
||||
m_connected = true;
|
||||
qInfo() << "ipc client connected to server:" << kDaemonIpcName;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DaemonIpcClient::handleDisconnected()
|
||||
@ -55,50 +56,80 @@ void DaemonIpcClient::handleErrorOccurred()
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
void DaemonIpcClient::sendCommand(const QString &command, ElevateMode elevateMode)
|
||||
bool DaemonIpcClient::keepAlive()
|
||||
{
|
||||
sendMessage("elevate=" + QString::number(static_cast<int>(elevateMode)));
|
||||
sendMessage("command=" + command);
|
||||
sendMessage("restart");
|
||||
if (!isConnected() && !connectToServer()) {
|
||||
qWarning() << "ipc client keep alive failed to connect";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sendMessage("noop")) {
|
||||
qWarning() << "ipc client keep alive ping failed";
|
||||
m_connected = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DaemonIpcClient::sendMessage(const QString &message, const QString &expectAck, const bool expectConnected)
|
||||
bool DaemonIpcClient::sendLogLevel(const QString &logLevel)
|
||||
{
|
||||
if (!keepAlive())
|
||||
return false;
|
||||
|
||||
sendMessage("logLevel=" + logLevel);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DaemonIpcClient::sendCommand(const QString &command, ElevateMode elevateMode)
|
||||
{
|
||||
if (!keepAlive())
|
||||
return false;
|
||||
|
||||
sendMessage("elevate=" + (elevateMode == ElevateMode::kAlways ? QStringLiteral("yes") : QStringLiteral("no")));
|
||||
sendMessage("command=" + command);
|
||||
sendMessage("restart");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DaemonIpcClient::sendMessage(const QString &message, const QString &expectAck, const bool expectConnected)
|
||||
{
|
||||
if (expectConnected && !m_connected) {
|
||||
qCritical() << "cannot send command, ipc not connected";
|
||||
return;
|
||||
qWarning() << "cannot send command, ipc not connected";
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray messageData = message.toUtf8() + "\n";
|
||||
m_socket->write(messageData);
|
||||
if (!m_socket->waitForBytesWritten(kTimeout)) {
|
||||
qCritical() << "ipc client failed to write command";
|
||||
return;
|
||||
qWarning() << "ipc client failed to write command";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_socket->waitForReadyRead(kTimeout)) {
|
||||
qCritical() << "ipc client failed to read response";
|
||||
return;
|
||||
qWarning() << "ipc client failed to read response";
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray response = m_socket->readAll();
|
||||
if (response.isEmpty()) {
|
||||
qCritical() << "ipc client got empty response";
|
||||
return;
|
||||
qWarning() << "ipc client got empty response";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString responseData = QString::fromUtf8(response);
|
||||
if (responseData.isEmpty()) {
|
||||
qCritical() << "ipc client failed to convert response to string";
|
||||
return;
|
||||
qWarning() << "ipc client failed to convert response to string";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (responseData != expectAck + "\n") {
|
||||
qCritical() << "ipc client got unexpected response: " << responseData;
|
||||
return;
|
||||
qWarning() << "ipc client got unexpected response: " << responseData;
|
||||
return false;
|
||||
}
|
||||
|
||||
qInfo() << "ipc client sent message: " << messageData;
|
||||
qDebug() << "ipc client sent message: " << messageData;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace deskflow::gui::ipc
|
||||
|
||||
@ -19,10 +19,10 @@ class DaemonIpcClient : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DaemonIpcClient(QObject *parent = nullptr);
|
||||
~DaemonIpcClient();
|
||||
void connectToServer();
|
||||
void sendCommand(const QString &command, ElevateMode elevateMode);
|
||||
explicit DaemonIpcClient(QObject *parent = nullptr);
|
||||
bool connectToServer();
|
||||
bool sendLogLevel(const QString &logLevel);
|
||||
bool sendCommand(const QString &command, ElevateMode elevateMode);
|
||||
|
||||
bool isConnected() const
|
||||
{
|
||||
@ -34,7 +34,8 @@ private slots:
|
||||
void handleErrorOccurred();
|
||||
|
||||
private:
|
||||
void sendMessage(const QString &message, const QString &expectAck = "ok", const bool expectConnected = true);
|
||||
bool keepAlive();
|
||||
bool sendMessage(const QString &message, const QString &expectAck = "ok", const bool expectConnected = true);
|
||||
|
||||
private:
|
||||
QLocalSocket *m_socket;
|
||||
|
||||
Reference in New Issue
Block a user