feat: Implement basic IPC connection between Daemon and GUI

This commit is contained in:
Nick Bolton 2025-02-06 12:03:51 +00:00
parent c0094554b1
commit 0d2d9f385d
17 changed files with 219 additions and 218 deletions

View file

@ -12,23 +12,15 @@
#include "base/Log.h" #include "base/Log.h"
#if SYSAPI_WIN32 #if SYSAPI_WIN32
#include "arch/win32/ArchMiscWindows.h" #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 #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) #endif
int main(int argc, char **argv)
{ {
#if SYSAPI_WIN32 #if SYSAPI_WIN32
// win32 instance needed for threading, etc. // win32 instance needed for threading, etc.
@ -45,4 +37,11 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
return DaemonApp::exec(); return DaemonApp::exec();
} }
#if SYSAPI_WIN32
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
return main(__argc, __argv);
}
#endif #endif

View file

@ -21,6 +21,7 @@
#include "gui/constants.h" #include "gui/constants.h"
#include "gui/core/CoreProcess.h" #include "gui/core/CoreProcess.h"
#include "gui/diagnostic.h" #include "gui/diagnostic.h"
#include "gui/ipc/DaemonIpcClient.h"
#include "gui/messages.h" #include "gui/messages.h"
#include "gui/string_utils.h" #include "gui/string_utils.h"
#include "gui/style_utils.h" #include "gui/style_utils.h"
@ -70,6 +71,7 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
m_tlsUtility(appConfig), m_tlsUtility(appConfig),
m_trayIcon{new QSystemTrayIcon(this)}, m_trayIcon{new QSystemTrayIcon(this)},
m_guiDupeChecker{new QLocalServer(this)}, m_guiDupeChecker{new QLocalServer(this)},
m_daemonIpcClient{new ipc::DaemonIpcClient(this)},
m_lblSecurityStatus{new QLabel(this)}, m_lblSecurityStatus{new QLabel(this)},
m_lblStatus{new QLabel(this)}, m_lblStatus{new QLabel(this)},
m_btnFingerprint{new QToolButton(this)}, m_btnFingerprint{new QToolButton(this)},
@ -167,6 +169,8 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
regenerateLocalFingerprints(); regenerateLocalFingerprints();
} }
} }
m_daemonIpcClient->connect();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()

View file

@ -54,6 +54,10 @@ namespace Ui {
class MainWindow; class MainWindow;
} }
namespace deskflow::gui::ipc {
class DaemonIpcClient;
}
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
using CoreMode = deskflow::gui::CoreProcess::Mode; using CoreMode = deskflow::gui::CoreProcess::Mode;
@ -208,6 +212,7 @@ private:
QStringList m_checkedServers; QStringList m_checkedServers;
QSystemTrayIcon *m_trayIcon = nullptr; QSystemTrayIcon *m_trayIcon = nullptr;
QLocalServer *m_guiDupeChecker = nullptr; QLocalServer *m_guiDupeChecker = nullptr;
deskflow::gui::ipc::DaemonIpcClient *m_daemonIpcClient = nullptr;
QLabel *m_lblSecurityStatus = nullptr; QLabel *m_lblSecurityStatus = nullptr;
QLabel *m_lblStatus = nullptr; QLabel *m_lblStatus = nullptr;

View file

