feat: Implement basic IPC connection between Daemon and GUI
This commit is contained in:
@ -12,23 +12,15 @@
|
||||
#include "base/Log.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#endif
|
||||
|
||||
#ifdef SYSAPI_UNIX
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DaemonApp app;
|
||||
return app.run(argc, argv);
|
||||
}
|
||||
|
||||
#elif SYSAPI_WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
// win32 instance needed for threading, etc.
|
||||
@ -45,4 +37,11 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
return DaemonApp::exec();
|
||||
}
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
return main(__argc, __argv);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "gui/constants.h"
|
||||
#include "gui/core/CoreProcess.h"
|
||||
#include "gui/diagnostic.h"
|
||||
#include "gui/ipc/DaemonIpcClient.h"
|
||||
#include "gui/messages.h"
|
||||
#include "gui/string_utils.h"
|
||||
#include "gui/style_utils.h"
|
||||
@ -70,6 +71,7 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
m_tlsUtility(appConfig),
|
||||
m_trayIcon{new QSystemTrayIcon(this)},
|
||||
m_guiDupeChecker{new QLocalServer(this)},
|
||||
m_daemonIpcClient{new ipc::DaemonIpcClient(this)},
|
||||
m_lblSecurityStatus{new QLabel(this)},
|
||||
m_lblStatus{new QLabel(this)},
|
||||
m_btnFingerprint{new QToolButton(this)},
|
||||
@ -167,6 +169,8 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
regenerateLocalFingerprints();
|
||||
}
|
||||
}
|
||||
|
||||
m_daemonIpcClient->connect();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
||||
@ -54,6 +54,10 @@ namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
namespace deskflow::gui::ipc {
|
||||
class DaemonIpcClient;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
using CoreMode = deskflow::gui::CoreProcess::Mode;
|
||||
@ -208,6 +212,7 @@ private:
|
||||
QStringList m_checkedServers;
|
||||
QSystemTrayIcon *m_trayIcon = nullptr;
|
||||
QLocalServer *m_guiDupeChecker = nullptr;
|
||||
deskflow::gui::ipc::DaemonIpcClient *m_daemonIpcClient = nullptr;
|
||||
|
||||
QLabel *m_lblSecurityStatus = nullptr;
|
||||
QLabel *m_lblStatus = nullptr;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2024 Chris Rizzitello <sithlord48@gmail.com>
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
@ -13,10 +13,11 @@ const auto kAppId = "@CMAKE_PROJECT_NAME@";
|
||||
const auto kAppDescription = "@CMAKE_PROJECT_DESCRIPTION@";
|
||||
const auto kVersion = "@CMAKE_PROJECT_VERSION@";
|
||||
const auto kVersionGitSha = "@GIT_SHA_SHORT@";
|
||||
const auto kDaemonIpcName = "@CMAKE_PROJECT_NAME@-daemon";
|
||||
|
||||
const auto kCopyright = //
|
||||
"Copyright @CMAKE_PROJECT_COPYRIGHT@\n"
|
||||
"Copyright (C) 2012-2024 Symless Ltd.\n"
|
||||
"Copyright (C) 2012-2025 Symless Ltd.\n"
|
||||
"Copyright (C) 2009-2012 Nick Bolton\n"
|
||||
"Copyright (C) 2002-2009 Chris Schoeneman";
|
||||
|
||||
@ -26,7 +27,6 @@ const auto kDebugBuild = true;
|
||||
const auto kDebugBuild = false;
|
||||
#endif
|
||||
|
||||
|
||||
const auto kSslDir = "tls";
|
||||
const auto kTlsDbSize = 2;
|
||||
const auto kCertificateFilename = "@CMAKE_PROJECT_NAME@.pem";
|
||||
|
||||
@ -145,8 +145,8 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE}
|
||||
XScreen.h
|
||||
languages/LanguageManager.cpp
|
||||
languages/LanguageManager.h
|
||||
ipc/IpcServer2.cpp
|
||||
ipc/IpcServer2.h
|
||||
ipc/DaemonIpcServer.cpp
|
||||
ipc/DaemonIpcServer.h
|
||||
)
|
||||
|
||||
find_package(Qt6 COMPONENTS Core Network)
|
||||
|
||||
@ -13,16 +13,15 @@
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "base/log_outputters.h"
|
||||
#include "common/constants.h"
|
||||
#include "common/ipc.h"
|
||||
#include "deskflow/App.h"
|
||||
#include "deskflow/ArgParser.h"
|
||||
#include "deskflow/ClientArgs.h"
|
||||
#include "deskflow/ServerArgs.h"
|
||||
#include "ipc/DaemonIpcServer.h"
|
||||
#include "ipc/IpcClientProxy.h"
|
||||
#include "ipc/IpcLogOutputter.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServer2.h"
|
||||
#include "ipc/IpcSettingMessage.h"
|
||||
#include "net/SocketMultiplexer.h"
|
||||
|
||||
@ -48,6 +47,7 @@
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace deskflow::core;
|
||||
|
||||
const char *const kLogFilename = "deskflow-daemon.log";
|
||||
|
||||
@ -99,13 +99,8 @@ int winMainLoopStatic(int, const char **)
|
||||
DaemonApp::DaemonApp(IEventQueue *events, int argc, char **argv)
|
||||
: QCoreApplication(argc, argv),
|
||||
m_events(events),
|
||||
m_ipcServer2{new deskflow::ipc::IpcServer2(this)}
|
||||
m_ipcServer{new ipc::DaemonIpcServer(this)}
|
||||
{
|
||||
// HACK: init used to be run, which was the main loop.
|
||||
// now it's used for arg parsing, install/uninstall, etc.
|
||||
if (init(argc, argv) != kExitSuccess) {
|
||||
exit(kExitFailed);
|
||||
}
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
@ -197,29 +192,11 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||
CLOG->insert(m_fileLogOutputter);
|
||||
}
|
||||
|
||||
// create socket multiplexer. this must happen after daemonization
|
||||
// on unix because threads evaporate across a fork().
|
||||
SocketMultiplexer multiplexer;
|
||||
|
||||
// uses event queue, must be created here.
|
||||
m_ipcServer = std::make_unique<IpcServer>(m_events, &multiplexer);
|
||||
|
||||
// send logging to gui via ipc, log system adopts outputter.
|
||||
m_ipcLogOutputter = std::make_unique<IpcLogOutputter>(*m_ipcServer, IpcClientType::GUI, true);
|
||||
CLOG->insert(m_ipcLogOutputter.get());
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
m_watchdog = std::make_unique<MSWindowsWatchdog>(false, *m_ipcServer, *m_ipcLogOutputter, foreground);
|
||||
m_watchdog = std::make_unique<MSWindowsWatchdog>(false, foreground);
|
||||
m_watchdog->setFileLogOutputter(m_fileLogOutputter);
|
||||
#endif
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIpcServer().messageReceived(), m_ipcServer.get(),
|
||||
new TMethodEventJob<DaemonApp>(this, &DaemonApp::handleIpcMessage)
|
||||
);
|
||||
|
||||
m_ipcServer->listen();
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
// install the platform event queue to handle service stop events.
|
||||
@ -273,113 +250,3 @@ std::string DaemonApp::logFilename()
|
||||
|
||||
return logFilename;
|
||||
}
|
||||
|
||||
void DaemonApp::handleIpcMessage(const Event &e, void *)
|
||||
{
|
||||
IpcMessage *m = static_cast<IpcMessage *>(e.getDataObject());
|
||||
switch (m->type()) {
|
||||
case IpcMessageType::Command: {
|
||||
IpcCommandMessage *cm = static_cast<IpcCommandMessage *>(m);
|
||||
std::string command = cm->command();
|
||||
|
||||
// if empty quotes, clear.
|
||||
if (command == "\"\"") {
|
||||
command.clear();
|
||||
}
|
||||
|
||||
if (!command.empty()) {
|
||||
LOG((CLOG_DEBUG "daemon got new core command"));
|
||||
LOG((CLOG_DEBUG2 "new command, elevate=%d command=%s", cm->elevate(), command.c_str()));
|
||||
|
||||
std::vector<std::string> argsArray;
|
||||
ArgParser::splitCommandString(command, argsArray);
|
||||
ArgParser argParser(NULL);
|
||||
const char **argv = argParser.getArgv(argsArray);
|
||||
int argc = static_cast<int>(argsArray.size());
|
||||
|
||||
if (isServerCommandLine(argsArray)) {
|
||||
auto serverArgs = new deskflow::ServerArgs();
|
||||
argParser.parseServerArgs(*serverArgs, argc, argv);
|
||||
} else {
|
||||
auto clientArgs = new deskflow::ClientArgs();
|
||||
argParser.parseClientArgs(*clientArgs, argc, argv);
|
||||
}
|
||||
|
||||
delete[] argv;
|
||||
std::string logLevel(ArgParser::argsBase().m_logFilter);
|
||||
if (!logLevel.empty()) {
|
||||
try {
|
||||
// change log level based on that in the command string
|
||||
// and change to that log level now.
|
||||
ARCH->setting("LogLevel", logLevel);
|
||||
CLOG->setFilter(logLevel.c_str());
|
||||
} catch (XArch &e) {
|
||||
LOG((CLOG_ERR "failed to save LogLevel setting, %s", e.what()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG((CLOG_DEBUG "empty command, elevate=%d", cm->elevate()));
|
||||
}
|
||||
|
||||
try {
|
||||
// store command in system settings. this is used when the daemon
|
||||
// next starts.
|
||||
ARCH->setting("Command", command);
|
||||
|
||||
// TODO: it would be nice to store bools/ints...
|
||||
ARCH->setting("Elevate", std::string(cm->elevate() ? "1" : "0"));
|
||||
} catch (XArch &e) {
|
||||
LOG((CLOG_ERR "failed to save settings, %s", e.what()));
|
||||
}
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
// tell the relauncher about the new command. this causes the
|
||||
// relauncher to stop the existing command and start the new
|
||||
// command.
|
||||
m_watchdog->setCommand(command, cm->elevate());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case IpcMessageType::Hello: {
|
||||
IpcHelloMessage *hm = static_cast<IpcHelloMessage *>(m);
|
||||
std::string type;
|
||||
switch (hm->clientType()) {
|
||||
case IpcClientType::GUI:
|
||||
type = "gui";
|
||||
break;
|
||||
case IpcClientType::Node:
|
||||
type = "node";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG "ipc hello, type=%s", type.c_str()));
|
||||
|
||||
// TODO: implement hello back handling in s1 gui and node (server/client).
|
||||
if (hm->clientType() == IpcClientType::GUI) {
|
||||
LOG((CLOG_DEBUG "sending ipc hello back"));
|
||||
IpcHelloBackMessage hbm;
|
||||
m_ipcServer->send(hbm, hm->clientType());
|
||||
}
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
std::string watchdogStatus = m_watchdog->isProcessRunning() ? "active" : "idle";
|
||||
LOG((CLOG_INFO "service status: %s", watchdogStatus.c_str()));
|
||||
#endif
|
||||
|
||||
m_ipcLogOutputter->notifyBuffer();
|
||||
break;
|
||||
}
|
||||
|
||||
case IpcMessageType::Setting:
|
||||
updateSetting(*m);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG((CLOG_DEBUG "ipc message ignored"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ipc/IpcServer.h"
|
||||
#include "common/common.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -14,12 +14,13 @@
|
||||
#include <QCoreApplication>
|
||||
|
||||
class Event;
|
||||
class IEventQueue;
|
||||
class IpcLogOutputter;
|
||||
class FileLogOutputter;
|
||||
class QLocalServer;
|
||||
|
||||
namespace deskflow::ipc {
|
||||
class IpcServer2;
|
||||
namespace deskflow::core::ipc {
|
||||
class DaemonIpcServer;
|
||||
}
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
@ -33,11 +34,11 @@ class DaemonApp : public QCoreApplication
|
||||
public:
|
||||
DaemonApp(IEventQueue *events, int argc, char **argv);
|
||||
~DaemonApp();
|
||||
int init(int argc, char **argv);
|
||||
void startAsync();
|
||||
void mainLoop(bool logToFile, bool foreground = false);
|
||||
|
||||
private:
|
||||
int init(int argc, char **argv);
|
||||
void daemonize();
|
||||
void foregroundError(const char *message);
|
||||
std::string logFilename();
|
||||
@ -51,9 +52,8 @@ public:
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::unique_ptr<IpcServer> m_ipcServer;
|
||||
std::unique_ptr<IpcLogOutputter> m_ipcLogOutputter;
|
||||
IEventQueue *m_events = nullptr;
|
||||
FileLogOutputter *m_fileLogOutputter = nullptr;
|
||||
std::unique_ptr<deskflow::ipc::IpcServer2> m_ipcServer2;
|
||||
std::unique_ptr<deskflow::core::ipc::DaemonIpcServer> m_ipcServer;
|
||||
};
|
||||
|
||||
69
src/lib/deskflow/ipc/DaemonIpcServer.cpp
Normal file
69
src/lib/deskflow/ipc/DaemonIpcServer.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "DaemonIpcServer.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "common/constants.h"
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
|
||||
namespace deskflow::core::ipc {
|
||||
|
||||
DaemonIpcServer::DaemonIpcServer(QObject *parent) : QObject(parent), m_server{new QLocalServer(this)}
|
||||
{
|
||||
// Daemon runs as system, but GUI runs as regular user, so we need to allow world access.
|
||||
m_server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
|
||||
connect(m_server, &QLocalServer::newConnection, this, &DaemonIpcServer::handleNewConnection);
|
||||
m_server->removeServer(kDaemonIpcName);
|
||||
if (m_server->listen(kDaemonIpcName)) {
|
||||
LOG_DEBUG("ipc server listening on: %s", kDaemonIpcName);
|
||||
} else {
|
||||
LOG_ERR("ipc server failed to listen on: %s", kDaemonIpcName);
|
||||
}
|
||||
}
|
||||
|
||||
DaemonIpcServer::~DaemonIpcServer()
|
||||
{
|
||||
m_server->close();
|
||||
}
|
||||
|
||||
void DaemonIpcServer::handleNewConnection()
|
||||
{
|
||||
QLocalSocket *clientSocket = m_server->nextPendingConnection();
|
||||
if (!clientSocket) {
|
||||
LOG_ERR("ipc server failed to get new connection");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("ipc server got new connection");
|
||||
|
||||
connect(clientSocket, &QLocalSocket::readyRead, this, [clientSocket]() {
|
||||
LOG_DEBUG("ipc server ready to read data");
|
||||
|
||||
QByteArray data = clientSocket->readAll();
|
||||
if (data.isEmpty()) {
|
||||
LOG_WARN("ipc server got empty message");
|
||||
return;
|
||||
}
|
||||
|
||||
QString dataStr = QString::fromUtf8(data);
|
||||
if (dataStr.isEmpty()) {
|
||||
LOG_ERR("ipc server failed to convert message to string");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataStr == "hello") {
|
||||
LOG_DEBUG("ipc server got message: %s", data.constData());
|
||||
clientSocket->write("hello");
|
||||
clientSocket->flush();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace deskflow::core::ipc
|
||||
@ -10,18 +10,21 @@
|
||||
|
||||
class QLocalServer;
|
||||
|
||||
namespace deskflow::ipc {
|
||||
namespace deskflow::core::ipc {
|
||||
|
||||
class IpcServer2 : public QObject
|
||||
class DaemonIpcServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IpcServer2(QObject *parent);
|
||||
~IpcServer2();
|
||||
DaemonIpcServer(QObject *parent);
|
||||
~DaemonIpcServer();
|
||||
|
||||
private slots:
|
||||
void handleNewConnection();
|
||||
|
||||
private:
|
||||
QLocalServer *m_server;
|
||||
};
|
||||
|
||||
} // namespace deskflow::ipc
|
||||
} // namespace deskflow::core::ipc
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "IpcServer2.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
|
||||
#include <QLocalServer>
|
||||
|
||||
namespace deskflow::ipc {
|
||||
|
||||
const auto kServerName = QStringLiteral("deskflow-daemon");
|
||||
|
||||
IpcServer2::IpcServer2(QObject *parent) : QObject(parent), m_server{new QLocalServer(this)}
|
||||
{
|
||||
m_server->removeServer(kServerName);
|
||||
m_server->listen(kServerName);
|
||||
LOG_INFO("ipc server listening on %s", kServerName.toStdString().c_str());
|
||||
}
|
||||
|
||||
IpcServer2::~IpcServer2()
|
||||
{
|
||||
m_server->close();
|
||||
}
|
||||
|
||||
} // namespace deskflow::ipc
|
||||
@ -69,6 +69,8 @@ add_library(${target} STATIC
|
||||
ipc/QDataStreamProxy.h
|
||||
ipc/QIpcClient.cpp
|
||||
ipc/QIpcClient.h
|
||||
ipc/DaemonIpcClient.cpp
|
||||
ipc/DaemonIpcClient.h
|
||||
proxy/QNetworkAccessManagerProxy.cpp
|
||||
proxy/QNetworkAccessManagerProxy.h
|
||||
proxy/QProcessProxy.cpp
|
||||
|
||||
66
src/lib/gui/ipc/DaemonIpcClient.cpp
Normal file
66
src/lib/gui/ipc/DaemonIpcClient.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "DaemonIpcClient.h"
|
||||
|
||||
#include "common/constants.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLocalSocket>
|
||||
#include <QObject>
|
||||
|
||||
namespace deskflow::gui::ipc {
|
||||
|
||||
const auto kTimeout = 1000;
|
||||
|
||||
DaemonIpcClient::DaemonIpcClient(QObject *parent) : QObject(parent), socket{new QLocalSocket(this)}
|
||||
{
|
||||
}
|
||||
|
||||
DaemonIpcClient::~DaemonIpcClient()
|
||||
{
|
||||
}
|
||||
|
||||
void DaemonIpcClient::connect()
|
||||
{
|
||||
socket->connectToServer(kDaemonIpcName);
|
||||
if (!socket->waitForConnected(kTimeout)) {
|
||||
qCritical() << "ipc client failed to connect to server:" << kDaemonIpcName;
|
||||
return;
|
||||
}
|
||||
|
||||
socket->write("hello");
|
||||
if (!socket->waitForBytesWritten(kTimeout)) {
|
||||
qCritical() << "ipc client failed to write message";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!socket->waitForReadyRead(kTimeout)) {
|
||||
qCritical() << "ipc client failed to read response";
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray response = socket->readAll();
|
||||
if (response.isEmpty()) {
|
||||
qCritical() << "ipc client got empty response";
|
||||
return;
|
||||
}
|
||||
|
||||
QString responseData = QString::fromUtf8(response);
|
||||
if (responseData.isEmpty()) {
|
||||
qCritical() << "ipc client failed to convert response to string";
|
||||
return;
|
||||
}
|
||||
|
||||
if (responseData != "hello") {
|
||||
qCritical() << "ipc client got unexpected response: " << responseData;
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "ipc client connected to server:" << kDaemonIpcName;
|
||||
}
|
||||
|
||||
} // namespace deskflow::gui::ipc
|
||||
28
src/lib/gui/ipc/DaemonIpcClient.h
Normal file
28
src/lib/gui/ipc/DaemonIpcClient.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QLocalSocket;
|
||||
|
||||
namespace deskflow::gui::ipc {
|
||||
|
||||
class DaemonIpcClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DaemonIpcClient(QObject *parent = nullptr);
|
||||
~DaemonIpcClient();
|
||||
void connect();
|
||||
|
||||
private:
|
||||
QLocalSocket *socket;
|
||||
};
|
||||
|
||||
} // namespace deskflow::gui::ipc
|
||||
@ -113,12 +113,12 @@ DWORD MSWindowsProcess::waitForExit()
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
void MSWindowsProcess::shutdown(IpcServer &ipcServer, int timeout)
|
||||
void MSWindowsProcess::shutdown(int timeout)
|
||||
{
|
||||
shutdown(m_info.hProcess, m_info.dwProcessId, ipcServer, timeout);
|
||||
shutdown(m_info.hProcess, m_info.dwProcessId, timeout);
|
||||
}
|
||||
|
||||
void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, IpcServer &ipcServer, int timeout)
|
||||
void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, int timeout)
|
||||
{
|
||||
LOG_DEBUG("shutting down process %d", pid);
|
||||
|
||||
@ -129,9 +129,6 @@ void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, IpcServer &ipcServer,
|
||||
return;
|
||||
}
|
||||
|
||||
IpcShutdownMessage shutdown;
|
||||
ipcServer.send(shutdown, IpcClientType::Node);
|
||||
|
||||
// wait for process to exit gracefully.
|
||||
double start = ARCH->time();
|
||||
while (true) { // NOSONAR -- Multiple breaks necessary
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ipc/IpcServer.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
@ -27,7 +25,7 @@ public:
|
||||
|
||||
BOOL startInForeground();
|
||||
BOOL startAsUser(HANDLE userToken, LPSECURITY_ATTRIBUTES sa);
|
||||
void shutdown(IpcServer &ipcServer, int timeout = kDefaultShutdownTimeout);
|
||||
void shutdown(int timeout = kDefaultShutdownTimeout);
|
||||
DWORD waitForExit();
|
||||
void createPipes();
|
||||
std::string readStdOutput();
|
||||
@ -38,7 +36,7 @@ public:
|
||||
return m_info;
|
||||
}
|
||||
|
||||
static void shutdown(HANDLE handle, DWORD pid, IpcServer &ipcServer, int timeout = kDefaultShutdownTimeout);
|
||||
static void shutdown(HANDLE handle, DWORD pid, int timeout = kDefaultShutdownTimeout);
|
||||
|
||||
private:
|
||||
void setStartupInfo(STARTUPINFO &si);
|
||||
|
||||
@ -57,17 +57,13 @@ typedef VOID(WINAPI *SendSas)(BOOL asUser);
|
||||
|
||||
const char g_activeDesktop[] = {"activeDesktop:"};
|
||||
|
||||
MSWindowsWatchdog::MSWindowsWatchdog(
|
||||
bool autoDetectCommand, IpcServer &ipcServer, IpcLogOutputter &ipcLogOutputter, bool foreground
|
||||
)
|
||||
MSWindowsWatchdog::MSWindowsWatchdog(bool autoDetectCommand, bool foreground)
|
||||
: m_thread(NULL),
|
||||
m_autoDetectCommand(autoDetectCommand),
|
||||
m_monitoring(true),
|
||||
m_commandChanged(false),
|
||||
m_outputWritePipe(nullptr),
|
||||
m_outputReadPipe(nullptr),
|
||||
m_ipcServer(ipcServer),
|
||||
m_ipcLogOutputter(ipcLogOutputter),
|
||||
m_elevateProcess(false),
|
||||
m_processFailures(0),
|
||||
m_processStarted(false),
|
||||
@ -265,7 +261,7 @@ void MSWindowsWatchdog::mainLoop(void *)
|
||||
|
||||
if (m_process != nullptr) {
|
||||
LOG((CLOG_DEBUG "terminated running process on exit"));
|
||||
m_process->shutdown(m_ipcServer);
|
||||
m_process->shutdown();
|
||||
m_process.reset();
|
||||
m_processStarted = false;
|
||||
}
|
||||
@ -301,7 +297,7 @@ void MSWindowsWatchdog::startProcess()
|
||||
|
||||
if (m_process != nullptr) {
|
||||
LOG((CLOG_DEBUG "closing existing process to make way for new one"));
|
||||
m_process->shutdown(m_ipcServer);
|
||||
m_process->shutdown();
|
||||
m_process.reset();
|
||||
m_processStarted = false;
|
||||
}
|
||||
@ -409,8 +405,6 @@ void MSWindowsWatchdog::outputLoop(void *)
|
||||
} else {
|
||||
buffer[bytesRead] = '\0';
|
||||
|
||||
m_ipcLogOutputter.write(kINFO, buffer);
|
||||
|
||||
if (m_fileLogOutputter != NULL) {
|
||||
m_fileLogOutputter->write(kINFO, buffer);
|
||||
}
|
||||
@ -433,7 +427,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
|
||||
LOG_INFO("daemon shutting down existing processes");
|
||||
|
||||
if (m_process != nullptr) {
|
||||
m_process->shutdown(m_ipcServer);
|
||||
m_process->shutdown();
|
||||
m_process.reset();
|
||||
m_processStarted = false;
|
||||
}
|
||||
@ -468,7 +462,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
|
||||
_stricmp(entry.szExeFile, "deskflow-core.exe") == 0) {
|
||||
|
||||
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
|
||||
deskflow::platform::MSWindowsProcess::shutdown(handle, entry.th32ProcessID, m_ipcServer);
|
||||
deskflow::platform::MSWindowsProcess::shutdown(handle, entry.th32ProcessID);
|
||||
CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class FileLogOutputter;
|
||||
class MSWindowsWatchdog
|
||||
{
|
||||
public:
|
||||
MSWindowsWatchdog(bool autoDetectCommand, IpcServer &ipcServer, IpcLogOutputter &ipcLogOutputter, bool foreground);
|
||||
MSWindowsWatchdog(bool autoDetectCommand, bool foreground);
|
||||
virtual ~MSWindowsWatchdog();
|
||||
|
||||
void startAsync();
|
||||
@ -65,8 +65,6 @@ private:
|
||||
HANDLE m_outputWritePipe;
|
||||
HANDLE m_outputReadPipe;
|
||||
Thread *m_outputThread;
|
||||
IpcServer &m_ipcServer;
|
||||
IpcLogOutputter &m_ipcLogOutputter;
|
||||
bool m_elevateProcess;
|
||||
MSWindowsSession m_session;
|
||||
int m_processFailures;
|
||||
|
||||
Reference in New Issue
Block a user