refactor: Remove old Windows TCP IPC implementation (replaced by Qt equivalent)
This commit is contained in:
@ -32,7 +32,6 @@ target_link_libraries(
|
||||
io
|
||||
mt
|
||||
net
|
||||
ipc
|
||||
platform
|
||||
server
|
||||
app
|
||||
|
||||
@ -27,7 +27,6 @@ target_link_libraries(
|
||||
io
|
||||
mt
|
||||
net
|
||||
ipc
|
||||
platform
|
||||
server
|
||||
app
|
||||
|
||||
@ -21,7 +21,6 @@ if(WIN32)
|
||||
arch
|
||||
base
|
||||
io
|
||||
ipc
|
||||
mt
|
||||
net
|
||||
platform
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
|
||||
#include "ServerConfig.h"
|
||||
#include "VersionChecker.h"
|
||||
#include "common/ipc.h"
|
||||
#include "gui/config/AppConfig.h"
|
||||
#include "gui/config/ConfigScopes.h"
|
||||
#include "gui/config/ServerConfigDialogState.h"
|
||||
@ -146,7 +145,6 @@ private:
|
||||
void setIcon();
|
||||
bool checkForApp(int which, QString &app);
|
||||
void setStatus(const QString &status);
|
||||
void sendIpcMessage(IpcMessageType type, const char *buffer, bool showErrors);
|
||||
void updateFromLogLine(const QString &line);
|
||||
QString getIPAddresses() const;
|
||||
void enableServer(bool enable);
|
||||
|
||||
@ -32,7 +32,6 @@ target_link_libraries(
|
||||
io
|
||||
mt
|
||||
net
|
||||
ipc
|
||||
platform
|
||||
server
|
||||
app
|
||||
|
||||
@ -9,7 +9,6 @@ add_subdirectory(client)
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(deskflow)
|
||||
add_subdirectory(io)
|
||||
add_subdirectory(ipc)
|
||||
add_subdirectory(mt)
|
||||
add_subdirectory(net)
|
||||
add_subdirectory(platform)
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
#include "base/Event.h"
|
||||
#include "base/EventQueue.h"
|
||||
|
||||
//
|
||||
// Event
|
||||
|
||||
@ -8,21 +8,17 @@
|
||||
#include "base/EventQueue.h"
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "base/EventTypes.h"
|
||||
#include "base/IEventJob.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/SimpleEventQueueBuffer.h"
|
||||
#include "base/Stopwatch.h"
|
||||
#include "base/XBase.h"
|
||||
#include "mt/Lock.h"
|
||||
#include "mt/Mutex.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
EVENT_TYPE_ACCESSOR(Client)
|
||||
EVENT_TYPE_ACCESSOR(IStream)
|
||||
EVENT_TYPE_ACCESSOR(IpcClient)
|
||||
EVENT_TYPE_ACCESSOR(IpcClientProxy)
|
||||
EVENT_TYPE_ACCESSOR(IpcServer)
|
||||
EVENT_TYPE_ACCESSOR(IpcServerProxy)
|
||||
EVENT_TYPE_ACCESSOR(IDataSocket)
|
||||
EVENT_TYPE_ACCESSOR(IListenSocket)
|
||||
EVENT_TYPE_ACCESSOR(ISocket)
|
||||
@ -55,10 +51,6 @@ EventQueue::EventQueue()
|
||||
m_nextType(Event::kLast),
|
||||
m_typesForClient(NULL),
|
||||
m_typesForIStream(NULL),
|
||||
m_typesForIpcClient(NULL),
|
||||
m_typesForIpcClientProxy(NULL),
|
||||
m_typesForIpcServer(NULL),
|
||||
m_typesForIpcServerProxy(NULL),
|
||||
m_typesForIDataSocket(NULL),
|
||||
m_typesForIListenSocket(NULL),
|
||||
m_typesForISocket(NULL),
|
||||
|
||||
@ -130,10 +130,6 @@ public:
|
||||
//
|
||||
ClientEvents &forClient();
|
||||
IStreamEvents &forIStream();
|
||||
IpcClientEvents &forIpcClient();
|
||||
IpcClientProxyEvents &forIpcClientProxy();
|
||||
IpcServerEvents &forIpcServer();
|
||||
IpcServerProxyEvents &forIpcServerProxy();
|
||||
IDataSocketEvents &forIDataSocket();
|
||||
IListenSocketEvents &forIListenSocket();
|
||||
ISocketEvents &forISocket();
|
||||
@ -153,10 +149,6 @@ public:
|
||||
private:
|
||||
ClientEvents *m_typesForClient;
|
||||
IStreamEvents *m_typesForIStream;
|
||||
IpcClientEvents *m_typesForIpcClient;
|
||||
IpcClientProxyEvents *m_typesForIpcClientProxy;
|
||||
IpcServerEvents *m_typesForIpcServer;
|
||||
IpcServerProxyEvents *m_typesForIpcServerProxy;
|
||||
IDataSocketEvents *m_typesForIDataSocket;
|
||||
IListenSocketEvents *m_typesForIListenSocket;
|
||||
ISocketEvents *m_typesForISocket;
|
||||
|
||||
@ -45,26 +45,6 @@ REGISTER_EVENT(IStream, inputShutdown)
|
||||
REGISTER_EVENT(IStream, outputShutdown)
|
||||
REGISTER_EVENT(IStream, inputFormatError)
|
||||
|
||||
//
|
||||
// IpcClient
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IpcClient, connected)
|
||||
REGISTER_EVENT(IpcClient, messageReceived)
|
||||
|
||||
//
|
||||
// IpcClientProxy
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IpcClientProxy, messageReceived)
|
||||
REGISTER_EVENT(IpcClientProxy, disconnected)
|
||||
|
||||
//
|
||||
// IpcServerProxy
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IpcServerProxy, messageReceived)
|
||||
|
||||
//
|
||||
// IDataSocket
|
||||
//
|
||||
@ -167,13 +147,6 @@ REGISTER_EVENT(IScreen, shapeChanged)
|
||||
REGISTER_EVENT(IScreen, suspend)
|
||||
REGISTER_EVENT(IScreen, resume)
|
||||
|
||||
//
|
||||
// IpcServer
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IpcServer, clientConnected)
|
||||
REGISTER_EVENT(IpcServer, messageReceived)
|
||||
|
||||
//
|
||||
// Clipboard
|
||||
//
|
||||
|
||||
@ -145,94 +145,6 @@ private:
|
||||
Event::Type m_inputFormatError;
|
||||
};
|
||||
|
||||
class IpcClientEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IpcClientEvents() : m_connected(Event::kUnknown), m_messageReceived(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Raised when the socket is connected.
|
||||
Event::Type connected();
|
||||
|
||||
//! Raised when a message is received.
|
||||
Event::Type messageReceived();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_connected;
|
||||
Event::Type m_messageReceived;
|
||||
};
|
||||
|
||||
class IpcClientProxyEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IpcClientProxyEvents() : m_messageReceived(Event::kUnknown), m_disconnected(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Raised when the server receives a message from a client.
|
||||
Event::Type messageReceived();
|
||||
|
||||
//! Raised when the client disconnects from the server.
|
||||
Event::Type disconnected();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_messageReceived;
|
||||
Event::Type m_disconnected;
|
||||
};
|
||||
|
||||
class IpcServerEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IpcServerEvents() : m_clientConnected(Event::kUnknown), m_messageReceived(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Raised when we have created the client proxy.
|
||||
Event::Type clientConnected();
|
||||
|
||||
//! Raised when a message is received through a client proxy.
|
||||
Event::Type messageReceived();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_clientConnected;
|
||||
Event::Type m_messageReceived;
|
||||
};
|
||||
|
||||
class IpcServerProxyEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IpcServerProxyEvents() : m_messageReceived(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Raised when the client receives a message from the server.
|
||||
Event::Type messageReceived();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_messageReceived;
|
||||
};
|
||||
|
||||
class IDataSocketEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
|
||||
@ -21,10 +21,6 @@ class EventQueueTimer;
|
||||
// Event type registration classes.
|
||||
class ClientEvents;
|
||||
class IStreamEvents;
|
||||
class IpcClientEvents;
|
||||
class IpcClientProxyEvents;
|
||||
class IpcServerEvents;
|
||||
class IpcServerProxyEvents;
|
||||
class IDataSocketEvents;
|
||||
class IListenSocketEvents;
|
||||
class ISocketEvents;
|
||||
@ -216,10 +212,6 @@ public:
|
||||
|
||||
virtual ClientEvents &forClient() = 0;
|
||||
virtual IStreamEvents &forIStream() = 0;
|
||||
virtual IpcClientEvents &forIpcClient() = 0;
|
||||
virtual IpcClientProxyEvents &forIpcClientProxy() = 0;
|
||||
virtual IpcServerEvents &forIpcServer() = 0;
|
||||
virtual IpcServerProxyEvents &forIpcServerProxy() = 0;
|
||||
virtual IDataSocketEvents &forIDataSocket() = 0;
|
||||
virtual IListenSocketEvents &forIListenSocket() = 0;
|
||||
virtual ISocketEvents &forISocket() = 0;
|
||||
|
||||
@ -8,7 +8,6 @@ configure_file(constants.h.in constants.h @ONLY)
|
||||
add_library(common INTERFACE
|
||||
common.h
|
||||
IInterface.h
|
||||
ipc.h
|
||||
stdbitset.h
|
||||
stddeque.h
|
||||
stdexcept.h
|
||||
|
||||
@ -45,7 +45,7 @@ enum
|
||||
#if WINAPI_MSWINDOWS
|
||||
namespace deskflow::common {
|
||||
|
||||
const auto kCloseEventName = "Global\\DeskflowCloseEvent";
|
||||
const auto kCloseEventName = "Global\\DeskflowClose";
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
enum class IpcMessageType : uint8_t
|
||||
{
|
||||
Hello,
|
||||
HelloBack,
|
||||
LogLine,
|
||||
Command,
|
||||
Shutdown,
|
||||
Setting
|
||||
};
|
||||
|
||||
enum class IpcClientType
|
||||
{
|
||||
Unknown,
|
||||
GUI,
|
||||
Node
|
||||
};
|
||||
|
||||
const auto kIpcHost = "127.0.0.1";
|
||||
const auto kIpcPort = 24801;
|
||||
|
||||
// handshake: node/gui -> daemon
|
||||
// $1 = type, the client identifies it's self as gui or core (server/client).
|
||||
const auto kIpcMsgHello = "IHEL%1i";
|
||||
|
||||
// handshake: daemon -> node/gui
|
||||
// the daemon responds to the handshake.
|
||||
const auto kIpcMsgHelloBack = "IHEL";
|
||||
|
||||
// log line: daemon -> gui
|
||||
// $1 = aggregate log lines collected from core (server/client) or the daemon
|
||||
// itself.
|
||||
const auto kIpcMsgLogLine = "ILOG%s";
|
||||
|
||||
// command: gui -> daemon
|
||||
// $1 = command; the command for the daemon to launch, typically the full
|
||||
// path to core (server/client). $2 = true when process must be elevated on ms
|
||||
// windows.
|
||||
const auto kIpcMsgCommand = "ICMD%s%1i";
|
||||
|
||||
// shutdown: daemon -> node
|
||||
// the daemon tells core (server/client) to shut down gracefully.
|
||||
const auto kIpcMsgShutdown = "ISDN";
|
||||
|
||||
// set setting: gui -> daemon
|
||||
// $1 = setting name
|
||||
// $2 = setting value
|
||||
const auto kIpcMsgSetting = "SSET%s%s";
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 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
|
||||
*/
|
||||
@ -9,36 +9,23 @@
|
||||
|
||||
#include "DisplayInvalidException.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/XArch.h"
|
||||
#include "base/EventQueue.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "base/XBase.h"
|
||||
#include "base/log_outputters.h"
|
||||
#include "common/constants.h"
|
||||
#include "common/ipc.h"
|
||||
#include "deskflow/ArgsBase.h"
|
||||
#include "deskflow/Config.h"
|
||||
#include "deskflow/XDeskflow.h"
|
||||
#include "deskflow/protocol_types.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServerProxy.h"
|
||||
#include <thread>
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include "base/IEventQueue.h"
|
||||
#include "base/TMethodJob.h"
|
||||
#endif
|
||||
|
||||
#if WINAPI_CARBON
|
||||
#include "platform/OSXDragSimulator.h"
|
||||
#endif
|
||||
|
||||
#include <charconv>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
@ -64,7 +51,6 @@ App::App(IEventQueue *events, deskflow::ArgsBase *args)
|
||||
m_args(args),
|
||||
m_fileLog(nullptr),
|
||||
m_appUtil(events),
|
||||
m_ipcClient(nullptr),
|
||||
m_socketMultiplexer(nullptr)
|
||||
{
|
||||
assert(s_instance == nullptr);
|
||||
@ -208,32 +194,6 @@ void App::initApp(int argc, const char **argv)
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
void App::initIpcClient()
|
||||
{
|
||||
m_ipcClient = new IpcClient(m_events, m_socketMultiplexer);
|
||||
m_ipcClient->connect();
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIpcClient().messageReceived(), m_ipcClient, new TMethodEventJob<App>(this, &App::handleIpcMessage)
|
||||
);
|
||||
}
|
||||
|
||||
void App::cleanupIpcClient()
|
||||
{
|
||||
m_ipcClient->disconnect();
|
||||
m_events->removeHandler(m_events->forIpcClient().messageReceived(), m_ipcClient);
|
||||
delete m_ipcClient;
|
||||
}
|
||||
|
||||
void App::handleIpcMessage(const Event &e, void *)
|
||||
{
|
||||
IpcMessage *m = static_cast<IpcMessage *>(e.getDataObject());
|
||||
if (m->type() == IpcMessageType::Shutdown) {
|
||||
LOG((CLOG_INFO "got ipc shutdown message"));
|
||||
m_events->addEvent(Event(Event::kQuit));
|
||||
}
|
||||
}
|
||||
|
||||
void App::runEventsLoop(void *)
|
||||
{
|
||||
m_events->loop();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* 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
|
||||
*/
|
||||
@ -11,7 +11,6 @@
|
||||
#include "base/Log.h"
|
||||
#include "common/common.h"
|
||||
#include "deskflow/IApp.h"
|
||||
#include "ipc/IpcClient.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
#include "deskflow/win32/AppUtilWindows.h"
|
||||
@ -20,7 +19,6 @@
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
namespace deskflow {
|
||||
class Screen;
|
||||
@ -110,12 +108,7 @@ public:
|
||||
|
||||
void (*m_bye)(int);
|
||||
|
||||
private:
|
||||
void handleIpcMessage(const Event &, void *);
|
||||
|
||||
protected:
|
||||
void initIpcClient();
|
||||
void cleanupIpcClient();
|
||||
void runEventsLoop(void *);
|
||||
|
||||
bool m_suspended;
|
||||
@ -126,7 +119,6 @@ private:
|
||||
static App *s_instance;
|
||||
FileLogOutputter *m_fileLog;
|
||||
ARCH_APP_UTIL m_appUtil;
|
||||
IpcClient *m_ipcClient;
|
||||
SocketMultiplexer *m_socketMultiplexer;
|
||||
};
|
||||
|
||||
|
||||
@ -188,8 +188,6 @@ bool ArgParser::parseGenericArgs(int argc, const char *const *argv, int &i)
|
||||
m_app->version();
|
||||
}
|
||||
argsBase().m_shouldExitOk = true;
|
||||
} else if (isArg(i, argc, argv, nullptr, "--ipc")) {
|
||||
argsBase().m_enableIpc = true;
|
||||
} else if (isArg(i, argc, argv, nullptr, "--server")) {
|
||||
// HACK: stop error happening when using portable (deskflowp)
|
||||
} else if (isArg(i, argc, argv, nullptr, "--client")) {
|
||||
|
||||
@ -56,8 +56,8 @@ public:
|
||||
/// @brief The name of the current computer
|
||||
std::string m_name;
|
||||
|
||||
/// @brief Tell the client to talk through IPC to the daemon
|
||||
bool m_enableIpc = false;
|
||||
/// @brief Should the app add a tray icon
|
||||
bool m_disableTray = false;
|
||||
|
||||
/// @brief Should drag drop support be enabled
|
||||
bool m_enableDragDrop = false;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2012 - 2024 Symless Ltd
|
||||
# SPDX-FileCopyrightText: 2012 - 2025 Symless Ltd
|
||||
# SPDX-FileCopyrightText: 2009 - 2012 Nick Bolton
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
@ -170,7 +170,6 @@ if(UNIX)
|
||||
PRIVATE
|
||||
arch
|
||||
client
|
||||
ipc
|
||||
net
|
||||
base
|
||||
platform
|
||||
|
||||
@ -454,12 +454,6 @@ int ClientApp::mainLoop()
|
||||
// start client, etc
|
||||
appUtil().startNode();
|
||||
|
||||
// init ipc client after node start, since create a new screen wipes out
|
||||
// the event queue (the screen ctors call adoptBuffer).
|
||||
if (argsBase().m_enableIpc) {
|
||||
initIpcClient();
|
||||
}
|
||||
|
||||
// run event loop. if startClient() failed we're supposed to retry
|
||||
// later. the timer installed by startClient() will take care of
|
||||
// that.
|
||||
@ -486,10 +480,6 @@ int ClientApp::mainLoop()
|
||||
updateStatus();
|
||||
LOG((CLOG_NOTE "stopped client"));
|
||||
|
||||
if (argsBase().m_enableIpc) {
|
||||
cleanupIpcClient();
|
||||
}
|
||||
|
||||
return kExitSuccess;
|
||||
}
|
||||
|
||||
|
||||
@ -4,26 +4,13 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
// TODO: split this class into windows and unix to get rid
|
||||
// of all the #ifdefs!
|
||||
|
||||
#include "deskflow/DaemonApp.h"
|
||||
|
||||
#include "arch/XArch.h"
|
||||
#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/IpcClientProxy.h"
|
||||
#include "ipc/IpcLogOutputter.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcSettingMessage.h"
|
||||
#include "net/SocketMultiplexer.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
@ -50,16 +37,6 @@ using namespace deskflow::core;
|
||||
const char *const kLogFilename = "deskflow-daemon.log";
|
||||
|
||||
namespace {
|
||||
void updateSetting(const IpcMessage &message)
|
||||
{
|
||||
try {
|
||||
auto setting = static_cast<const IpcSettingMessage &>(message);
|
||||
ARCH->setting(setting.getName(), setting.getValue());
|
||||
} catch (const XArch &e) {
|
||||
LOG((CLOG_ERR "failed to save setting: %s", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
bool isServerCommandLine(const std::vector<std::string> &cmd)
|
||||
{
|
||||
auto isServer = false;
|
||||
@ -76,7 +53,7 @@ bool isServerCommandLine(const std::vector<std::string> &cmd)
|
||||
|
||||
int mainLoopStatic()
|
||||
{
|
||||
DaemonApp::instance().mainLoop(true);
|
||||
DaemonApp::instance().mainLoop();
|
||||
return kExitSuccess;
|
||||
}
|
||||
|
||||
@ -108,7 +85,7 @@ void DaemonApp::run()
|
||||
|
||||
// run process in foreground instead of daemonizing.
|
||||
// useful for debugging.
|
||||
mainLoop(false, m_foreground);
|
||||
mainLoop(m_foreground);
|
||||
} else {
|
||||
#if SYSAPI_WIN32
|
||||
LOG((CLOG_NOTE "daemonizing windows service"));
|
||||
@ -260,7 +237,7 @@ DaemonApp::InitResult DaemonApp::init(IEventQueue *events, int argc, char **argv
|
||||
return FatalError;
|
||||
}
|
||||
|
||||
void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||
void DaemonApp::mainLoop(bool foreground)
|
||||
{
|
||||
if (m_events == nullptr) {
|
||||
throw XDeskflow("event queue not set");
|
||||
@ -269,17 +246,12 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||
try {
|
||||
DAEMON_RUNNING(true);
|
||||
|
||||
if (logToFile) {
|
||||
m_fileLogOutputter = new FileLogOutputter(logFilename().c_str()); // NOSONAR -- Adopted by `Log`
|
||||
CLOG->insert(m_fileLogOutputter);
|
||||
}
|
||||
m_fileLogOutputter = new FileLogOutputter(logFilename().c_str()); // NOSONAR - Adopted by `Log`
|
||||
CLOG->insert(m_fileLogOutputter);
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
m_watchdog = std::make_unique<MSWindowsWatchdog>(false, foreground);
|
||||
m_watchdog->setFileLogOutputter(m_fileLogOutputter);
|
||||
#endif
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
// install the platform event queue to handle service stop events.
|
||||
m_events->adoptBuffer(new MSWindowsEventQueueBuffer(m_events));
|
||||
@ -293,14 +265,13 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||
|
||||
m_watchdog->startAsync();
|
||||
#endif
|
||||
|
||||
m_events->loop();
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
m_watchdog->stop();
|
||||
#endif
|
||||
|
||||
CLOG->remove(m_ipcLogOutputter.get());
|
||||
|
||||
DAEMON_RUNNING(false);
|
||||
} catch (std::exception &e) {
|
||||
LOG((CLOG_CRIT "an error occurred: %s", e.what()));
|
||||
|
||||
@ -13,11 +13,8 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
class Event;
|
||||
class IEventQueue;
|
||||
class IpcLogOutputter;
|
||||
class FileLogOutputter;
|
||||
class QLocalServer;
|
||||
class QCoreApplication;
|
||||
@ -49,15 +46,14 @@ public:
|
||||
|
||||
InitResult init(IEventQueue *events, int argc, char **argv);
|
||||
void run();
|
||||
void mainLoop(bool logToFile, bool foreground = false);
|
||||
void restartCoreProcess();
|
||||
void saveLogLevel(const QString &logLevel) const;
|
||||
void mainLoop(bool foreground = false);
|
||||
void setLogLevel(const QString &logLevel);
|
||||
void setElevate(bool elevate);
|
||||
void setCommand(const QString &command);
|
||||
void applyWatchdogCommand() const;
|
||||
void clearWatchdogCommand();
|
||||
|
||||
// Getters
|
||||
std::string logFilename();
|
||||
|
||||
static DaemonApp &instance()
|
||||
@ -79,7 +75,6 @@ private:
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::unique_ptr<IpcLogOutputter> m_ipcLogOutputter;
|
||||
IEventQueue *m_events = nullptr;
|
||||
FileLogOutputter *m_fileLogOutputter = nullptr;
|
||||
deskflow::core::ipc::DaemonIpcServer *m_ipcServer = nullptr;
|
||||
|
||||
@ -706,12 +706,6 @@ int ServerApp::mainLoop()
|
||||
// start server, etc
|
||||
appUtil().startNode();
|
||||
|
||||
// init ipc client after node start, since create a new screen wipes out
|
||||
// the event queue (the screen ctors call adoptBuffer).
|
||||
if (argsBase().m_enableIpc) {
|
||||
initIpcClient();
|
||||
}
|
||||
|
||||
// handle hangup signal by reloading the server's configuration
|
||||
ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL);
|
||||
m_events->adoptHandler(
|
||||
@ -761,10 +755,6 @@ int ServerApp::mainLoop()
|
||||
updateStatus();
|
||||
LOG((CLOG_NOTE "stopped server"));
|
||||
|
||||
if (argsBase().m_enableIpc) {
|
||||
cleanupIpcClient();
|
||||
}
|
||||
|
||||
return kExitSuccess;
|
||||
}
|
||||
|
||||
|
||||
@ -64,13 +64,6 @@ add_library(${target} STATIC
|
||||
core/ServerMessage.h
|
||||
core/WaylandWarnings.cpp
|
||||
core/WaylandWarnings.h
|
||||
ipc/IpcReader.cpp
|
||||
ipc/IpcReader.h
|
||||
ipc/IQIpcClient.cpp
|
||||
ipc/IQIpcClient.h
|
||||
ipc/QDataStreamProxy.h
|
||||
ipc/QIpcClient.cpp
|
||||
ipc/QIpcClient.h
|
||||
ipc/DaemonIpcClient.cpp
|
||||
ipc/DaemonIpcClient.h
|
||||
proxy/QNetworkAccessManagerProxy.cpp
|
||||
|
||||
@ -158,18 +158,6 @@ CoreProcess::CoreProcess(const IAppConfig &appConfig, const IServerConfig &serve
|
||||
m_pDeps(deps),
|
||||
m_daemonIpcClient{new ipc::DaemonIpcClient(this)}
|
||||
{
|
||||
if (m_appConfig.processMode() == ProcessMode::kService) {
|
||||
|
||||
connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connected, this, &CoreProcess::daemonIpcClientConnected);
|
||||
|
||||
const auto logPath = requestDaemonLogPath();
|
||||
if (!logPath.isEmpty()) {
|
||||
qInfo() << "daemon log path:" << logPath;
|
||||
m_daemonFileTail = new FileTail(logPath, this);
|
||||
connect(m_daemonFileTail, &FileTail::newLine, this, &CoreProcess::handleLogLines);
|
||||
}
|
||||
}
|
||||
|
||||
connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connected, this, &CoreProcess::daemonIpcClientConnected);
|
||||
|
||||
connect(&m_pDeps->process(), &QProcessProxy::finished, this, &CoreProcess::onProcessFinished);
|
||||
@ -191,30 +179,6 @@ CoreProcess::CoreProcess(const IAppConfig &appConfig, const IServerConfig &serve
|
||||
});
|
||||
}
|
||||
|
||||
void CoreProcess::onIpcClientServiceReady()
|
||||
{
|
||||
if (m_processState == ProcessState::Starting) {
|
||||
qDebug("service ready, continuing core process start");
|
||||
start();
|
||||
} else if (m_processState == ProcessState::Stopping) {
|
||||
qDebug("service ready, continuing core process stop");
|
||||
stop();
|
||||
} else {
|
||||
// This may happen when the IPC connection fails and then reconnects.
|
||||
qWarning("ignoring service ready, process state is not starting or stopping");
|
||||
}
|
||||
}
|
||||
|
||||
void CoreProcess::onIpcClientError(const QString &text) const
|
||||
{
|
||||
qCritical().noquote() << text;
|
||||
}
|
||||
|
||||
void CoreProcess::onIpcClientRead(const QString &text)
|
||||
{
|
||||
handleLogLines(text);
|
||||
}
|
||||
|
||||
void CoreProcess::onProcessReadyReadStandardOutput()
|
||||
{
|
||||
if (m_pDeps->process()) {
|
||||
@ -314,10 +278,6 @@ void CoreProcess::startProcessFromDaemon(const QString &app, const QStringList &
|
||||
qFatal("core process must be in starting state");
|
||||
}
|
||||
|
||||
if (!m_daemonIpcClient->isConnected()) {
|
||||
m_daemonIpcClient->connectToServer();
|
||||
}
|
||||
|
||||
QString commandQuoted = makeQuotedArgs(app, args);
|
||||
|
||||
qInfo("running command: %s", qPrintable(commandQuoted));
|
||||
@ -506,8 +466,6 @@ void CoreProcess::cleanup()
|
||||
if (isDesktop && isRunning) {
|
||||
stop();
|
||||
}
|
||||
|
||||
m_pDeps->ipcClient().disconnectFromHost();
|
||||
}
|
||||
|
||||
bool CoreProcess::addGenericArgs(QStringList &args, const ProcessMode processMode) const
|
||||
@ -518,9 +476,6 @@ bool CoreProcess::addGenericArgs(QStringList &args, const ProcessMode processMod
|
||||
args << "--name" << m_appConfig.screenName();
|
||||
|
||||
if (processMode != ProcessMode::kDesktop) {
|
||||
// tell client/server to talk to daemon through ipc.
|
||||
args << "--ipc";
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
// tell the client/server to shut down when a ms windows desk
|
||||
// is switched; this is because we may need to elevate or not
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#include "gui/FileTail.h"
|
||||
#include "gui/config/IAppConfig.h"
|
||||
#include "gui/config/IServerConfig.h"
|
||||
#include "gui/ipc/QIpcClient.h"
|
||||
#include "gui/proxy/QProcessProxy.h"
|
||||
|
||||
#include <memory>
|
||||
@ -31,7 +30,6 @@ class CoreProcess : public QObject
|
||||
{
|
||||
using IServerConfig = deskflow::gui::IServerConfig;
|
||||
using QProcessProxy = deskflow::gui::proxy::QProcessProxy;
|
||||
using IQIpcClient = deskflow::gui::ipc::IQIpcClient;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
@ -43,17 +41,12 @@ public:
|
||||
{
|
||||
return m_process;
|
||||
}
|
||||
virtual IQIpcClient &ipcClient()
|
||||
{
|
||||
return m_ipcClient;
|
||||
}
|
||||
virtual QString appPath(const QString &name) const;
|
||||
virtual bool fileExists(const QString &path) const;
|
||||
virtual QString getProfileRoot() const;
|
||||
|
||||
private:
|
||||
QProcessProxy m_process;
|
||||
QIpcClient m_ipcClient;
|
||||
};
|
||||
|
||||
enum class Mode
|
||||
@ -136,9 +129,6 @@ signals:
|
||||
void secureSocket(bool enabled);
|
||||
|
||||
private slots:
|
||||
void onIpcClientServiceReady();
|
||||
void onIpcClientRead(const QString &text);
|
||||
void onIpcClientError(const QString &text) const;
|
||||
void onProcessFinished(int exitCode, QProcess::ExitStatus);
|
||||
void onProcessReadyReadStandardOutput();
|
||||
void onProcessReadyReadStandardError();
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2024 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
// empty .cpp for qt moc
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2024 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "gui/config/ElevateMode.h"
|
||||
|
||||
namespace deskflow::gui::ipc {
|
||||
|
||||
class IQIpcClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
~IQIpcClient() override = default;
|
||||
virtual void sendHello() const = 0;
|
||||
virtual void sendCommand(const QString &command, ElevateMode elevate) const = 0;
|
||||
virtual void connectToHost() = 0;
|
||||
virtual void disconnectFromHost() = 0;
|
||||
virtual bool isConnected() const = 0;
|
||||
|
||||
signals:
|
||||
void read(const QString &text);
|
||||
void serviceReady();
|
||||
};
|
||||
|
||||
} // namespace deskflow::gui::ipc
|
||||
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "IpcReader.h"
|
||||
|
||||
#include "Logger.h"
|
||||
#include "byte_utils.h"
|
||||
#include "common/ipc.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMutex>
|
||||
#include <QTcpSocket>
|
||||
|
||||
using namespace deskflow::gui;
|
||||
|
||||
IpcReader::IpcReader(QTcpSocket *socket) : m_Socket(socket)
|
||||
{
|
||||
}
|
||||
|
||||
void IpcReader::start() const
|
||||
{
|
||||
connect(m_Socket, &QTcpSocket::readyRead, this, &IpcReader::onSocketReadyRead);
|
||||
}
|
||||
|
||||
void IpcReader::stop() const
|
||||
{
|
||||
disconnect(m_Socket, &QTcpSocket::readyRead, this, &IpcReader::onSocketReadyRead);
|
||||
}
|
||||
|
||||
void IpcReader::onSocketReadyRead()
|
||||
{
|
||||
QMutexLocker locker(&m_Mutex);
|
||||
logVerbose("ready read");
|
||||
|
||||
while (m_Socket->bytesAvailable()) {
|
||||
logVerbose("bytes available");
|
||||
|
||||
char codeBuf[5];
|
||||
readStream(codeBuf, 4);
|
||||
codeBuf[4] = 0;
|
||||
logVerbose(QString("ipc read: %1").arg(codeBuf));
|
||||
|
||||
if (memcmp(codeBuf, kIpcMsgLogLine, 4) == 0) {
|
||||
logVerbose("reading log line");
|
||||
|
||||
char lenBuf[4];
|
||||
readStream(lenBuf, 4);
|
||||
int len = bytesToInt(lenBuf, 4);
|
||||
|
||||
std::vector<char> dataBuf(len);
|
||||
readStream(dataBuf.data(), len);
|
||||
QString text = QString::fromUtf8(dataBuf.data(), len);
|
||||
|
||||
Q_EMIT read(text);
|
||||
} else if (memcmp(codeBuf, kIpcMsgHelloBack, 4) == 0) {
|
||||
logVerbose("reading hello back");
|
||||
Q_EMIT helloBack();
|
||||
} else {
|
||||
qCritical("aborting ipc read, message invalid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
logVerbose("read done");
|
||||
}
|
||||
|
||||
bool IpcReader::readStream(char *buffer, int length)
|
||||
{
|
||||
logVerbose("reading stream");
|
||||
|
||||
int read = 0;
|
||||
while (read < length) {
|
||||
int ask = length - read;
|
||||
if (m_Socket->bytesAvailable() < ask) {
|
||||
logVerbose("buffer too short, waiting");
|
||||
m_Socket->waitForReadyRead(-1);
|
||||
}
|
||||
|
||||
auto got = m_Socket->read(buffer, ask);
|
||||
read += got;
|
||||
|
||||
logVerbose(QString("ask=%1 got=%2 read=%3").arg(ask).arg(got).arg(read));
|
||||
|
||||
if (got == -1) {
|
||||
logVerbose("socket ended, aborting");
|
||||
return false;
|
||||
} else if (length - read > 0) {
|
||||
logVerbose(QString("more remains, seek to %1").arg(got));
|
||||
buffer += got;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
class QTcpSocket;
|
||||
|
||||
class IpcReader : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
explicit IpcReader(QTcpSocket *socket);
|
||||
~IpcReader() override = default;
|
||||
void start() const;
|
||||
void stop() const;
|
||||
|
||||
signals:
|
||||
void read(const QString &text);
|
||||
void helloBack();
|
||||
|
||||
private:
|
||||
bool readStream(char *buffer, int length);
|
||||
|
||||
private slots:
|
||||
void onSocketReadyRead();
|
||||
|
||||
private:
|
||||
QTcpSocket *m_Socket;
|
||||
QMutex m_Mutex;
|
||||
};
|
||||
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2024 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTcpSocket>
|
||||
|
||||
/**
|
||||
* @brief Useful for overriding QDataStream.
|
||||
*/
|
||||
class QDataStreamProxy
|
||||
{
|
||||
public:
|
||||
explicit QDataStreamProxy() = default;
|
||||
explicit QDataStreamProxy(QTcpSocket *socket) : m_Stream(std::make_unique<QDataStream>(socket))
|
||||
{
|
||||
}
|
||||
virtual ~QDataStreamProxy() = default;
|
||||
|
||||
virtual qint64 writeRawData(const char *data, int len)
|
||||
{
|
||||
assert(m_Stream);
|
||||
return m_Stream->writeRawData(data, len);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<QDataStream> m_Stream;
|
||||
};
|
||||
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "QIpcClient.h"
|
||||
|
||||
#include "IpcReader.h"
|
||||
#include "byte_utils.h"
|
||||
#include "common/ipc.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QHostAddress>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
const auto kRetryInterval = 1000;
|
||||
const auto kConnectTimeout = 5000;
|
||||
|
||||
using namespace deskflow::gui;
|
||||
|
||||
QIpcClient::QIpcClient(const StreamProvider &streamProvider) : m_streamProvider(streamProvider)
|
||||
{
|
||||
|
||||
m_pSocket = std::make_unique<QTcpSocket>();
|
||||
|
||||
if (!m_streamProvider) {
|
||||
m_streamProvider = [this]() { return std::make_shared<QDataStreamProxy>(m_pSocket.get()); };
|
||||
}
|
||||
|
||||
connect(m_pSocket.get(), &QTcpSocket::connected, this, &QIpcClient::onSocketConnected);
|
||||
connect(m_pSocket.get(), &QTcpSocket::errorOccurred, this, &QIpcClient::onSocketError);
|
||||
|
||||
m_pReader = std::make_unique<IpcReader>(m_pSocket.get());
|
||||
connect(
|
||||
m_pReader.get(), &IpcReader::read, this, //
|
||||
&QIpcClient::onIpcReaderRead
|
||||
);
|
||||
connect(m_pReader.get(), &IpcReader::helloBack, this, &QIpcClient::onIpcReaderHelloBack);
|
||||
}
|
||||
|
||||
void QIpcClient::onSocketConnected() const
|
||||
{
|
||||
sendHello();
|
||||
}
|
||||
|
||||
void QIpcClient::connectToHost()
|
||||
{
|
||||
m_isConnecting = true;
|
||||
qInfo("connecting to background service...");
|
||||
const auto port = static_cast<quint16>(kIpcPort);
|
||||
m_pSocket->connectToHost(QHostAddress(QHostAddress::LocalHost), port);
|
||||
|
||||
if (!m_readerStarted) {
|
||||
m_pReader->start();
|
||||
m_readerStarted = true;
|
||||
}
|
||||
|
||||
QTimer::singleShot(kConnectTimeout, this, [this]() {
|
||||
if (!m_isConnected) {
|
||||
qCritical("ipc connection timeout");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void QIpcClient::disconnectFromHost()
|
||||
{
|
||||
m_pReader->stop();
|
||||
m_pSocket->flush();
|
||||
m_pSocket->close();
|
||||
|
||||
m_isConnecting = false;
|
||||
m_isConnected = false;
|
||||
|
||||
qInfo("disconnected from background service");
|
||||
}
|
||||
|
||||
void QIpcClient::onSocketError(QAbstractSocket::SocketError socketError)
|
||||
{
|
||||
QString text;
|
||||
switch (socketError) {
|
||||
case 0:
|
||||
text = "connection refused";
|
||||
break;
|
||||
case 1:
|
||||
text = "remote host closed";
|
||||
break;
|
||||
default:
|
||||
text = QString("code=%1").arg(socketError);
|
||||
break;
|
||||
}
|
||||
|
||||
qWarning("ipc connection error, %s", qUtf8Printable(text));
|
||||
m_isConnected = false;
|
||||
|
||||
QTimer::singleShot(kRetryInterval, this, &QIpcClient::onRetryConnect);
|
||||
}
|
||||
|
||||
void QIpcClient::onRetryConnect()
|
||||
{
|
||||
if (m_isConnected) {
|
||||
qDebug("ipc already connected, skipping retry");
|
||||
return;
|
||||
} else if (!m_isConnecting) {
|
||||
qDebug("ipc not connecting, skipping retry");
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo("retrying connection to background service...");
|
||||
connectToHost();
|
||||
}
|
||||
|
||||
void QIpcClient::sendHello() const
|
||||
{
|
||||
qDebug("sending ipc hello message");
|
||||
auto stream = m_streamProvider();
|
||||
stream->writeRawData(kIpcMsgHello, 4);
|
||||
|
||||
char typeBuf[1];
|
||||
typeBuf[0] = static_cast<char>(IpcClientType::GUI);
|
||||
stream->writeRawData(typeBuf, 1);
|
||||
}
|
||||
|
||||
void QIpcClient::sendCommand(const QString &command, ElevateMode const elevate) const
|
||||
{
|
||||
qDebug("sending ipc command: %s", qUtf8Printable(command));
|
||||
|
||||
auto stream = m_streamProvider();
|
||||
stream->writeRawData(kIpcMsgCommand, 4);
|
||||
|
||||
std::string stdStringCommand = command.toStdString();
|
||||
const char *charCommand = stdStringCommand.c_str();
|
||||
auto length = static_cast<int>(stdStringCommand.length());
|
||||
|
||||
QByteArray lenBuf = intToBytes(length);
|
||||
if (lenBuf.size() != 4) {
|
||||
qFatal("unexpected int buffer size: %lld", lenBuf.size());
|
||||
}
|
||||
stream->writeRawData(lenBuf, 4);
|
||||
stream->writeRawData(charCommand, length);
|
||||
|
||||
char elevateBuf[1];
|
||||
// see enum ElevateMode documentation for why this flag is mapped this way
|
||||
elevateBuf[0] = (elevate == ElevateMode::kAlways) ? 1 : 0;
|
||||
stream->writeRawData(elevateBuf, 1);
|
||||
}
|
||||
|
||||
void QIpcClient::onIpcReaderHelloBack()
|
||||
{
|
||||
qDebug("ipc hello back received");
|
||||
|
||||
if (m_isConnected) {
|
||||
qWarning("ipc already connected, ignoring hello back");
|
||||
return;
|
||||
}
|
||||
|
||||
m_isConnected = true;
|
||||
Q_EMIT serviceReady();
|
||||
}
|
||||
|
||||
void QIpcClient::onIpcReaderRead(const QString &text)
|
||||
{
|
||||
Q_EMIT read(text);
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractSocket>
|
||||
#include <QDataStream>
|
||||
#include <QObject>
|
||||
#include <QTcpSocket>
|
||||
#include <memory>
|
||||
|
||||
#include "IpcReader.h"
|
||||
#include "QDataStreamProxy.h"
|
||||
#include "gui/config/ElevateMode.h"
|
||||
#include "gui/ipc/IQIpcClient.h"
|
||||
|
||||
class IpcReader;
|
||||
|
||||
class QIpcClient : public deskflow::gui::ipc::IQIpcClient
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using StreamProvider = std::function<std::shared_ptr<QDataStreamProxy>()>;
|
||||
|
||||
explicit QIpcClient(const StreamProvider &streamProvider = nullptr);
|
||||
|
||||
void sendHello() const override;
|
||||
void sendCommand(const QString &command, ElevateMode elevate) const override;
|
||||
void connectToHost() override;
|
||||
void disconnectFromHost() override;
|
||||
bool isConnected() const override
|
||||
{
|
||||
return m_isConnected;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onRetryConnect();
|
||||
void onSocketConnected() const;
|
||||
void onIpcReaderHelloBack();
|
||||
void onSocketError(QAbstractSocket::SocketError error);
|
||||
void onIpcReaderRead(const QString &text);
|
||||
|
||||
private:
|
||||
std::unique_ptr<QTcpSocket> m_pSocket;
|
||||
std::unique_ptr<IpcReader> m_pReader;
|
||||
bool m_readerStarted = false;
|
||||
StreamProvider m_streamProvider;
|
||||
bool m_isConnected = false;
|
||||
bool m_isConnecting = false;
|
||||
};
|
||||
@ -1,32 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2012 - 2024 Symless Ltd
|
||||
# SPDX-FileCopyrightText: 2009 - 2012 Nick Bolton
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
add_library(ipc STATIC
|
||||
IpcClient.cpp
|
||||
IpcClient.h
|
||||
IpcClientProxy.cpp
|
||||
IpcClientProxy.h
|
||||
IpcLogOutputter.cpp
|
||||
IpcLogOutputter.h
|
||||
IpcMessage.cpp
|
||||
IpcMessage.h
|
||||
IpcServer.cpp
|
||||
IpcServer.h
|
||||
IpcServerProxy.cpp
|
||||
IpcServerProxy.h
|
||||
IpcSettingMessage.cpp
|
||||
IpcSettingMessage.h
|
||||
)
|
||||
|
||||
if(UNIX)
|
||||
target_link_libraries(
|
||||
ipc
|
||||
arch
|
||||
base
|
||||
mt
|
||||
io
|
||||
net
|
||||
app)
|
||||
endif()
|
||||
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "ipc/IpcClient.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "common/ipc.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServerProxy.h"
|
||||
|
||||
//
|
||||
// IpcClient
|
||||
//
|
||||
|
||||
IpcClient::IpcClient(IEventQueue *events, SocketMultiplexer *socketMultiplexer)
|
||||
: m_serverAddress(NetworkAddress(kIpcHost, kIpcPort)),
|
||||
m_socket(events, socketMultiplexer),
|
||||
m_server(nullptr),
|
||||
m_events(events)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
IpcClient::IpcClient(IEventQueue *events, SocketMultiplexer *socketMultiplexer, int port)
|
||||
: m_serverAddress(NetworkAddress(kIpcHost, port)),
|
||||
m_socket(events, socketMultiplexer),
|
||||
m_server(nullptr),
|
||||
m_events(events)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void IpcClient::init()
|
||||
{
|
||||
m_serverAddress.resolve();
|
||||
}
|
||||
|
||||
IpcClient::~IpcClient()
|
||||
{
|
||||
}
|
||||
|
||||
void IpcClient::connect()
|
||||
{
|
||||
m_events->adoptHandler(
|
||||
m_events->forIDataSocket().connected(), m_socket.getEventTarget(),
|
||||
new TMethodEventJob<IpcClient>(this, &IpcClient::handleConnected)
|
||||
);
|
||||
|
||||
m_socket.connect(m_serverAddress);
|
||||
m_server = new IpcServerProxy(m_socket, m_events);
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIpcServerProxy().messageReceived(), m_server,
|
||||
new TMethodEventJob<IpcClient>(this, &IpcClient::handleMessageReceived)
|
||||
);
|
||||
}
|
||||
|
||||
void IpcClient::disconnect()
|
||||
{
|
||||
m_events->removeHandler(m_events->forIDataSocket().connected(), m_socket.getEventTarget());
|
||||
m_events->removeHandler(m_events->forIpcServerProxy().messageReceived(), m_server);
|
||||
|
||||
m_server->disconnect();
|
||||
delete m_server;
|
||||
m_server = nullptr;
|
||||
}
|
||||
|
||||
void IpcClient::send(const IpcMessage &message)
|
||||
{
|
||||
assert(m_server != nullptr);
|
||||
m_server->send(message);
|
||||
}
|
||||
|
||||
void IpcClient::handleConnected(const Event &, void *)
|
||||
{
|
||||
m_events->addEvent(Event(m_events->forIpcClient().connected(), this, m_server, Event::kDontFreeData));
|
||||
|
||||
IpcHelloMessage message(IpcClientType::Node);
|
||||
send(message);
|
||||
}
|
||||
|
||||
void IpcClient::handleMessageReceived(const Event &e, void *)
|
||||
{
|
||||
Event event(m_events->forIpcClient().messageReceived(), this);
|
||||
event.setDataObject(e.getDataObject());
|
||||
m_events->addEvent(event);
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/EventTypes.h"
|
||||
#include "net/NetworkAddress.h"
|
||||
#include "net/TCPSocket.h"
|
||||
|
||||
class IpcServerProxy;
|
||||
class IpcMessage;
|
||||
class IEventQueue;
|
||||
class SocketMultiplexer;
|
||||
|
||||
//! IPC client for communication between daemon and GUI.
|
||||
/*!
|
||||
* See \ref IpcServer description.
|
||||
*/
|
||||
class IpcClient
|
||||
{
|
||||
public:
|
||||
IpcClient(IEventQueue *events, SocketMultiplexer *socketMultiplexer);
|
||||
IpcClient(IEventQueue *events, SocketMultiplexer *socketMultiplexer, int port);
|
||||
virtual ~IpcClient();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Connects to the IPC server at localhost.
|
||||
void connect();
|
||||
|
||||
//! Disconnects from the IPC server.
|
||||
void disconnect();
|
||||
|
||||
//! Sends a message to the server.
|
||||
void send(const IpcMessage &message);
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
void init();
|
||||
void handleConnected(const Event &, void *);
|
||||
void handleMessageReceived(const Event &, void *);
|
||||
|
||||
private:
|
||||
NetworkAddress m_serverAddress;
|
||||
TCPSocket m_socket;
|
||||
IpcServerProxy *m_server;
|
||||
IEventQueue *m_events;
|
||||
};
|
||||
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "ipc/IpcClientProxy.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "common/ipc.h"
|
||||
#include "deskflow/ProtocolUtil.h"
|
||||
#include "io/IStream.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcSettingMessage.h"
|
||||
|
||||
//
|
||||
// IpcClientProxy
|
||||
//
|
||||
|
||||
IpcClientProxy::IpcClientProxy(deskflow::IStream &stream, IEventQueue *events) : m_stream(stream), m_events(events)
|
||||
{
|
||||
m_events->adoptHandler(
|
||||
m_events->forIStream().inputReady(), stream.getEventTarget(),
|
||||
new TMethodEventJob<IpcClientProxy>(this, &IpcClientProxy::handleData)
|
||||
);
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIStream().outputError(), stream.getEventTarget(),
|
||||
new TMethodEventJob<IpcClientProxy>(this, &IpcClientProxy::handleWriteError)
|
||||
);
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIStream().inputShutdown(), stream.getEventTarget(),
|
||||
new TMethodEventJob<IpcClientProxy>(this, &IpcClientProxy::handleDisconnect)
|
||||
);
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIStream().outputShutdown(), stream.getEventTarget(),
|
||||
new TMethodEventJob<IpcClientProxy>(this, &IpcClientProxy::handleWriteError)
|
||||
);
|
||||
}
|
||||
|
||||
IpcClientProxy::~IpcClientProxy()
|
||||
{
|
||||
m_events->removeHandler(m_events->forIStream().inputReady(), m_stream.getEventTarget());
|
||||
m_events->removeHandler(m_events->forIStream().outputError(), m_stream.getEventTarget());
|
||||
m_events->removeHandler(m_events->forIStream().inputShutdown(), m_stream.getEventTarget());
|
||||
m_events->removeHandler(m_events->forIStream().outputShutdown(), m_stream.getEventTarget());
|
||||
|
||||
// don't delete the stream while it's being used.
|
||||
ARCH->lockMutex(m_readMutex);
|
||||
ARCH->lockMutex(m_writeMutex);
|
||||
delete &m_stream;
|
||||
ARCH->unlockMutex(m_readMutex);
|
||||
ARCH->unlockMutex(m_writeMutex);
|
||||
|
||||
ARCH->closeMutex(m_readMutex);
|
||||
ARCH->closeMutex(m_writeMutex);
|
||||
}
|
||||
|
||||
void IpcClientProxy::handleDisconnect(const Event &, void *)
|
||||
{
|
||||
disconnect();
|
||||
LOG((CLOG_DEBUG "ipc client disconnected"));
|
||||
}
|
||||
|
||||
void IpcClientProxy::handleWriteError(const Event &, void *)
|
||||
{
|
||||
disconnect();
|
||||
LOG((CLOG_DEBUG "ipc client write error"));
|
||||
}
|
||||
|
||||
void IpcClientProxy::handleData(const Event &, void *)
|
||||
{
|
||||
// don't allow the dtor to destroy the stream while we're using it.
|
||||
ArchMutexLock lock(m_readMutex);
|
||||
|
||||
LOG((CLOG_DEBUG "start ipc handle data"));
|
||||
|
||||
uint8_t code[4];
|
||||
uint32_t n = m_stream.read(code, 4);
|
||||
while (n != 0) {
|
||||
|
||||
LOG((CLOG_DEBUG "ipc read: %c%c%c%c", code[0], code[1], code[2], code[3]));
|
||||
|
||||
IpcMessage *m = nullptr;
|
||||
if (memcmp(code, kIpcMsgHello, 4) == 0) {
|
||||
m = parseHello();
|
||||
} else if (memcmp(code, kIpcMsgCommand, 4) == 0) {
|
||||
m = parseCommand();
|
||||
} else if (memcmp(code, kIpcMsgSetting, 4) == 0) {
|
||||
m = parseSetting();
|
||||
} else {
|
||||
LOG((CLOG_ERR "invalid ipc message"));
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// don't delete with this event; the data is passed to a new event.
|
||||
Event e(m_events->forIpcClientProxy().messageReceived(), this, NULL, Event::kDontFreeData);
|
||||
e.setDataObject(m);
|
||||
m_events->addEvent(e);
|
||||
|
||||
n = m_stream.read(code, 4);
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG "finished ipc handle data"));
|
||||
}
|
||||
|
||||
void IpcClientProxy::send(const IpcMessage &message)
|
||||
{
|
||||
// don't allow other threads to write until we've finished the entire
|
||||
// message. stream write is locked, but only for that single write.
|
||||
// also, don't allow the dtor to destroy the stream while we're using it.
|
||||
ArchMutexLock lock(m_writeMutex);
|
||||
|
||||
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));
|
||||
|
||||
switch (message.type()) {
|
||||
case IpcMessageType::LogLine: {
|
||||
const IpcLogLineMessage &llm = static_cast<const IpcLogLineMessage &>(message);
|
||||
const std::string logLine = llm.logLine();
|
||||
ProtocolUtil::writef(&m_stream, kIpcMsgLogLine, &logLine);
|
||||
break;
|
||||
}
|
||||
|
||||
case IpcMessageType::Shutdown:
|
||||
ProtocolUtil::writef(&m_stream, kIpcMsgShutdown);
|
||||
break;
|
||||
|
||||
case IpcMessageType::HelloBack:
|
||||
ProtocolUtil::writef(&m_stream, kIpcMsgHelloBack);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG((CLOG_ERR "ipc message not supported: %d", message.type()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IpcHelloMessage *IpcClientProxy::parseHello()
|
||||
{
|
||||
uint8_t type;
|
||||
ProtocolUtil::readf(&m_stream, kIpcMsgHello + 4, &type);
|
||||
|
||||
m_clientType = static_cast<IpcClientType>(type);
|
||||
|
||||
// must be deleted by event handler.
|
||||
return new IpcHelloMessage(m_clientType);
|
||||
}
|
||||
|
||||
IpcCommandMessage *IpcClientProxy::parseCommand()
|
||||
{
|
||||
std::string command;
|
||||
uint8_t elevate;
|
||||
ProtocolUtil::readf(&m_stream, kIpcMsgCommand + 4, &command, &elevate);
|
||||
|
||||
// must be deleted by event handler.
|
||||
return new IpcCommandMessage(command, elevate != 0);
|
||||
}
|
||||
|
||||
IpcSettingMessage *IpcClientProxy::parseSetting() const
|
||||
{
|
||||
std::string name;
|
||||
std::string value;
|
||||
|
||||
ProtocolUtil::readf(&m_stream, kIpcMsgSetting + 4, &name, &value);
|
||||
|
||||
// must be deleted by event handler.
|
||||
return new IpcSettingMessage(name, value);
|
||||
}
|
||||
|
||||
void IpcClientProxy::disconnect()
|
||||
{
|
||||
LOG((CLOG_DEBUG "ipc disconnect, closing stream"));
|
||||
m_disconnecting = true;
|
||||
m_stream.close();
|
||||
m_events->addEvent(Event(m_events->forIpcClientProxy().disconnected(), this));
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "base/Event.h"
|
||||
#include "base/EventTypes.h"
|
||||
#include "common/ipc.h"
|
||||
|
||||
namespace deskflow {
|
||||
class IStream;
|
||||
}
|
||||
class IpcMessage;
|
||||
class IpcCommandMessage;
|
||||
class IpcSettingMessage;
|
||||
class IpcHelloMessage;
|
||||
class IEventQueue;
|
||||
|
||||
class IpcClientProxy
|
||||
{
|
||||
friend class IpcServer;
|
||||
|
||||
public:
|
||||
IpcClientProxy(deskflow::IStream &stream, IEventQueue *events);
|
||||
IpcClientProxy(IpcClientProxy const &) = delete;
|
||||
IpcClientProxy(IpcClientProxy &&) = delete;
|
||||
virtual ~IpcClientProxy();
|
||||
|
||||
IpcClientProxy &operator=(IpcClientProxy const &) = delete;
|
||||
IpcClientProxy &operator=(IpcClientProxy &&) = delete;
|
||||
|
||||
private:
|
||||
void send(const IpcMessage &message);
|
||||
void handleData(const Event &, void *);
|
||||
void handleDisconnect(const Event &, void *);
|
||||
void handleWriteError(const Event &, void *);
|
||||
IpcHelloMessage *parseHello();
|
||||
IpcCommandMessage *parseCommand();
|
||||
IpcSettingMessage *parseSetting() const;
|
||||
void disconnect();
|
||||
|
||||
private:
|
||||
deskflow::IStream &m_stream;
|
||||
IEventQueue *m_events;
|
||||
IpcClientType m_clientType = IpcClientType::Unknown;
|
||||
bool m_disconnecting = false;
|
||||
ArchMutex m_readMutex = ARCH->newMutex();
|
||||
ArchMutex m_writeMutex = ARCH->newMutex();
|
||||
};
|
||||
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "ipc/IpcLogOutputter.h"
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/XArch.h"
|
||||
#include "base/Event.h"
|
||||
#include "base/EventQueue.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "base/TMethodJob.h"
|
||||
#include "common/ipc.h"
|
||||
#include "ipc/IpcClientProxy.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServer.h"
|
||||
#include "mt/Thread.h"
|
||||
|
||||
enum EIpcLogOutputter
|
||||
{
|
||||
kBufferMaxSize = 1000,
|
||||
kMaxSendLines = 100,
|
||||
kBufferRateWriteLimit = 1000, // writes per kBufferRateTime
|
||||
kBufferRateTimeLimit = 1 // seconds
|
||||
};
|
||||
|
||||
IpcLogOutputter::IpcLogOutputter(IpcServer &ipcServer, IpcClientType clientType, bool useThread)
|
||||
: m_ipcServer(ipcServer),
|
||||
m_bufferMutex(ARCH->newMutex()),
|
||||
m_sending(false),
|
||||
m_bufferThread(nullptr),
|
||||
m_running(false),
|
||||
m_notifyCond(ARCH->newCondVar()),
|
||||
m_notifyMutex(ARCH->newMutex()),
|
||||
m_bufferThreadId(0),
|
||||
m_bufferWaiting(false),
|
||||
m_bufferMaxSize(kBufferMaxSize),
|
||||
m_bufferRateWriteLimit(kBufferRateWriteLimit),
|
||||
m_bufferRateTimeLimit(kBufferRateTimeLimit),
|
||||
m_bufferWriteCount(0),
|
||||
m_bufferRateStart(ARCH->time()),
|
||||
m_clientType(clientType),
|
||||
m_runningMutex(ARCH->newMutex())
|
||||
{
|
||||
if (useThread) {
|
||||
const auto outputter =
|
||||
new TMethodJob<IpcLogOutputter>(this, &IpcLogOutputter::bufferThread); // NOSONAR -- Adopted by `Log`
|
||||
m_bufferThread = new Thread(outputter);
|
||||
}
|
||||
}
|
||||
|
||||
IpcLogOutputter::~IpcLogOutputter()
|
||||
{
|
||||
close();
|
||||
|
||||
ARCH->closeMutex(m_bufferMutex);
|
||||
|
||||
if (m_bufferThread != nullptr) {
|
||||
m_bufferThread->cancel();
|
||||
m_bufferThread->wait();
|
||||
delete m_bufferThread;
|
||||
}
|
||||
|
||||
ARCH->closeCondVar(m_notifyCond);
|
||||
ARCH->closeMutex(m_notifyMutex);
|
||||
}
|
||||
|
||||
void IpcLogOutputter::open(const char *title)
|
||||
{
|
||||
}
|
||||
|
||||
void IpcLogOutputter::close()
|
||||
{
|
||||
if (m_bufferThread != nullptr) {
|
||||
ArchMutexLock lock(m_runningMutex);
|
||||
m_running = false;
|
||||
notifyBuffer();
|
||||
m_bufferThread->wait(5);
|
||||
}
|
||||
}
|
||||
|
||||
void IpcLogOutputter::show(bool showIfEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
bool IpcLogOutputter::write(ELevel, const char *text)
|
||||
{
|
||||
// ignore events from the buffer thread (would cause recursion).
|
||||
if (m_bufferThread != nullptr && Thread::getCurrentThread().getID() == m_bufferThreadId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
appendBuffer(text);
|
||||
notifyBuffer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IpcLogOutputter::appendBuffer(const std::string &text)
|
||||
{
|
||||
ArchMutexLock lock(m_bufferMutex);
|
||||
|
||||
double elapsed = ARCH->time() - m_bufferRateStart;
|
||||
if (elapsed < m_bufferRateTimeLimit) {
|
||||
if (m_bufferWriteCount >= m_bufferRateWriteLimit) {
|
||||
// discard the log line if we've logged too much.
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
m_bufferWriteCount = 0;
|
||||
m_bufferRateStart = ARCH->time();
|
||||
}
|
||||
|
||||
if (m_buffer.size() >= m_bufferMaxSize) {
|
||||
// if the queue is exceeds size limit,
|
||||
// throw away the oldest item
|
||||
m_buffer.pop_front();
|
||||
}
|
||||
|
||||
m_buffer.push_back(text);
|
||||
m_bufferWriteCount++;
|
||||
}
|
||||
|
||||
bool IpcLogOutputter::isRunning()
|
||||
{
|
||||
ArchMutexLock lock(m_runningMutex);
|
||||
return m_running;
|
||||
}
|
||||
|
||||
void IpcLogOutputter::bufferThread(void *)
|
||||
{
|
||||
m_bufferThreadId = m_bufferThread->getID();
|
||||
m_running = true;
|
||||
|
||||
try {
|
||||
while (isRunning()) {
|
||||
if (m_buffer.empty() || !m_ipcServer.hasClients(m_clientType)) {
|
||||
ArchMutexLock lock(m_notifyMutex);
|
||||
ARCH->waitCondVar(m_notifyCond, m_notifyMutex, -1);
|
||||
}
|
||||
|
||||
sendBuffer();
|
||||
}
|
||||
} catch (XArch &e) {
|
||||
LOG((CLOG_ERR "ipc log buffer thread error, %s", e.what()));
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG "ipc log buffer thread finished"));
|
||||
}
|
||||
|
||||
void IpcLogOutputter::notifyBuffer()
|
||||
{
|
||||
ArchMutexLock lock(m_notifyMutex);
|
||||
ARCH->broadcastCondVar(m_notifyCond);
|
||||
}
|
||||
|
||||
std::string IpcLogOutputter::getChunk(size_t count)
|
||||
{
|
||||
ArchMutexLock lock(m_bufferMutex);
|
||||
|
||||
if (m_buffer.size() < count) {
|
||||
count = m_buffer.size();
|
||||
}
|
||||
|
||||
std::string chunk;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
chunk.append(m_buffer.front());
|
||||
chunk.append("\n");
|
||||
m_buffer.pop_front();
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
void IpcLogOutputter::sendBuffer()
|
||||
{
|
||||
if (m_buffer.empty() || !m_ipcServer.hasClients(m_clientType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IpcLogLineMessage message(getChunk(kMaxSendLines));
|
||||
m_sending = true;
|
||||
m_ipcServer.send(message, IpcClientType::GUI);
|
||||
m_sending = false;
|
||||
}
|
||||
|
||||
void IpcLogOutputter::bufferMaxSize(uint16_t bufferMaxSize)
|
||||
{
|
||||
m_bufferMaxSize = bufferMaxSize;
|
||||
}
|
||||
|
||||
uint16_t IpcLogOutputter::bufferMaxSize() const
|
||||
{
|
||||
return m_bufferMaxSize;
|
||||
}
|
||||
|
||||
void IpcLogOutputter::bufferRateLimit(uint16_t writeLimit, double timeLimit)
|
||||
{
|
||||
m_bufferRateWriteLimit = writeLimit;
|
||||
m_bufferRateTimeLimit = timeLimit;
|
||||
}
|
||||
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "base/ILogOutputter.h"
|
||||
#include "common/ipc.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
class IpcServer;
|
||||
class Event;
|
||||
class IpcClientProxy;
|
||||
|
||||
//! Write log to GUI over IPC
|
||||
/*!
|
||||
This outputter writes output to the GUI via IPC.
|
||||
*/
|
||||
class IpcLogOutputter : public ILogOutputter
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
If \p useThread is \c true, the buffer will be sent using a thread.
|
||||
If \p useThread is \c false, then the buffer needs to be sent manually
|
||||
using the \c sendBuffer() function.
|
||||
*/
|
||||
IpcLogOutputter(IpcServer &ipcServer, IpcClientType clientType, bool useThread);
|
||||
IpcLogOutputter(IpcLogOutputter const &) = delete;
|
||||
virtual ~IpcLogOutputter();
|
||||
|
||||
// ILogOutputter overrides
|
||||
virtual void open(const char *title);
|
||||
virtual void close();
|
||||
virtual void show(bool showIfEmpty);
|
||||
virtual bool write(ELevel level, const char *message);
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Notify that the buffer should be sent.
|
||||
void notifyBuffer();
|
||||
|
||||
//! Set the buffer size
|
||||
/*!
|
||||
Set the maximum size of the buffer to protect memory
|
||||
from runaway logging.
|
||||
*/
|
||||
void bufferMaxSize(uint16_t bufferMaxSize);
|
||||
|
||||
//! Set the rate limit
|
||||
/*!
|
||||
Set the maximum number of \p writeRate for every \p timeRate in seconds.
|
||||
*/
|
||||
void bufferRateLimit(uint16_t writeLimit, double timeLimit);
|
||||
|
||||
//! Send the buffer
|
||||
/*!
|
||||
Sends a chunk of the buffer to the IPC server, normally called
|
||||
when threaded mode is on.
|
||||
*/
|
||||
void sendBuffer();
|
||||
|
||||
//@}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get the buffer size
|
||||
/*!
|
||||
Returns the maximum size of the buffer.
|
||||
*/
|
||||
uint16_t bufferMaxSize() const;
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
void init();
|
||||
void bufferThread(void *);
|
||||
std::string getChunk(size_t count);
|
||||
void appendBuffer(const std::string &text);
|
||||
bool isRunning();
|
||||
|
||||
private:
|
||||
using Buffer = std::deque<std::string>;
|
||||
|
||||
IpcServer &m_ipcServer;
|
||||
Buffer m_buffer;
|
||||
ArchMutex m_bufferMutex;
|
||||
bool m_sending;
|
||||
Thread *m_bufferThread;
|
||||
bool m_running;
|
||||
ArchCond m_notifyCond;
|
||||
ArchMutex m_notifyMutex;
|
||||
bool m_bufferWaiting;
|
||||
IArchMultithread::ThreadID m_bufferThreadId;
|
||||
uint16_t m_bufferMaxSize;
|
||||
uint16_t m_bufferRateWriteLimit;
|
||||
double m_bufferRateTimeLimit;
|
||||
uint16_t m_bufferWriteCount;
|
||||
double m_bufferRateStart;
|
||||
IpcClientType m_clientType;
|
||||
ArchMutex m_runningMutex;
|
||||
};
|
||||
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "common/ipc.h"
|
||||
|
||||
IpcMessage::IpcMessage(IpcMessageType type) : m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
IpcHelloMessage::IpcHelloMessage(IpcClientType clientType) : IpcMessage(IpcMessageType::Hello), m_clientType(clientType)
|
||||
{
|
||||
}
|
||||
|
||||
IpcHelloBackMessage::IpcHelloBackMessage() : IpcMessage(IpcMessageType::HelloBack)
|
||||
{
|
||||
}
|
||||
|
||||
IpcShutdownMessage::IpcShutdownMessage() : IpcMessage(IpcMessageType::Shutdown)
|
||||
{
|
||||
}
|
||||
|
||||
IpcLogLineMessage::IpcLogLineMessage(const std::string &logLine)
|
||||
: IpcMessage(IpcMessageType::LogLine),
|
||||
m_logLine(logLine)
|
||||
{
|
||||
}
|
||||
|
||||
IpcCommandMessage::IpcCommandMessage(const std::string &command, bool elevate)
|
||||
: IpcMessage(IpcMessageType::Command),
|
||||
m_command(command),
|
||||
m_elevate(elevate)
|
||||
{
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Event.h"
|
||||
#include "common/ipc.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class IpcMessage : public EventData
|
||||
{
|
||||
public:
|
||||
~IpcMessage() override = default;
|
||||
|
||||
//! Gets the message type ID.
|
||||
IpcMessageType type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit IpcMessage(IpcMessageType type);
|
||||
|
||||
private:
|
||||
IpcMessageType m_type;
|
||||
};
|
||||
|
||||
class IpcHelloMessage : public IpcMessage
|
||||
{
|
||||
public:
|
||||
explicit IpcHelloMessage(IpcClientType clientType);
|
||||
~IpcHelloMessage() override = default;
|
||||
|
||||
//! Gets the message type ID.
|
||||
IpcClientType clientType() const
|
||||
{
|
||||
return m_clientType;
|
||||
}
|
||||
|
||||
private:
|
||||
IpcClientType m_clientType;
|
||||
};
|
||||
|
||||
class IpcHelloBackMessage : public IpcMessage
|
||||
{
|
||||
public:
|
||||
explicit IpcHelloBackMessage();
|
||||
~IpcHelloBackMessage() override = default;
|
||||
};
|
||||
|
||||
class IpcShutdownMessage : public IpcMessage
|
||||
{
|
||||
public:
|
||||
explicit IpcShutdownMessage();
|
||||
~IpcShutdownMessage() override = default;
|
||||
};
|
||||
|
||||
class IpcLogLineMessage : public IpcMessage
|
||||
{
|
||||
public:
|
||||
explicit IpcLogLineMessage(const std::string &logLine);
|
||||
~IpcLogLineMessage() override = default;
|
||||
|
||||
//! Gets the log line.
|
||||
std::string logLine() const
|
||||
{
|
||||
return m_logLine;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_logLine;
|
||||
};
|
||||
|
||||
class IpcCommandMessage : public IpcMessage
|
||||
{
|
||||
public:
|
||||
explicit IpcCommandMessage(const std::string &command, bool elevate);
|
||||
~IpcCommandMessage() override = default;
|
||||
|
||||
//! Gets the command.
|
||||
std::string command() const
|
||||
{
|
||||
return m_command;
|
||||
}
|
||||
|
||||
//! Gets whether or not the process should be elevated on MS Windows.
|
||||
bool elevate() const
|
||||
{
|
||||
return m_elevate;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_command;
|
||||
bool m_elevate;
|
||||
};
|
||||
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "ipc/IpcServer.h"
|
||||
|
||||
#include "base/Event.h"
|
||||
#include "base/IEventQueue.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "common/ipc.h"
|
||||
#include "io/IStream.h"
|
||||
#include "ipc/IpcClientProxy.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "net/IDataSocket.h"
|
||||
|
||||
//
|
||||
// IpcServer
|
||||
//
|
||||
|
||||
IpcServer::IpcServer(IEventQueue *events, SocketMultiplexer *socketMultiplexer)
|
||||
: m_mock(false),
|
||||
m_events(events),
|
||||
m_socketMultiplexer(socketMultiplexer),
|
||||
m_socket(nullptr),
|
||||
m_address(NetworkAddress(kIpcHost, kIpcPort))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
IpcServer::IpcServer(IEventQueue *events, SocketMultiplexer *socketMultiplexer, int port)
|
||||
: m_mock(false),
|
||||
m_events(events),
|
||||
m_socketMultiplexer(socketMultiplexer),
|
||||
m_address(NetworkAddress(kIpcHost, port))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void IpcServer::init()
|
||||
{
|
||||
m_socket = new TCPListenSocket(m_events, m_socketMultiplexer, IArchNetwork::EAddressFamily::kINET);
|
||||
|
||||
m_clientsMutex = ARCH->newMutex();
|
||||
m_address.resolve();
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIListenSocket().connecting(), m_socket,
|
||||
new TMethodEventJob<IpcServer>(this, &IpcServer::handleClientConnecting)
|
||||
);
|
||||
}
|
||||
|
||||
IpcServer::~IpcServer()
|
||||
{
|
||||
if (m_mock) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_socket != nullptr) {
|
||||
delete m_socket;
|
||||
}
|
||||
|
||||
ARCH->lockMutex(m_clientsMutex);
|
||||
ClientList::iterator it;
|
||||
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||
deleteClient(*it);
|
||||
}
|
||||
m_clients.clear();
|
||||
ARCH->unlockMutex(m_clientsMutex);
|
||||
ARCH->closeMutex(m_clientsMutex);
|
||||
|
||||
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_socket);
|
||||
}
|
||||
|
||||
void IpcServer::listen()
|
||||
{
|
||||
m_socket->bind(m_address);
|
||||
}
|
||||
|
||||
void IpcServer::handleClientConnecting(const Event &, void *)
|
||||
{
|
||||
deskflow::IStream *stream = m_socket->accept();
|
||||
if (stream == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG "accepted ipc client connection"));
|
||||
|
||||
ARCH->lockMutex(m_clientsMutex);
|
||||
IpcClientProxy *proxy = new IpcClientProxy(*stream, m_events);
|
||||
m_clients.push_back(proxy);
|
||||
ARCH->unlockMutex(m_clientsMutex);
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIpcClientProxy().disconnected(), proxy,
|
||||
new TMethodEventJob<IpcServer>(this, &IpcServer::handleClientDisconnected)
|
||||
);
|
||||
|
||||
m_events->adoptHandler(
|
||||
m_events->forIpcClientProxy().messageReceived(), proxy,
|
||||
new TMethodEventJob<IpcServer>(this, &IpcServer::handleMessageReceived)
|
||||
);
|
||||
|
||||
m_events->addEvent(Event(m_events->forIpcServer().clientConnected(), this, proxy, Event::kDontFreeData));
|
||||
}
|
||||
|
||||
void IpcServer::handleClientDisconnected(const Event &e, void *)
|
||||
{
|
||||
IpcClientProxy *proxy = static_cast<IpcClientProxy *>(e.getTarget());
|
||||
|
||||
ArchMutexLock lock(m_clientsMutex);
|
||||
m_clients.remove(proxy);
|
||||
deleteClient(proxy);
|
||||
|
||||
LOG((CLOG_DEBUG "ipc client proxy removed, connected=%d", m_clients.size()));
|
||||
}
|
||||
|
||||
void IpcServer::handleMessageReceived(const Event &e, void *)
|
||||
{
|
||||
Event event(m_events->forIpcServer().messageReceived(), this);
|
||||
event.setDataObject(e.getDataObject());
|
||||
m_events->addEvent(event);
|
||||
}
|
||||
|
||||
void IpcServer::deleteClient(IpcClientProxy *proxy)
|
||||
{
|
||||
m_events->removeHandler(m_events->forIpcClientProxy().messageReceived(), proxy);
|
||||
m_events->removeHandler(m_events->forIpcClientProxy().disconnected(), proxy);
|
||||
delete proxy;
|
||||
}
|
||||
|
||||
bool IpcServer::hasClients(IpcClientType clientType) const
|
||||
{
|
||||
ArchMutexLock lock(m_clientsMutex);
|
||||
|
||||
if (m_clients.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientList::const_iterator it;
|
||||
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||
// at least one client is alive and type matches, there are clients.
|
||||
IpcClientProxy *p = *it;
|
||||
if (!p->m_disconnecting && p->m_clientType == clientType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// all clients must be disconnecting, no active clients.
|
||||
return false;
|
||||
}
|
||||
|
||||
void IpcServer::send(const IpcMessage &message, IpcClientType filterType)
|
||||
{
|
||||
ArchMutexLock lock(m_clientsMutex);
|
||||
|
||||
ClientList::iterator it;
|
||||
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||
IpcClientProxy *proxy = *it;
|
||||
if (proxy->m_clientType == filterType) {
|
||||
proxy->send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "base/EventTypes.h"
|
||||
#include "common/ipc.h"
|
||||
#include "net/NetworkAddress.h"
|
||||
#include "net/TCPListenSocket.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
class Event;
|
||||
class IpcClientProxy;
|
||||
class IpcMessage;
|
||||
class IEventQueue;
|
||||
class SocketMultiplexer;
|
||||
|
||||
//! IPC server for communication between daemon and GUI.
|
||||
/*!
|
||||
The IPC server listens on localhost. The IPC client runs on both the
|
||||
client/server process or the GUI. The IPC server runs on the daemon process.
|
||||
This allows the GUI to send config changes to the daemon and client/server,
|
||||
and allows the daemon and client/server to send log data to the GUI.
|
||||
*/
|
||||
class IpcServer
|
||||
{
|
||||
public:
|
||||
IpcServer(IEventQueue *events, SocketMultiplexer *socketMultiplexer);
|
||||
IpcServer(IEventQueue *events, SocketMultiplexer *socketMultiplexer, int port);
|
||||
IpcServer(IpcServer const &) = delete;
|
||||
IpcServer(IpcServer &&) = delete;
|
||||
virtual ~IpcServer();
|
||||
|
||||
IpcServer &operator=(IpcServer const &) = delete;
|
||||
IpcServer &operator=(IpcServer &&) = delete;
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Opens a TCP socket only allowing local connections.
|
||||
virtual void listen();
|
||||
|
||||
//! Send a message to all clients matching the filter type.
|
||||
virtual void send(const IpcMessage &message, IpcClientType filterType);
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Returns true when there are clients of the specified type connected.
|
||||
virtual bool hasClients(IpcClientType clientType) const;
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
void init();
|
||||
void handleClientConnecting(const Event &, void *);
|
||||
void handleClientDisconnected(const Event &, void *);
|
||||
void handleMessageReceived(const Event &, void *);
|
||||
void deleteClient(IpcClientProxy *proxy);
|
||||
|
||||
private:
|
||||
using ClientList = std::list<IpcClientProxy *>;
|
||||
|
||||
bool m_mock;
|
||||
IEventQueue *m_events;
|
||||
SocketMultiplexer *m_socketMultiplexer;
|
||||
TCPListenSocket *m_socket;
|
||||
NetworkAddress m_address;
|
||||
ClientList m_clients;
|
||||
ArchMutex m_clientsMutex;
|
||||
|
||||
#ifdef TEST_ENV
|
||||
public:
|
||||
IpcServer() : m_mock(true), m_events(nullptr), m_socketMultiplexer(nullptr), m_socket(nullptr)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "ipc/IpcServerProxy.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "common/ipc.h"
|
||||
#include "deskflow/ProtocolUtil.h"
|
||||
#include "io/IStream.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
|
||||
//
|
||||
// IpcServerProxy
|
||||
//
|
||||
|
||||
IpcServerProxy::IpcServerProxy(deskflow::IStream &stream, IEventQueue *events) : m_stream(stream), m_events(events)
|
||||
{
|
||||
m_events->adoptHandler(
|
||||
m_events->forIStream().inputReady(), stream.getEventTarget(),
|
||||
new TMethodEventJob<IpcServerProxy>(this, &IpcServerProxy::handleData)
|
||||
);
|
||||
}
|
||||
|
||||
IpcServerProxy::~IpcServerProxy()
|
||||
{
|
||||
m_events->removeHandler(m_events->forIStream().inputReady(), m_stream.getEventTarget());
|
||||
}
|
||||
|
||||
void IpcServerProxy::handleData(const Event &, void *)
|
||||
{
|
||||
LOG((CLOG_DEBUG "start ipc handle data"));
|
||||
|
||||
uint8_t code[4];
|
||||
uint32_t n = m_stream.read(code, 4);
|
||||
while (n != 0) {
|
||||
|
||||
LOG((CLOG_DEBUG "ipc read: %c%c%c%c", code[0], code[1], code[2], code[3]));
|
||||
|
||||
IpcMessage *m = nullptr;
|
||||
if (memcmp(code, kIpcMsgLogLine, 4) == 0) {
|
||||
m = parseLogLine();
|
||||
} else if (memcmp(code, kIpcMsgShutdown, 4) == 0) {
|
||||
m = new IpcShutdownMessage();
|
||||
} else {
|
||||
LOG((CLOG_ERR "invalid ipc message"));
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// don't delete with this event; the data is passed to a new event.
|
||||
Event e(m_events->forIpcServerProxy().messageReceived(), this, NULL, Event::kDontFreeData);
|
||||
e.setDataObject(m);
|
||||
m_events->addEvent(e);
|
||||
|
||||
n = m_stream.read(code, 4);
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG "finished ipc handle data"));
|
||||
}
|
||||
|
||||
void IpcServerProxy::send(const IpcMessage &message)
|
||||
{
|
||||
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));
|
||||
|
||||
switch (message.type()) {
|
||||
case IpcMessageType::Hello: {
|
||||
const IpcHelloMessage &hm = static_cast<const IpcHelloMessage &>(message);
|
||||
ProtocolUtil::writef(&m_stream, kIpcMsgHello, hm.clientType());
|
||||
break;
|
||||
}
|
||||
|
||||
case IpcMessageType::Command: {
|
||||
const IpcCommandMessage &cm = static_cast<const IpcCommandMessage &>(message);
|
||||
const std::string command = cm.command();
|
||||
ProtocolUtil::writef(&m_stream, kIpcMsgCommand, &command);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG((CLOG_ERR "ipc message not supported: %d", message.type()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IpcLogLineMessage *IpcServerProxy::parseLogLine()
|
||||
{
|
||||
std::string logLine;
|
||||
ProtocolUtil::readf(&m_stream, kIpcMsgLogLine + 4, &logLine);
|
||||
|
||||
// must be deleted by event handler.
|
||||
return new IpcLogLineMessage(logLine);
|
||||
}
|
||||
|
||||
void IpcServerProxy::disconnect()
|
||||
{
|
||||
LOG((CLOG_DEBUG "ipc disconnect, closing stream"));
|
||||
m_stream.close();
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Event.h"
|
||||
#include "base/EventTypes.h"
|
||||
|
||||
namespace deskflow {
|
||||
class IStream;
|
||||
}
|
||||
class IpcMessage;
|
||||
class IpcLogLineMessage;
|
||||
class IEventQueue;
|
||||
|
||||
class IpcServerProxy
|
||||
{
|
||||
friend class IpcClient;
|
||||
|
||||
public:
|
||||
IpcServerProxy(deskflow::IStream &stream, IEventQueue *events);
|
||||
IpcServerProxy(IpcServerProxy const &) = delete;
|
||||
virtual ~IpcServerProxy();
|
||||
|
||||
private:
|
||||
void send(const IpcMessage &message);
|
||||
|
||||
void handleData(const Event &, void *);
|
||||
IpcLogLineMessage *parseLogLine();
|
||||
void disconnect();
|
||||
|
||||
private:
|
||||
deskflow::IStream &m_stream;
|
||||
IEventQueue *m_events;
|
||||
};
|
||||
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "IpcSettingMessage.h"
|
||||
|
||||
IpcSettingMessage::IpcSettingMessage(const std::string &name, const std::string &value)
|
||||
: IpcMessage(IpcMessageType::Setting),
|
||||
m_name(name),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string &IpcSettingMessage::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string &IpcSettingMessage::getValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IpcMessage.h"
|
||||
#include <string>
|
||||
|
||||
class IpcSettingMessage : public IpcMessage
|
||||
{
|
||||
public:
|
||||
//!
|
||||
//! \brief IpcSettingMessage constructor
|
||||
//! \param name - setting name
|
||||
//! \param value - setting value
|
||||
//!
|
||||
IpcSettingMessage(const std::string &name, const std::string &value);
|
||||
|
||||
//!
|
||||
//! \brief getName is a getter for the setting name
|
||||
//! \return setting name
|
||||
//!
|
||||
const std::string &getName() const;
|
||||
|
||||
//!
|
||||
//! \brief getValue is a getter for the setting value
|
||||
//! \return setting value
|
||||
//!
|
||||
const std::string &getValue() const;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_value;
|
||||
};
|
||||
@ -179,7 +179,6 @@ if(UNIX)
|
||||
platform
|
||||
io
|
||||
net
|
||||
ipc
|
||||
app
|
||||
client
|
||||
${libs})
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
#include "base/Log.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2009 Chris Schoeneman
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
@ -13,12 +12,8 @@
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodJob.h"
|
||||
#include "base/log_outputters.h"
|
||||
#include "common/ipc.h"
|
||||
#include "deskflow/App.h"
|
||||
#include "deskflow/ArgsBase.h"
|
||||
#include "ipc/IpcLogOutputter.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServer.h"
|
||||
#include "mt/Thread.h"
|
||||
|
||||
#include <Shellapi.h>
|
||||
@ -437,7 +432,7 @@ void MSWindowsWatchdog::outputLoop(void *)
|
||||
// process output to the VS debug output window.
|
||||
// we could use the MSWindowsDebugOutputter, but it's really fiddly to
|
||||
// so, and there doesn't seem to be an advantage of doing that.
|
||||
OutputDebugString(output.c_str());
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2009 Chris Schoeneman
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
@ -19,8 +18,6 @@
|
||||
#include <string>
|
||||
|
||||
class Thread;
|
||||
class IpcLogOutputter;
|
||||
class IpcServer;
|
||||
class FileLogOutputter;
|
||||
|
||||
class MSWindowsWatchdog
|
||||
|
||||
@ -140,7 +140,6 @@ macro(config_test_deps)
|
||||
server
|
||||
app
|
||||
mt
|
||||
ipc
|
||||
gui
|
||||
GTest::gtest
|
||||
GTest::gmock
|
||||
|
||||
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
// TODO: fix, tests failing intermittently on mac.
|
||||
#ifndef WINAPI_CARBON
|
||||
|
||||
#define TEST_ENV
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "base/EventQueue.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/TMethodEventJob.h"
|
||||
#include "base/TMethodJob.h"
|
||||
#include "common/ipc.h"
|
||||
#include "ipc/IpcClient.h"
|
||||
#include "ipc/IpcClientProxy.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServer.h"
|
||||
#include "ipc/IpcServerProxy.h"
|
||||
#include "mt/Thread.h"
|
||||
#include "net/SocketMultiplexer.h"
|
||||
#include "test/shared/TestEventQueue.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
const int kTestPort = 24802;
|
||||
|
||||
class IpcTests : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
IpcTests();
|
||||
virtual ~IpcTests();
|
||||
|
||||
void connectToServer_handleMessageReceived(const Event &, void *);
|
||||
void sendMessageToServer_serverHandleMessageReceived(const Event &, void *);
|
||||
void sendMessageToClient_serverHandleClientConnected(const Event &, void *);
|
||||
void sendMessageToClient_clientHandleMessageReceived(const Event &, void *);
|
||||
|
||||
public:
|
||||
SocketMultiplexer m_multiplexer;
|
||||
bool m_connectToServer_helloMessageReceived;
|
||||
bool m_connectToServer_hasClientNode;
|
||||
IpcServer *m_connectToServer_server;
|
||||
std::string m_sendMessageToServer_receivedString;
|
||||
std::string m_sendMessageToClient_receivedString;
|
||||
IpcClient *m_sendMessageToServer_client;
|
||||
IpcServer *m_sendMessageToClient_server;
|
||||
TestEventQueue m_events;
|
||||
};
|
||||
|
||||
TEST_F(IpcTests, connectToServer)
|
||||
{
|
||||
SocketMultiplexer socketMultiplexer;
|
||||
IpcServer server(&m_events, &socketMultiplexer, kTestPort);
|
||||
server.listen();
|
||||
m_connectToServer_server = &server;
|
||||
|
||||
m_events.adoptHandler(
|
||||
m_events.forIpcServer().messageReceived(), &server,
|
||||
new TMethodEventJob<IpcTests>(this, &IpcTests::connectToServer_handleMessageReceived)
|
||||
);
|
||||
|
||||
IpcClient client(&m_events, &socketMultiplexer, kTestPort);
|
||||
client.connect();
|
||||
|
||||
m_events.initQuitTimeout(5);
|
||||
m_events.loop();
|
||||
m_events.removeHandler(m_events.forIpcServer().messageReceived(), &server);
|
||||
m_events.cleanupQuitTimeout();
|
||||
|
||||
EXPECT_EQ(true, m_connectToServer_helloMessageReceived);
|
||||
EXPECT_EQ(true, m_connectToServer_hasClientNode);
|
||||
}
|
||||
|
||||
TEST_F(IpcTests, sendMessageToServer)
|
||||
{
|
||||
SocketMultiplexer socketMultiplexer;
|
||||
IpcServer server(&m_events, &socketMultiplexer, kTestPort);
|
||||
server.listen();
|
||||
|
||||
// event handler sends "test" command to server.
|
||||
m_events.adoptHandler(
|
||||
m_events.forIpcServer().messageReceived(), &server,
|
||||
new TMethodEventJob<IpcTests>(this, &IpcTests::sendMessageToServer_serverHandleMessageReceived)
|
||||
);
|
||||
|
||||
IpcClient client(&m_events, &socketMultiplexer, kTestPort);
|
||||
client.connect();
|
||||
m_sendMessageToServer_client = &client;
|
||||
|
||||
m_events.initQuitTimeout(5);
|
||||
m_events.loop();
|
||||
m_events.removeHandler(m_events.forIpcServer().messageReceived(), &server);
|
||||
m_events.cleanupQuitTimeout();
|
||||
|
||||
EXPECT_EQ("test", m_sendMessageToServer_receivedString);
|
||||
}
|
||||
|
||||
TEST_F(IpcTests, sendMessageToClient)
|
||||
{
|
||||
SocketMultiplexer socketMultiplexer;
|
||||
IpcServer server(&m_events, &socketMultiplexer, kTestPort);
|
||||
server.listen();
|
||||
m_sendMessageToClient_server = &server;
|
||||
|
||||
// event handler sends "test" log line to client.
|
||||
m_events.adoptHandler(
|
||||
m_events.forIpcServer().messageReceived(), &server,
|
||||
new TMethodEventJob<IpcTests>(this, &IpcTests::sendMessageToClient_serverHandleClientConnected)
|
||||
);
|
||||
|
||||
IpcClient client(&m_events, &socketMultiplexer, kTestPort);
|
||||
client.connect();
|
||||
|
||||
m_events.adoptHandler(
|
||||
m_events.forIpcClient().messageReceived(), &client,
|
||||
new TMethodEventJob<IpcTests>(this, &IpcTests::sendMessageToClient_clientHandleMessageReceived)
|
||||
);
|
||||
|
||||
m_events.initQuitTimeout(5);
|
||||
m_events.loop();
|
||||
m_events.removeHandler(m_events.forIpcServer().messageReceived(), &server);
|
||||
m_events.removeHandler(m_events.forIpcClient().messageReceived(), &client);
|
||||
m_events.cleanupQuitTimeout();
|
||||
|
||||
EXPECT_EQ("test", m_sendMessageToClient_receivedString);
|
||||
}
|
||||
|
||||
IpcTests::IpcTests()
|
||||
: m_connectToServer_helloMessageReceived(false),
|
||||
m_connectToServer_hasClientNode(false),
|
||||
m_connectToServer_server(nullptr),
|
||||
m_sendMessageToClient_server(nullptr),
|
||||
m_sendMessageToServer_client(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
IpcTests::~IpcTests()
|
||||
{
|
||||
}
|
||||
|
||||
void IpcTests::connectToServer_handleMessageReceived(const Event &e, void *)
|
||||
{
|
||||
IpcMessage *m = static_cast<IpcMessage *>(e.getDataObject());
|
||||
if (m->type() == IpcMessageType::Hello) {
|
||||
m_connectToServer_hasClientNode = m_connectToServer_server->hasClients(IpcClientType::Node);
|
||||
m_connectToServer_helloMessageReceived = true;
|
||||
m_events.raiseQuitEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void IpcTests::sendMessageToServer_serverHandleMessageReceived(const Event &e, void *)
|
||||
{
|
||||
IpcMessage *m = static_cast<IpcMessage *>(e.getDataObject());
|
||||
if (m->type() == IpcMessageType::Hello) {
|
||||
LOG((CLOG_DEBUG "client said hello, sending test to server"));
|
||||
IpcCommandMessage m("test", true);
|
||||
m_sendMessageToServer_client->send(m);
|
||||
} else if (m->type() == IpcMessageType::Command) {
|
||||
IpcCommandMessage *cm = static_cast<IpcCommandMessage *>(m);
|
||||
LOG((CLOG_DEBUG "got ipc command message, %d", cm->command().c_str()));
|
||||
m_sendMessageToServer_receivedString = cm->command();
|
||||
m_events.raiseQuitEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void IpcTests::sendMessageToClient_serverHandleClientConnected(const Event &e, void *)
|
||||
{
|
||||
IpcMessage *m = static_cast<IpcMessage *>(e.getDataObject());
|
||||
if (m->type() == IpcMessageType::Hello) {
|
||||
LOG((CLOG_DEBUG "client said hello, sending test to client"));
|
||||
IpcLogLineMessage m("test");
|
||||
m_sendMessageToClient_server->send(m, IpcClientType::Node);
|
||||
}
|
||||
}
|
||||
|
||||
void IpcTests::sendMessageToClient_clientHandleMessageReceived(const Event &e, void *)
|
||||
{
|
||||
IpcMessage *m = static_cast<IpcMessage *>(e.getDataObject());
|
||||
if (m->type() == IpcMessageType::LogLine) {
|
||||
IpcLogLineMessage *llm = static_cast<IpcLogLineMessage *>(m);
|
||||
LOG((CLOG_DEBUG "got ipc log message, %d", llm->logLine().c_str()));
|
||||
m_sendMessageToClient_receivedString = llm->logLine();
|
||||
m_events.raiseQuitEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WINAPI_CARBON
|
||||
@ -34,10 +34,6 @@ public:
|
||||
MOCK_METHOD(void *, getSystemTarget, (), (override));
|
||||
MOCK_METHOD(ClientEvents &, forClient, (), (override));
|
||||
MOCK_METHOD(IStreamEvents &, forIStream, (), (override));
|
||||
MOCK_METHOD(IpcClientEvents &, forIpcClient, (), (override));
|
||||
MOCK_METHOD(IpcClientProxyEvents &, forIpcClientProxy, (), (override));
|
||||
MOCK_METHOD(IpcServerEvents &, forIpcServer, (), (override));
|
||||
MOCK_METHOD(IpcServerProxyEvents &, forIpcServerProxy, (), (override));
|
||||
MOCK_METHOD(IDataSocketEvents &, forIDataSocket, (), (override));
|
||||
MOCK_METHOD(IListenSocketEvents &, forIListenSocket, (), (override));
|
||||
MOCK_METHOD(ISocketEvents &, forISocket, (), (override));
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2015 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServer.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Invoke;
|
||||
|
||||
class IEventQueue;
|
||||
|
||||
class MockIpcServer : public IpcServer
|
||||
{
|
||||
public:
|
||||
MockIpcServer() : m_sendCond(ARCH->newCondVar()), m_sendMutex(ARCH->newMutex())
|
||||
{
|
||||
}
|
||||
|
||||
~MockIpcServer()
|
||||
{
|
||||
if (m_sendCond != NULL) {
|
||||
ARCH->closeCondVar(m_sendCond);
|
||||
}
|
||||
|
||||
if (m_sendMutex != NULL) {
|
||||
ARCH->closeMutex(m_sendMutex);
|
||||
}
|
||||
}
|
||||
|
||||
MOCK_METHOD(void, listen, (), (override));
|
||||
MOCK_METHOD(void, send, (const IpcMessage &, IpcClientType), (override));
|
||||
MOCK_METHOD(bool, hasClients, (IpcClientType), (const, override));
|
||||
|
||||
void delegateToFake()
|
||||
{
|
||||
ON_CALL(*this, send(_, _)).WillByDefault(Invoke(this, &MockIpcServer::mockSend));
|
||||
}
|
||||
|
||||
void waitForSend()
|
||||
{
|
||||
ARCH->waitCondVar(m_sendCond, m_sendMutex, 5);
|
||||
}
|
||||
|
||||
private:
|
||||
void mockSend(const IpcMessage &, IpcClientType)
|
||||
{
|
||||
ArchMutexLock lock(m_sendMutex);
|
||||
ARCH->broadcastCondVar(m_sendCond);
|
||||
}
|
||||
|
||||
ArchCond m_sendCond;
|
||||
ArchMutex m_sendMutex;
|
||||
};
|
||||
@ -205,18 +205,6 @@ TEST_F(GenericArgsParsingTests, parseGenericArgs_versionCmd_showVersion)
|
||||
EXPECT_EQ(1, i);
|
||||
}
|
||||
|
||||
TEST_F(GenericArgsParsingTests, parseGenericArgs_ipcCmd_enableIpcTrue)
|
||||
{
|
||||
int i = 1;
|
||||
const int argc = 2;
|
||||
const char *kIpcCmd[argc] = {"stub", "--ipc"};
|
||||
|
||||
m_argParser->parseGenericArgs(argc, kIpcCmd, i);
|
||||
|
||||
EXPECT_EQ(true, argsBase.m_enableIpc);
|
||||
EXPECT_EQ(1, i);
|
||||
}
|
||||
|
||||
#ifndef WINAPI_XWINDOWS
|
||||
TEST_F(GenericArgsParsingTests, parseGenericArgs_dragDropCmdOnNonLinux_enableDragDropTrue)
|
||||
{
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
|
||||
#include "gui/config/IAppConfig.h"
|
||||
#include "gui/core/CoreProcess.h"
|
||||
#include "gui/ipc/IQIpcClient.h"
|
||||
#include "gui/proxy/QProcessProxy.h"
|
||||
#include "shared/gui/mocks/AppConfigMock.h"
|
||||
#include "shared/gui/mocks/ServerConfigMock.h"
|
||||
@ -45,41 +44,23 @@ public:
|
||||
MOCK_METHOD(QString, readAllStandardError, (), (override));
|
||||
};
|
||||
|
||||
class QIpcClientMock : public ipc::IQIpcClient
|
||||
{
|
||||
public:
|
||||
QIpcClientMock()
|
||||
{
|
||||
ON_CALL(*this, isConnected()).WillByDefault(Return(true));
|
||||
}
|
||||
|
||||
MOCK_METHOD(void, sendHello, (), (const, override));
|
||||
MOCK_METHOD(void, sendCommand, (const QString &command, ElevateMode elevate), (const, override));
|
||||
MOCK_METHOD(void, connectToHost, (), (override));
|
||||
MOCK_METHOD(void, disconnectFromHost, (), (override));
|
||||
MOCK_METHOD(bool, isConnected, (), (const, override));
|
||||
};
|
||||
|
||||
class DepsMock : public CoreProcess::Deps
|
||||
{
|
||||
public:
|
||||
DepsMock()
|
||||
{
|
||||
ON_CALL(*this, process()).WillByDefault(ReturnRef(m_process));
|
||||
ON_CALL(*this, ipcClient()).WillByDefault(ReturnRef(m_ipcClient));
|
||||
ON_CALL(*this, appPath(_)).WillByDefault(Return("stub app path"));
|
||||
ON_CALL(*this, fileExists(_)).WillByDefault(Return(true));
|
||||
ON_CALL(*this, getProfileRoot()).WillByDefault(Return("stub profile"));
|
||||
}
|
||||
|
||||
MOCK_METHOD(proxy::QProcessProxy &, process, (), (override));
|
||||
MOCK_METHOD(ipc::IQIpcClient &, ipcClient, (), (override));
|
||||
MOCK_METHOD(QString, appPath, (const QString &name), (const, override));
|
||||
MOCK_METHOD(bool, fileExists, (const QString &path), (const, override));
|
||||
MOCK_METHOD(QString, getProfileRoot, (), (const, override));
|
||||
|
||||
NiceMock<QProcessProxyMock> m_process;
|
||||
NiceMock<QIpcClientMock> m_ipcClient;
|
||||
};
|
||||
|
||||
class CoreProcessTests : public Test
|
||||
@ -111,15 +92,6 @@ TEST_F(CoreProcessTests, start_serverDesktop_callsProcessStart)
|
||||
m_coreProcess.start(ProcessMode::kDesktop);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, start_serverService_callsSendCommand)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Server);
|
||||
|
||||
EXPECT_CALL(m_pDeps->m_ipcClient, sendCommand(_, _)).Times(1);
|
||||
|
||||
m_coreProcess.start(ProcessMode::kService);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, start_clientDesktop_callsProcessStart)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
||||
@ -130,16 +102,6 @@ TEST_F(CoreProcessTests, start_clientDesktop_callsProcessStart)
|
||||
m_coreProcess.start(ProcessMode::kDesktop);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, start_clientService_callsSendCommand)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
||||
m_coreProcess.setAddress("stub address");
|
||||
|
||||
EXPECT_CALL(m_pDeps->m_ipcClient, sendCommand(_, _)).Times(1);
|
||||
|
||||
m_coreProcess.start(ProcessMode::kService);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, stop_serverDesktop_callsProcessClose)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Server);
|
||||
@ -150,16 +112,6 @@ TEST_F(CoreProcessTests, stop_serverDesktop_callsProcessClose)
|
||||
m_coreProcess.stop(ProcessMode::kDesktop);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, stop_serverService_callsSendCommand)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Server);
|
||||
m_coreProcess.start();
|
||||
|
||||
EXPECT_CALL(m_pDeps->m_ipcClient, sendCommand(_, _)).Times(1);
|
||||
|
||||
m_coreProcess.stop(ProcessMode::kService);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, stop_clientDesktop_callsProcessClose)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
||||
@ -171,17 +123,6 @@ TEST_F(CoreProcessTests, stop_clientDesktop_callsProcessClose)
|
||||
m_coreProcess.stop(ProcessMode::kDesktop);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, stop_clientService_callsSendCommand)
|
||||
{
|
||||
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
||||
m_coreProcess.setAddress("stub address");
|
||||
m_coreProcess.start();
|
||||
|
||||
EXPECT_CALL(m_pDeps->m_ipcClient, sendCommand(_, _)).Times(1);
|
||||
|
||||
m_coreProcess.stop(ProcessMode::kService);
|
||||
}
|
||||
|
||||
TEST_F(CoreProcessTests, restart_serverDesktop_callsProcessStart)
|
||||
{
|
||||
ON_CALL(m_appConfig, processMode()).WillByDefault(Return(ProcessMode::kDesktop));
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2024 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "gui/ipc/QIpcClient.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using testing::_;
|
||||
using testing::StrEq;
|
||||
|
||||
namespace {
|
||||
|
||||
class MockStream : public QDataStreamProxy
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD(qint64, writeRawData, (const char *, int), (override));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(QIpcClientTests, sendCommand_anyCommand_commandSent)
|
||||
{
|
||||
auto mockStream = std::make_shared<MockStream>();
|
||||
QIpcClient::StreamProvider streamProvider = [&mockStream]() { return mockStream; };
|
||||
|
||||
EXPECT_CALL(*mockStream, writeRawData(_, _)).Times(3);
|
||||
EXPECT_CALL(*mockStream, writeRawData(StrEq("test"), 4)).Times(1);
|
||||
|
||||
QIpcClient ipcClient(streamProvider);
|
||||
ipcClient.sendCommand("test", ElevateMode::kAutomatic);
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2015 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#define TEST_ENV
|
||||
|
||||
#include "test/mock/ipc/MockIpcServer.h"
|
||||
|
||||
#include "base/String.h"
|
||||
#include "common/common.h"
|
||||
#include "ipc/IpcLogOutputter.h"
|
||||
#include "mt/Thread.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// HACK: ipc logging only used on windows anyway
|
||||
#if WINAPI_MSWINDOWS
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Matcher;
|
||||
using ::testing::MatcherCast;
|
||||
using ::testing::Property;
|
||||
using ::testing::Return;
|
||||
using ::testing::StrEq;
|
||||
|
||||
using namespace deskflow;
|
||||
|
||||
// TODO Fix the IPC Tests for windows, see #6709
|
||||
// Tests disabled due to gtest/gmock update causing build problems
|
||||
// Decision to disable tests and create issue instead due to time constraints
|
||||
// inline const Matcher<const IpcMessage&> IpcLogLineMessageEq(const std::string& s)
|
||||
// {
|
||||
// const Matcher<const IpcLogLineMessage&> m(
|
||||
// Property(&IpcLogLineMessage::logLine, StrEq(s)));
|
||||
// return MatcherCast<const IpcMessage&>(m);
|
||||
// }
|
||||
//
|
||||
// TEST(IpcLogOutputterTests, write_threadingEnabled_bufferIsSent)
|
||||
//{
|
||||
// MockIpcServer mockServer;
|
||||
// mockServer.delegateToFake();
|
||||
//
|
||||
// ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true));
|
||||
//
|
||||
// EXPECT_CALL(mockServer, hasClients(_)).Times(AtLeast(3));
|
||||
// EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\n"),
|
||||
// _)).Times(1); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock
|
||||
// 2\n"), _)).Times(1);
|
||||
//
|
||||
// IpcLogOutputter outputter(mockServer, IpcClientType::Unknown, true);
|
||||
// outputter.write(kNOTE, "mock 1");
|
||||
// mockServer.waitForSend();
|
||||
// outputter.write(kNOTE, "mock 2");
|
||||
// mockServer.waitForSend();
|
||||
// }
|
||||
//
|
||||
// TEST(IpcLogOutputterTests, write_overBufferMaxSize_firstLineTruncated)
|
||||
//{
|
||||
// MockIpcServer mockServer;
|
||||
//
|
||||
// ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true));
|
||||
// EXPECT_CALL(mockServer, hasClients(_)).Times(1);
|
||||
// EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 2\nmock 3\n"),
|
||||
// _)).Times(1);
|
||||
//
|
||||
// IpcLogOutputter outputter(mockServer, IpcClientType::Unknown, false);
|
||||
// outputter.bufferMaxSize(2);
|
||||
//
|
||||
// // log more lines than the buffer can contain
|
||||
// outputter.write(kNOTE, "mock 1");
|
||||
// outputter.write(kNOTE, "mock 2");
|
||||
// outputter.write(kNOTE, "mock 3");
|
||||
// outputter.sendBuffer();
|
||||
// }
|
||||
//
|
||||
// TEST(IpcLogOutputterTests, write_underBufferMaxSize_allLinesAreSent)
|
||||
//{
|
||||
// MockIpcServer mockServer;
|
||||
//
|
||||
// ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true));
|
||||
//
|
||||
// EXPECT_CALL(mockServer, hasClients(_)).Times(1);
|
||||
// EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\nmock 2\n"),
|
||||
// _)).Times(1);
|
||||
//
|
||||
// IpcLogOutputter outputter(mockServer, IpcClientType::Unknown, false);
|
||||
// outputter.bufferMaxSize(2);
|
||||
//
|
||||
// // log more lines than the buffer can contain
|
||||
// outputter.write(kNOTE, "mock 1");
|
||||
// outputter.write(kNOTE, "mock 2");
|
||||
// outputter.sendBuffer();
|
||||
// }
|
||||
//
|
||||
//// HACK: temporarily disable this intermittently failing unit test.
|
||||
//// when the build machine is under heavy load, a race condition
|
||||
//// usually happens.
|
||||
// #if 0
|
||||
// TEST(IpcLogOutputterTests, write_overBufferRateLimit_lastLineTruncated)
|
||||
//{
|
||||
// MockIpcServer mockServer;
|
||||
//
|
||||
// ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true));
|
||||
//
|
||||
// EXPECT_CALL(mockServer, hasClients(_)).Times(2);
|
||||
// EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\nmock 2\n"),
|
||||
// _)).Times(1); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock
|
||||
// 4\nmock 5\n"), _)).Times(1);
|
||||
//
|
||||
// IpcLogOutputter outputter(mockServer, false);
|
||||
// outputter.bufferRateLimit(2, 1); // 1s
|
||||
//
|
||||
// // log 1 more line than the buffer can accept in time limit.
|
||||
// outputter.write(kNOTE, "mock 1");
|
||||
// outputter.write(kNOTE, "mock 2");
|
||||
// outputter.write(kNOTE, "mock 3");
|
||||
//
|
||||
// outputter.sendBuffer();
|
||||
//
|
||||
// // after waiting the time limit send another to make sure
|
||||
// // we can log after the time limit passes.
|
||||
// // HACK: sleep causes the unit test to fail intermittently,
|
||||
// // so lets try 100ms (there must be a better way to solve this)
|
||||
// ARCH->sleep(2); // 2s
|
||||
// outputter.write(kNOTE, "mock 4");
|
||||
// outputter.write(kNOTE, "mock 5");
|
||||
// outputter.write(kNOTE, "mock 6");
|
||||
//
|
||||
// outputter.sendBuffer();
|
||||
// }
|
||||
// #endif
|
||||
//
|
||||
// TEST(IpcLogOutputterTests, write_underBufferRateLimit_allLinesAreSent)
|
||||
//{
|
||||
// MockIpcServer mockServer;
|
||||
//
|
||||
// ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true));
|
||||
//
|
||||
// EXPECT_CALL(mockServer, hasClients(_)).Times(2);
|
||||
// EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\nmock 2\n"),
|
||||
// _)).Times(1); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock
|
||||
// 3\nmock 4\n"), _)).Times(1);
|
||||
//
|
||||
// IpcLogOutputter outputter(mockServer, IpcClientType::Unknown, false);
|
||||
// outputter.bufferRateLimit(4, 1); // 1s (should be plenty of time)
|
||||
//
|
||||
// // log 1 more line than the buffer can accept in time limit.
|
||||
// outputter.write(kNOTE, "mock 1");
|
||||
// outputter.write(kNOTE, "mock 2");
|
||||
// outputter.sendBuffer();
|
||||
//
|
||||
// // after waiting the time limit send another to make sure
|
||||
// // we can log after the time limit passes.
|
||||
// outputter.write(kNOTE, "mock 3");
|
||||
// outputter.write(kNOTE, "mock 4");
|
||||
// outputter.sendBuffer();
|
||||
// }
|
||||
|
||||
#endif // WINAPI_MSWINDOWS
|
||||
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2015 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#define TEST_ENV
|
||||
|
||||
#include "ipc/IpcSettingMessage.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(IpcSettingMessage, testIpcSettingMessage)
|
||||
{
|
||||
const std::string expected_name = "test";
|
||||
const std::string expected_value = "test_value";
|
||||
|
||||
IpcSettingMessage message("test", "test_value");
|
||||
|
||||
EXPECT_EQ(expected_name, message.getName());
|
||||
EXPECT_EQ(expected_value, message.getValue());
|
||||
}
|
||||
Reference in New Issue
Block a user