@ -1,7 +1,7 @@
/* /*
* Deskflow -- mouse and keyboard sharing utility * Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Chris Rizzitello <sithlord48@gmail.com> * 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-FileCopyrightText: (C) 2002 Chris Schoeneman
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception * 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 kAppDescription = "@CMAKE_PROJECT_DESCRIPTION@";
const auto kVersion = "@CMAKE_PROJECT_VERSION@"; const auto kVersion = "@CMAKE_PROJECT_VERSION@";
const auto kVersionGitSha = "@GIT_SHA_SHORT@"; const auto kVersionGitSha = "@GIT_SHA_SHORT@";
const auto kDaemonIpcName = "@CMAKE_PROJECT_NAME@-daemon";
const auto kCopyright = // const auto kCopyright = //
"Copyright @CMAKE_PROJECT_COPYRIGHT@\n" "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) 2009-2012 Nick Bolton\n"
"Copyright (C) 2002-2009 Chris Schoeneman"; "Copyright (C) 2002-2009 Chris Schoeneman";
@ -26,7 +27,6 @@ const auto kDebugBuild = true;
const auto kDebugBuild = false; const auto kDebugBuild = false;
#endif #endif
const auto kSslDir = "tls"; const auto kSslDir = "tls";
const auto kTlsDbSize = 2; const auto kTlsDbSize = 2;
const auto kCertificateFilename = "@CMAKE_PROJECT_NAME@.pem"; const auto kCertificateFilename = "@CMAKE_PROJECT_NAME@.pem";

View file

@ -145,8 +145,8 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE}
XScreen.h XScreen.h
languages/LanguageManager.cpp languages/LanguageManager.cpp
languages/LanguageManager.h languages/LanguageManager.h
ipc/IpcServer2.cpp ipc/DaemonIpcServer.cpp
ipc/IpcServer2.h ipc/DaemonIpcServer.h
) )
find_package(Qt6 COMPONENTS Core Network) find_package(Qt6 COMPONENTS Core Network)

View file

@ -13,16 +13,15 @@
#include "base/Log.h" #include "base/Log.h"
#include "base/TMethodEventJob.h" #include "base/TMethodEventJob.h"
#include "base/log_outputters.h" #include "base/log_outputters.h"
#include "common/constants.h"
#include "common/ipc.h" #include "common/ipc.h"
#include "deskflow/App.h" #include "deskflow/App.h"
#include "deskflow/ArgParser.h" #include "deskflow/ArgParser.h"
#include "deskflow/ClientArgs.h" #include "deskflow/ClientArgs.h"
#include "deskflow/ServerArgs.h" #include "deskflow/ServerArgs.h"
#include "ipc/DaemonIpcServer.h"
#include "ipc/IpcClientProxy.h" #include "ipc/IpcClientProxy.h"
#include "ipc/IpcLogOutputter.h" #include "ipc/IpcLogOutputter.h"
#include "ipc/IpcMessage.h" #include "ipc/IpcMessage.h"
#include "ipc/IpcServer2.h"
#include "ipc/IpcSettingMessage.h" #include "ipc/IpcSettingMessage.h"
#include "net/SocketMultiplexer.h" #include "net/SocketMultiplexer.h"
@ -48,6 +47,7 @@
#include <string> #include <string>
using namespace std; using namespace std;
using namespace deskflow::core;
const char *const kLogFilename = "deskflow-daemon.log"; const char *const kLogFilename = "deskflow-daemon.log";
@ -99,13 +99,8 @@ int winMainLoopStatic(int, const char **)
DaemonApp::DaemonApp(IEventQueue *events, int argc, char **argv) DaemonApp::DaemonApp(IEventQueue *events, int argc, char **argv)
: QCoreApplication(argc, argv), : QCoreApplication(argc, argv),
m_events(events), 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; s_instance = this;
} }
@ -197,29 +192,11 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
CLOG->insert(m_fileLogOutputter); 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 #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); m_watchdog->setFileLogOutputter(m_fileLogOutputter);
#endif #endif
m_events->adoptHandler(
m_events->forIpcServer().messageReceived(), m_ipcServer.get(),
new TMethodEventJob<DaemonApp>(this, &DaemonApp::handleIpcMessage)
);
m_ipcServer->listen();
#if SYSAPI_WIN32 #if SYSAPI_WIN32
// install the platform event queue to handle service stop events. // install the platform event queue to handle service stop events.
@ -273,113 +250,3 @@ std::string DaemonApp::logFilename()
return 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;
}
}

View file

@ -6,7 +6,7 @@
#pragma once #pragma once
#include "ipc/IpcServer.h" #include "common/common.h"
#include <memory> #include <memory>
#include <string> #include <string>
@ -14,12 +14,13 @@
#include <QCoreApplication> #include <QCoreApplication>
class Event; class Event;
class IEventQueue;
class IpcLogOutputter; class IpcLogOutputter;
class FileLogOutputter; class FileLogOutputter;
class QLocalServer; class QLocalServer;
namespace deskflow::ipc { namespace deskflow::core::ipc {
class IpcServer2; class DaemonIpcServer;
} }
#if SYSAPI_WIN32 #if SYSAPI_WIN32
@ -33,11 +34,11 @@ class DaemonApp : public QCoreApplication
public: public:
DaemonApp(IEventQueue *events, int argc, char **argv); DaemonApp(IEventQueue *events, int argc, char **argv);
~DaemonApp(); ~DaemonApp();
int init(int argc, char **argv);
void startAsync(); void startAsync();
void mainLoop(bool logToFile, bool foreground = false); void mainLoop(bool logToFile, bool foreground = false);
private: private:
int init(int argc, char **argv);
void daemonize(); void daemonize();
void foregroundError(const char *message); void foregroundError(const char *message);
std::string logFilename(); std::string logFilename();
@ -51,9 +52,8 @@ public:
#endif #endif
private: private:
std::unique_ptr<IpcServer> m_ipcServer;
std::unique_ptr<IpcLogOutputter> m_ipcLogOutputter; std::unique_ptr<IpcLogOutputter> m_ipcLogOutputter;
IEventQueue *m_events = nullptr; IEventQueue *m_events = nullptr;
FileLogOutputter *m_fileLogOutputter = nullptr; FileLogOutputter *m_fileLogOutputter = nullptr;
std::unique_ptr<deskflow::ipc::IpcServer2> m_ipcServer2; std::unique_ptr<deskflow::core::ipc::DaemonIpcServer> m_ipcServer;
}; };

View 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

View file

@ -10,18 +10,21 @@
class QLocalServer; class QLocalServer;
namespace deskflow::ipc { namespace deskflow::core::ipc {
class IpcServer2 : public QObject class DaemonIpcServer : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
IpcServer2(QObject *parent); DaemonIpcServer(QObject *parent);
~IpcServer2(); ~DaemonIpcServer();
private slots:
void handleNewConnection();
private: private:
QLocalServer *m_server; QLocalServer *m_server;
}; };
} // namespace deskflow::ipc } // namespace deskflow::core::ipc

View file

@ -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

View file

@ -69,6 +69,8 @@ add_library(${target} STATIC
ipc/QDataStreamProxy.h ipc/QDataStreamProxy.h
ipc/QIpcClient.cpp ipc/QIpcClient.cpp
ipc/QIpcClient.h ipc/QIpcClient.h
ipc/DaemonIpcClient.cpp
ipc/DaemonIpcClient.h
proxy/QNetworkAccessManagerProxy.cpp proxy/QNetworkAccessManagerProxy.cpp
proxy/QNetworkAccessManagerProxy.h proxy/QNetworkAccessManagerProxy.h
proxy/QProcessProxy.cpp proxy/QProcessProxy.cpp

View 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

View 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

View file

@ -113,12 +113,12 @@ DWORD MSWindowsProcess::waitForExit()
return exitCode; 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); LOG_DEBUG("shutting down process %d", pid);
@ -129,9 +129,6 @@ void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, IpcServer &ipcServer,
return; return;
} }
IpcShutdownMessage shutdown;
ipcServer.send(shutdown, IpcClientType::Node);
// wait for process to exit gracefully. // wait for process to exit gracefully.
double start = ARCH->time(); double start = ARCH->time();
while (true) { // NOSONAR -- Multiple breaks necessary while (true) { // NOSONAR -- Multiple breaks necessary

View file

@ -6,8 +6,6 @@
#pragma once #pragma once
#include "ipc/IpcServer.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
@ -27,7 +25,7 @@ public:
BOOL startInForeground(); BOOL startInForeground();
BOOL startAsUser(HANDLE userToken, LPSECURITY_ATTRIBUTES sa); BOOL startAsUser(HANDLE userToken, LPSECURITY_ATTRIBUTES sa);
void shutdown(IpcServer &ipcServer, int timeout = kDefaultShutdownTimeout); void shutdown(int timeout = kDefaultShutdownTimeout);
DWORD waitForExit(); DWORD waitForExit();
void createPipes(); void createPipes();
std::string readStdOutput(); std::string readStdOutput();
@ -38,7 +36,7 @@ public:
return m_info; 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: private:
void setStartupInfo(STARTUPINFO &si); void setStartupInfo(STARTUPINFO &si);

View file

@ -57,17 +57,13 @@ typedef VOID(WINAPI *SendSas)(BOOL asUser);
const char g_activeDesktop[] = {"activeDesktop:"}; const char g_activeDesktop[] = {"activeDesktop:"};
MSWindowsWatchdog::MSWindowsWatchdog( MSWindowsWatchdog::MSWindowsWatchdog(bool autoDetectCommand, bool foreground)
bool autoDetectCommand, IpcServer &ipcServer, IpcLogOutputter &ipcLogOutputter, bool foreground
)
: m_thread(NULL), : m_thread(NULL),
m_autoDetectCommand(autoDetectCommand), m_autoDetectCommand(autoDetectCommand),
m_monitoring(true), m_monitoring(true),
m_commandChanged(false), m_commandChanged(false),
m_outputWritePipe(nullptr), m_outputWritePipe(nullptr),
m_outputReadPipe(nullptr), m_outputReadPipe(nullptr),
m_ipcServer(ipcServer),
m_ipcLogOutputter(ipcLogOutputter),
m_elevateProcess(false), m_elevateProcess(false),
m_processFailures(0), m_processFailures(0),
m_processStarted(false), m_processStarted(false),
@ -265,7 +261,7 @@ void MSWindowsWatchdog::mainLoop(void *)
if (m_process != nullptr) { if (m_process != nullptr) {
LOG((CLOG_DEBUG "terminated running process on exit")); LOG((CLOG_DEBUG "terminated running process on exit"));
m_process->shutdown(m_ipcServer); m_process->shutdown();
m_process.reset(); m_process.reset();
m_processStarted = false; m_processStarted = false;
} }
@ -301,7 +297,7 @@ void MSWindowsWatchdog::startProcess()
if (m_process != nullptr) { if (m_process != nullptr) {
LOG((CLOG_DEBUG "closing existing process to make way for new one")); LOG((CLOG_DEBUG "closing existing process to make way for new one"));
m_process->shutdown(m_ipcServer); m_process->shutdown();
m_process.reset(); m_process.reset();
m_processStarted = false; m_processStarted = false;
} }
@ -409,8 +405,6 @@ void MSWindowsWatchdog::outputLoop(void *)
} else { } else {
buffer[bytesRead] = '\0'; buffer[bytesRead] = '\0';
m_ipcLogOutputter.write(kINFO, buffer);
if (m_fileLogOutputter != NULL) { if (m_fileLogOutputter != NULL) {
m_fileLogOutputter->write(kINFO, buffer); m_fileLogOutputter->write(kINFO, buffer);
} }
@ -433,7 +427,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
LOG_INFO("daemon shutting down existing processes"); LOG_INFO("daemon shutting down existing processes");
if (m_process != nullptr) { if (m_process != nullptr) {
m_process->shutdown(m_ipcServer); m_process->shutdown();
m_process.reset(); m_process.reset();
m_processStarted = false; m_processStarted = false;
} }
@ -468,7 +462,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
_stricmp(entry.szExeFile, "deskflow-core.exe") == 0) { _stricmp(entry.szExeFile, "deskflow-core.exe") == 0) {
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); 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); CloseHandle(handle);
} }
} }

View file

@ -26,7 +26,7 @@ class FileLogOutputter;
class MSWindowsWatchdog class MSWindowsWatchdog
{ {
public: public:
MSWindowsWatchdog(bool autoDetectCommand, IpcServer &ipcServer, IpcLogOutputter &ipcLogOutputter, bool foreground); MSWindowsWatchdog(bool autoDetectCommand, bool foreground);
virtual ~MSWindowsWatchdog(); virtual ~MSWindowsWatchdog();
void startAsync(); void startAsync();
@ -65,8 +65,6 @@ private:
HANDLE m_outputWritePipe; HANDLE m_outputWritePipe;
HANDLE m_outputReadPipe; HANDLE m_outputReadPipe;
Thread *m_outputThread; Thread *m_outputThread;
IpcServer &m_ipcServer;
IpcLogOutputter &m_ipcLogOutputter;
bool m_elevateProcess; bool m_elevateProcess;
MSWindowsSession m_session; MSWindowsSession m_session;
int m_processFailures; int m_processFailures;