refactor: Remove old Windows TCP IPC implementation (replaced by Qt equivalent)
This commit is contained in:
parent
a3b0ec28fc
commit
5a7f6bd1c0
62 changed files with 19 additions and 2685 deletions
|
|
@ -32,7 +32,6 @@ target_link_libraries(
|
||||||
io
|
io
|
||||||
mt
|
mt
|
||||||
net
|
net
|
||||||
ipc
|
|
||||||
platform
|
platform
|
||||||
server
|
server
|
||||||
app
|
app
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ target_link_libraries(
|
||||||
io
|
io
|
||||||
mt
|
mt
|
||||||
net
|
net
|
||||||
ipc
|
|
||||||
platform
|
platform
|
||||||
server
|
server
|
||||||
app
|
app
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ if(WIN32)
|
||||||
arch
|
arch
|
||||||
base
|
base
|
||||||
io
|
io
|
||||||
ipc
|
|
||||||
mt
|
mt
|
||||||
net
|
net
|
||||||
platform
|
platform
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
#include "ServerConfig.h"
|
#include "ServerConfig.h"
|
||||||
#include "VersionChecker.h"
|
#include "VersionChecker.h"
|
||||||
#include "common/ipc.h"
|
|
||||||
#include "gui/config/AppConfig.h"
|
#include "gui/config/AppConfig.h"
|
||||||
#include "gui/config/ConfigScopes.h"
|
#include "gui/config/ConfigScopes.h"
|
||||||
#include "gui/config/ServerConfigDialogState.h"
|
#include "gui/config/ServerConfigDialogState.h"
|
||||||
|
|
@ -146,7 +145,6 @@ private:
|
||||||
void setIcon();
|
void setIcon();
|
||||||
bool checkForApp(int which, QString &app);
|
bool checkForApp(int which, QString &app);
|
||||||
void setStatus(const QString &status);
|
void setStatus(const QString &status);
|
||||||
void sendIpcMessage(IpcMessageType type, const char *buffer, bool showErrors);
|
|
||||||
void updateFromLogLine(const QString &line);
|
void updateFromLogLine(const QString &line);
|
||||||
QString getIPAddresses() const;
|
QString getIPAddresses() const;
|
||||||
void enableServer(bool enable);
|
void enableServer(bool enable);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ target_link_libraries(
|
||||||
io
|
io
|
||||||
mt
|
mt
|
||||||
net
|
net
|
||||||
ipc
|
|
||||||
platform
|
platform
|
||||||
server
|
server
|
||||||
app
|
app
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ add_subdirectory(client)
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
add_subdirectory(deskflow)
|
add_subdirectory(deskflow)
|
||||||
add_subdirectory(io)
|
add_subdirectory(io)
|
||||||
add_subdirectory(ipc)
|
|
||||||
add_subdirectory(mt)
|
add_subdirectory(mt)
|
||||||
add_subdirectory(net)
|
add_subdirectory(net)
|
||||||
add_subdirectory(platform)
|
add_subdirectory(platform)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
#include "base/EventQueue.h"
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Event
|
// Event
|
||||||
|
|
|
||||||
|
|
@ -8,21 +8,17 @@
|
||||||
#include "base/EventQueue.h"
|
#include "base/EventQueue.h"
|
||||||
|
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
#include "base/EventTypes.h"
|
|
||||||
#include "base/IEventJob.h"
|
#include "base/IEventJob.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/SimpleEventQueueBuffer.h"
|
#include "base/SimpleEventQueueBuffer.h"
|
||||||
#include "base/Stopwatch.h"
|
#include "base/Stopwatch.h"
|
||||||
#include "base/XBase.h"
|
|
||||||
#include "mt/Lock.h"
|
#include "mt/Lock.h"
|
||||||
#include "mt/Mutex.h"
|
#include "mt/Mutex.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
EVENT_TYPE_ACCESSOR(Client)
|
EVENT_TYPE_ACCESSOR(Client)
|
||||||
EVENT_TYPE_ACCESSOR(IStream)
|
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(IDataSocket)
|
||||||
EVENT_TYPE_ACCESSOR(IListenSocket)
|
EVENT_TYPE_ACCESSOR(IListenSocket)
|
||||||
EVENT_TYPE_ACCESSOR(ISocket)
|
EVENT_TYPE_ACCESSOR(ISocket)
|
||||||
|
|
@ -55,10 +51,6 @@ EventQueue::EventQueue()
|
||||||
m_nextType(Event::kLast),
|
m_nextType(Event::kLast),
|
||||||
m_typesForClient(NULL),
|
m_typesForClient(NULL),
|
||||||
m_typesForIStream(NULL),
|
m_typesForIStream(NULL),
|
||||||
m_typesForIpcClient(NULL),
|
|
||||||
m_typesForIpcClientProxy(NULL),
|
|
||||||
m_typesForIpcServer(NULL),
|
|
||||||
m_typesForIpcServerProxy(NULL),
|
|
||||||
m_typesForIDataSocket(NULL),
|
m_typesForIDataSocket(NULL),
|
||||||
m_typesForIListenSocket(NULL),
|
m_typesForIListenSocket(NULL),
|
||||||
m_typesForISocket(NULL),
|
m_typesForISocket(NULL),
|
||||||
|
|
|
||||||
|
|
@ -130,10 +130,6 @@ public:
|
||||||
//
|
//
|
||||||
ClientEvents &forClient();
|
ClientEvents &forClient();
|
||||||
IStreamEvents &forIStream();
|
IStreamEvents &forIStream();
|
||||||
IpcClientEvents &forIpcClient();
|
|
||||||
IpcClientProxyEvents &forIpcClientProxy();
|
|
||||||
IpcServerEvents &forIpcServer();
|
|
||||||
IpcServerProxyEvents &forIpcServerProxy();
|
|
||||||
IDataSocketEvents &forIDataSocket();
|
IDataSocketEvents &forIDataSocket();
|
||||||
IListenSocketEvents &forIListenSocket();
|
IListenSocketEvents &forIListenSocket();
|
||||||
ISocketEvents &forISocket();
|
ISocketEvents &forISocket();
|
||||||
|
|
@ -153,10 +149,6 @@ public:
|
||||||
private:
|
private:
|
||||||
ClientEvents *m_typesForClient;
|
ClientEvents *m_typesForClient;
|
||||||
IStreamEvents *m_typesForIStream;
|
IStreamEvents *m_typesForIStream;
|
||||||
IpcClientEvents *m_typesForIpcClient;
|
|
||||||
IpcClientProxyEvents *m_typesForIpcClientProxy;
|
|
||||||
IpcServerEvents *m_typesForIpcServer;
|
|
||||||
IpcServerProxyEvents *m_typesForIpcServerProxy;
|
|
||||||
IDataSocketEvents *m_typesForIDataSocket;
|
IDataSocketEvents *m_typesForIDataSocket;
|
||||||
IListenSocketEvents *m_typesForIListenSocket;
|
IListenSocketEvents *m_typesForIListenSocket;
|
||||||
ISocketEvents *m_typesForISocket;
|
ISocketEvents *m_typesForISocket;
|
||||||
|
|
|
||||||
|
|
@ -45,26 +45,6 @@ REGISTER_EVENT(IStream, inputShutdown)
|
||||||
REGISTER_EVENT(IStream, outputShutdown)
|
REGISTER_EVENT(IStream, outputShutdown)
|
||||||
REGISTER_EVENT(IStream, inputFormatError)
|
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
|
// IDataSocket
|
||||||
//
|
//
|
||||||
|
|
@ -167,13 +147,6 @@ REGISTER_EVENT(IScreen, shapeChanged)
|
||||||
REGISTER_EVENT(IScreen, suspend)
|
REGISTER_EVENT(IScreen, suspend)
|
||||||
REGISTER_EVENT(IScreen, resume)
|
REGISTER_EVENT(IScreen, resume)
|
||||||
|
|
||||||
//
|
|
||||||
// IpcServer
|
|
||||||
//
|
|
||||||
|
|
||||||
REGISTER_EVENT(IpcServer, clientConnected)
|
|
||||||
REGISTER_EVENT(IpcServer, messageReceived)
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clipboard
|
// Clipboard
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -145,94 +145,6 @@ private:
|
||||||
Event::Type m_inputFormatError;
|
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
|
class IDataSocketEvents : public EventTypes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,6 @@ class EventQueueTimer;
|
||||||
// Event type registration classes.
|
// Event type registration classes.
|
||||||
class ClientEvents;
|
class ClientEvents;
|
||||||
class IStreamEvents;
|
class IStreamEvents;
|
||||||
class IpcClientEvents;
|
|
||||||
class IpcClientProxyEvents;
|
|
||||||
class IpcServerEvents;
|
|
||||||
class IpcServerProxyEvents;
|
|
||||||
class IDataSocketEvents;
|
class IDataSocketEvents;
|
||||||
class IListenSocketEvents;
|
class IListenSocketEvents;
|
||||||
class ISocketEvents;
|
class ISocketEvents;
|
||||||
|
|
@ -216,10 +212,6 @@ public:
|
||||||
|
|
||||||
virtual ClientEvents &forClient() = 0;
|
virtual ClientEvents &forClient() = 0;
|
||||||
virtual IStreamEvents &forIStream() = 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 IDataSocketEvents &forIDataSocket() = 0;
|
||||||
virtual IListenSocketEvents &forIListenSocket() = 0;
|
virtual IListenSocketEvents &forIListenSocket() = 0;
|
||||||
virtual ISocketEvents &forISocket() = 0;
|
virtual ISocketEvents &forISocket() = 0;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ configure_file(constants.h.in constants.h @ONLY)
|
||||||
add_library(common INTERFACE
|
add_library(common INTERFACE
|
||||||
common.h
|
common.h
|
||||||
IInterface.h
|
IInterface.h
|
||||||
ipc.h
|
|
||||||
stdbitset.h
|
stdbitset.h
|
||||||
stddeque.h
|
stddeque.h
|
||||||
stdexcept.h
|
stdexcept.h
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ enum
|
||||||
#if WINAPI_MSWINDOWS
|
#if WINAPI_MSWINDOWS
|
||||||
namespace deskflow::common {
|
namespace deskflow::common {
|
||||||
|
|
||||||
const auto kCloseEventName = "Global\\DeskflowCloseEvent";
|
const auto kCloseEventName = "Global\\DeskflowClose";
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
* 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-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -9,36 +9,23 @@
|
||||||
|
|
||||||
#include "DisplayInvalidException.h"
|
#include "DisplayInvalidException.h"
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
#include "arch/XArch.h"
|
|
||||||
#include "base/EventQueue.h"
|
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/TMethodEventJob.h"
|
|
||||||
#include "base/XBase.h"
|
|
||||||
#include "base/log_outputters.h"
|
#include "base/log_outputters.h"
|
||||||
#include "common/constants.h"
|
#include "common/constants.h"
|
||||||
#include "common/ipc.h"
|
|
||||||
#include "deskflow/ArgsBase.h"
|
#include "deskflow/ArgsBase.h"
|
||||||
#include "deskflow/Config.h"
|
#include "deskflow/Config.h"
|
||||||
#include "deskflow/XDeskflow.h"
|
#include "deskflow/XDeskflow.h"
|
||||||
#include "deskflow/protocol_types.h"
|
#include "deskflow/protocol_types.h"
|
||||||
#include "ipc/IpcMessage.h"
|
|
||||||
#include "ipc/IpcServerProxy.h"
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
#include "arch/win32/ArchMiscWindows.h"
|
|
||||||
#include "base/IEventQueue.h"
|
#include "base/IEventQueue.h"
|
||||||
#include "base/TMethodJob.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WINAPI_CARBON
|
#if WINAPI_CARBON
|
||||||
#include "platform/OSXDragSimulator.h"
|
#include "platform/OSXDragSimulator.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <charconv>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -64,7 +51,6 @@ App::App(IEventQueue *events, deskflow::ArgsBase *args)
|
||||||
m_args(args),
|
m_args(args),
|
||||||
m_fileLog(nullptr),
|
m_fileLog(nullptr),
|
||||||
m_appUtil(events),
|
m_appUtil(events),
|
||||||
m_ipcClient(nullptr),
|
|
||||||
m_socketMultiplexer(nullptr)
|
m_socketMultiplexer(nullptr)
|
||||||
{
|
{
|
||||||
assert(s_instance == nullptr);
|
assert(s_instance == nullptr);
|
||||||
|
|
@ -208,32 +194,6 @@ void App::initApp(int argc, const char **argv)
|
||||||
loadConfig();
|
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 *)
|
void App::runEventsLoop(void *)
|
||||||
{
|
{
|
||||||
m_events->loop();
|
m_events->loop();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* 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-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
#include "deskflow/IApp.h"
|
#include "deskflow/IApp.h"
|
||||||
#include "ipc/IpcClient.h"
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
#include "deskflow/win32/AppUtilWindows.h"
|
#include "deskflow/win32/AppUtilWindows.h"
|
||||||
|
|
@ -20,7 +19,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace deskflow {
|
namespace deskflow {
|
||||||
class Screen;
|
class Screen;
|
||||||
|
|
@ -110,12 +108,7 @@ public:
|
||||||
|
|
||||||
void (*m_bye)(int);
|
void (*m_bye)(int);
|
||||||
|
|
||||||
private:
|
|
||||||
void handleIpcMessage(const Event &, void *);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void initIpcClient();
|
|
||||||
void cleanupIpcClient();
|
|
||||||
void runEventsLoop(void *);
|
void runEventsLoop(void *);
|
||||||
|
|
||||||
bool m_suspended;
|
bool m_suspended;
|
||||||
|
|
@ -126,7 +119,6 @@ private:
|
||||||
static App *s_instance;
|
static App *s_instance;
|
||||||
FileLogOutputter *m_fileLog;
|
FileLogOutputter *m_fileLog;
|
||||||
ARCH_APP_UTIL m_appUtil;
|
ARCH_APP_UTIL m_appUtil;
|
||||||
IpcClient *m_ipcClient;
|
|
||||||
SocketMultiplexer *m_socketMultiplexer;
|
SocketMultiplexer *m_socketMultiplexer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -188,8 +188,6 @@ bool ArgParser::parseGenericArgs(int argc, const char *const *argv, int &i)
|
||||||
m_app->version();
|
m_app->version();
|
||||||
}
|
}
|
||||||
argsBase().m_shouldExitOk = true;
|
argsBase().m_shouldExitOk = true;
|
||||||
} else if (isArg(i, argc, argv, nullptr, "--ipc")) {
|
|
||||||
argsBase().m_enableIpc = true;
|
|
||||||
} else if (isArg(i, argc, argv, nullptr, "--server")) {
|
} else if (isArg(i, argc, argv, nullptr, "--server")) {
|
||||||
// HACK: stop error happening when using portable (deskflowp)
|
// HACK: stop error happening when using portable (deskflowp)
|
||||||
} else if (isArg(i, argc, argv, nullptr, "--client")) {
|
} else if (isArg(i, argc, argv, nullptr, "--client")) {
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ public:
|
||||||
/// @brief The name of the current computer
|
/// @brief The name of the current computer
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
/// @brief Tell the client to talk through IPC to the daemon
|
/// @brief Should the app add a tray icon
|
||||||
bool m_enableIpc = false;
|
bool m_disableTray = false;
|
||||||
|
|
||||||
/// @brief Should drag drop support be enabled
|
/// @brief Should drag drop support be enabled
|
||||||
bool m_enableDragDrop = false;
|
bool m_enableDragDrop = false;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
|
# 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-FileCopyrightText: 2009 - 2012 Nick Bolton
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
@ -170,7 +170,6 @@ if(UNIX)
|
||||||
PRIVATE
|
PRIVATE
|
||||||
arch
|
arch
|
||||||
client
|
client
|
||||||
ipc
|
|
||||||
net
|
net
|
||||||
base
|
base
|
||||||
platform
|
platform
|
||||||
|
|
|
||||||
|
|
@ -454,12 +454,6 @@ int ClientApp::mainLoop()
|
||||||
// start client, etc
|
// start client, etc
|
||||||
appUtil().startNode();
|
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
|
// run event loop. if startClient() failed we're supposed to retry
|
||||||
// later. the timer installed by startClient() will take care of
|
// later. the timer installed by startClient() will take care of
|
||||||
// that.
|
// that.
|
||||||
|
|
@ -486,10 +480,6 @@ int ClientApp::mainLoop()
|
||||||
updateStatus();
|
updateStatus();
|
||||||
LOG((CLOG_NOTE "stopped client"));
|
LOG((CLOG_NOTE "stopped client"));
|
||||||
|
|
||||||
if (argsBase().m_enableIpc) {
|
|
||||||
cleanupIpcClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,13 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* 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 "deskflow/DaemonApp.h"
|
||||||
|
|
||||||
#include "arch/XArch.h"
|
#include "arch/XArch.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/TMethodEventJob.h"
|
|
||||||
#include "base/log_outputters.h"
|
#include "base/log_outputters.h"
|
||||||
#include "common/constants.h"
|
#include "common/constants.h"
|
||||||
#include "common/ipc.h"
|
|
||||||
#include "deskflow/App.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
|
#if SYSAPI_WIN32
|
||||||
|
|
||||||
|
|
@ -50,16 +37,6 @@ using namespace deskflow::core;
|
||||||
const char *const kLogFilename = "deskflow-daemon.log";
|
const char *const kLogFilename = "deskflow-daemon.log";
|
||||||
|
|
||||||
namespace {
|
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)
|
bool isServerCommandLine(const std::vector<std::string> &cmd)
|
||||||
{
|
{
|
||||||
auto isServer = false;
|
auto isServer = false;
|
||||||
|
|
@ -76,7 +53,7 @@ bool isServerCommandLine(const std::vector<std::string> &cmd)
|
||||||
|
|
||||||
int mainLoopStatic()
|
int mainLoopStatic()
|
||||||
{
|
{
|
||||||
DaemonApp::instance().mainLoop(true);
|
DaemonApp::instance().mainLoop();
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,7 +85,7 @@ void DaemonApp::run()
|
||||||
|
|
||||||
// run process in foreground instead of daemonizing.
|
// run process in foreground instead of daemonizing.
|
||||||
// useful for debugging.
|
// useful for debugging.
|
||||||
mainLoop(false, m_foreground);
|
mainLoop(m_foreground);
|
||||||
} else {
|
} else {
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
LOG((CLOG_NOTE "daemonizing windows service"));
|
LOG((CLOG_NOTE "daemonizing windows service"));
|
||||||
|
|
@ -260,7 +237,7 @@ DaemonApp::InitResult DaemonApp::init(IEventQueue *events, int argc, char **argv
|
||||||
return FatalError;
|
return FatalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
void DaemonApp::mainLoop(bool foreground)
|
||||||
{
|
{
|
||||||
if (m_events == nullptr) {
|
if (m_events == nullptr) {
|
||||||
throw XDeskflow("event queue not set");
|
throw XDeskflow("event queue not set");
|
||||||
|
|
@ -269,17 +246,12 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||||
try {
|
try {
|
||||||
DAEMON_RUNNING(true);
|
DAEMON_RUNNING(true);
|
||||||
|
|
||||||
if (logToFile) {
|
m_fileLogOutputter = new FileLogOutputter(logFilename().c_str()); // NOSONAR - Adopted by `Log`
|
||||||
m_fileLogOutputter = new FileLogOutputter(logFilename().c_str()); // NOSONAR -- Adopted by `Log`
|
CLOG->insert(m_fileLogOutputter);
|
||||||
CLOG->insert(m_fileLogOutputter);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
m_watchdog = std::make_unique<MSWindowsWatchdog>(false, foreground);
|
m_watchdog = std::make_unique<MSWindowsWatchdog>(false, foreground);
|
||||||
m_watchdog->setFileLogOutputter(m_fileLogOutputter);
|
m_watchdog->setFileLogOutputter(m_fileLogOutputter);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
|
||||||
|
|
||||||
// install the platform event queue to handle service stop events.
|
// install the platform event queue to handle service stop events.
|
||||||
m_events->adoptBuffer(new MSWindowsEventQueueBuffer(m_events));
|
m_events->adoptBuffer(new MSWindowsEventQueueBuffer(m_events));
|
||||||
|
|
@ -293,14 +265,13 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||||
|
|
||||||
m_watchdog->startAsync();
|
m_watchdog->startAsync();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_events->loop();
|
m_events->loop();
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
m_watchdog->stop();
|
m_watchdog->stop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CLOG->remove(m_ipcLogOutputter.get());
|
|
||||||
|
|
||||||
DAEMON_RUNNING(false);
|
DAEMON_RUNNING(false);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
LOG((CLOG_CRIT "an error occurred: %s", e.what()));
|
LOG((CLOG_CRIT "an error occurred: %s", e.what()));
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,8 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "common/common.h"
|
|
||||||
|
|
||||||
class Event;
|
class Event;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
class IpcLogOutputter;
|
|
||||||
class FileLogOutputter;
|
class FileLogOutputter;
|
||||||
class QLocalServer;
|
class QLocalServer;
|
||||||
class QCoreApplication;
|
class QCoreApplication;
|
||||||
|
|
@ -49,15 +46,14 @@ public:
|
||||||
|
|
||||||
InitResult init(IEventQueue *events, int argc, char **argv);
|
InitResult init(IEventQueue *events, int argc, char **argv);
|
||||||
void run();
|
void run();
|
||||||
void mainLoop(bool logToFile, bool foreground = false);
|
|
||||||
void restartCoreProcess();
|
void restartCoreProcess();
|
||||||
void saveLogLevel(const QString &logLevel) const;
|
void saveLogLevel(const QString &logLevel) const;
|
||||||
|
void mainLoop(bool foreground = false);
|
||||||
|
void setLogLevel(const QString &logLevel);
|
||||||
void setElevate(bool elevate);
|
void setElevate(bool elevate);
|
||||||
void setCommand(const QString &command);
|
void setCommand(const QString &command);
|
||||||
void applyWatchdogCommand() const;
|
void applyWatchdogCommand() const;
|
||||||
void clearWatchdogCommand();
|
void clearWatchdogCommand();
|
||||||
|
|
||||||
// Getters
|
|
||||||
std::string logFilename();
|
std::string logFilename();
|
||||||
|
|
||||||
static DaemonApp &instance()
|
static DaemonApp &instance()
|
||||||
|
|
@ -79,7 +75,6 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<IpcLogOutputter> m_ipcLogOutputter;
|
|
||||||
IEventQueue *m_events = nullptr;
|
IEventQueue *m_events = nullptr;
|
||||||
FileLogOutputter *m_fileLogOutputter = nullptr;
|
FileLogOutputter *m_fileLogOutputter = nullptr;
|
||||||
deskflow::core::ipc::DaemonIpcServer *m_ipcServer = nullptr;
|
deskflow::core::ipc::DaemonIpcServer *m_ipcServer = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -706,12 +706,6 @@ int ServerApp::mainLoop()
|
||||||
// start server, etc
|
// start server, etc
|
||||||
appUtil().startNode();
|
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
|
// handle hangup signal by reloading the server's configuration
|
||||||
ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL);
|
ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL);
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
|
|
@ -761,10 +755,6 @@ int ServerApp::mainLoop()
|
||||||
updateStatus();
|
updateStatus();
|
||||||
LOG((CLOG_NOTE "stopped server"));
|
LOG((CLOG_NOTE "stopped server"));
|
||||||
|
|
||||||
if (argsBase().m_enableIpc) {
|
|
||||||
cleanupIpcClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,6 @@ add_library(${target} STATIC
|
||||||
core/ServerMessage.h
|
core/ServerMessage.h
|
||||||
core/WaylandWarnings.cpp
|
core/WaylandWarnings.cpp
|
||||||
core/WaylandWarnings.h
|
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.cpp
|
||||||
ipc/DaemonIpcClient.h
|
ipc/DaemonIpcClient.h
|
||||||
proxy/QNetworkAccessManagerProxy.cpp
|
proxy/QNetworkAccessManagerProxy.cpp
|
||||||
|
|
|
||||||
|
|
@ -158,18 +158,6 @@ CoreProcess::CoreProcess(const IAppConfig &appConfig, const IServerConfig &serve
|
||||||
m_pDeps(deps),
|
m_pDeps(deps),
|
||||||
m_daemonIpcClient{new ipc::DaemonIpcClient(this)}
|
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_daemonIpcClient, &ipc::DaemonIpcClient::connected, this, &CoreProcess::daemonIpcClientConnected);
|
||||||
|
|
||||||
connect(&m_pDeps->process(), &QProcessProxy::finished, this, &CoreProcess::onProcessFinished);
|
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()
|
void CoreProcess::onProcessReadyReadStandardOutput()
|
||||||
{
|
{
|
||||||
if (m_pDeps->process()) {
|
if (m_pDeps->process()) {
|
||||||
|
|
@ -314,10 +278,6 @@ void CoreProcess::startProcessFromDaemon(const QString &app, const QStringList &
|
||||||
qFatal("core process must be in starting state");
|
qFatal("core process must be in starting state");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_daemonIpcClient->isConnected()) {
|
|
||||||
m_daemonIpcClient->connectToServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString commandQuoted = makeQuotedArgs(app, args);
|
QString commandQuoted = makeQuotedArgs(app, args);
|
||||||
|
|
||||||
qInfo("running command: %s", qPrintable(commandQuoted));
|
qInfo("running command: %s", qPrintable(commandQuoted));
|
||||||
|
|
@ -506,8 +466,6 @@ void CoreProcess::cleanup()
|
||||||
if (isDesktop && isRunning) {
|
if (isDesktop && isRunning) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pDeps->ipcClient().disconnectFromHost();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoreProcess::addGenericArgs(QStringList &args, const ProcessMode processMode) const
|
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();
|
args << "--name" << m_appConfig.screenName();
|
||||||
|
|
||||||
if (processMode != ProcessMode::kDesktop) {
|
if (processMode != ProcessMode::kDesktop) {
|
||||||
// tell client/server to talk to daemon through ipc.
|
|
||||||
args << "--ipc";
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
// tell the client/server to shut down when a ms windows desk
|
// tell the client/server to shut down when a ms windows desk
|
||||||
// is switched; this is because we may need to elevate or not
|
// is switched; this is because we may need to elevate or not
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#include "gui/FileTail.h"
|
#include "gui/FileTail.h"
|
||||||
#include "gui/config/IAppConfig.h"
|
#include "gui/config/IAppConfig.h"
|
||||||
#include "gui/config/IServerConfig.h"
|
#include "gui/config/IServerConfig.h"
|
||||||
#include "gui/ipc/QIpcClient.h"
|
|
||||||
#include "gui/proxy/QProcessProxy.h"
|
#include "gui/proxy/QProcessProxy.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -31,7 +30,6 @@ class CoreProcess : public QObject
|
||||||
{
|
{
|
||||||
using IServerConfig = deskflow::gui::IServerConfig;
|
using IServerConfig = deskflow::gui::IServerConfig;
|
||||||
using QProcessProxy = deskflow::gui::proxy::QProcessProxy;
|
using QProcessProxy = deskflow::gui::proxy::QProcessProxy;
|
||||||
using IQIpcClient = deskflow::gui::ipc::IQIpcClient;
|
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
@ -43,17 +41,12 @@ public:
|
||||||
{
|
{
|
||||||
return m_process;
|
return m_process;
|
||||||
}
|
}
|
||||||
virtual IQIpcClient &ipcClient()
|
|
||||||
{
|
|
||||||
return m_ipcClient;
|
|
||||||
}
|
|
||||||
virtual QString appPath(const QString &name) const;
|
virtual QString appPath(const QString &name) const;
|
||||||
virtual bool fileExists(const QString &path) const;
|
virtual bool fileExists(const QString &path) const;
|
||||||
virtual QString getProfileRoot() const;
|
virtual QString getProfileRoot() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QProcessProxy m_process;
|
QProcessProxy m_process;
|
||||||
QIpcClient m_ipcClient;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Mode
|
enum class Mode
|
||||||
|
|
@ -136,9 +129,6 @@ signals:
|
||||||
void secureSocket(bool enabled);
|
void secureSocket(bool enabled);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onIpcClientServiceReady();
|
|
||||||
void onIpcClientRead(const QString &text);
|
|
||||||
void onIpcClientError(const QString &text) const;
|
|
||||||
void onProcessFinished(int exitCode, QProcess::ExitStatus);
|
void onProcessFinished(int exitCode, QProcess::ExitStatus);
|
||||||
void onProcessReadyReadStandardOutput();
|
void onProcessReadyReadStandardOutput();
|
||||||
void onProcessReadyReadStandardError();
|
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
|
platform
|
||||||
io
|
io
|
||||||
net
|
net
|
||||||
ipc
|
|
||||||
app
|
app
|
||||||
client
|
client
|
||||||
${libs})
|
${libs})
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
#include "arch/win32/XArchWindows.h"
|
#include "arch/win32/XArchWindows.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "ipc/IpcMessage.h"
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2009 Chris Schoeneman
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -13,12 +12,8 @@
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/TMethodJob.h"
|
#include "base/TMethodJob.h"
|
||||||
#include "base/log_outputters.h"
|
#include "base/log_outputters.h"
|
||||||
#include "common/ipc.h"
|
|
||||||
#include "deskflow/App.h"
|
#include "deskflow/App.h"
|
||||||
#include "deskflow/ArgsBase.h"
|
#include "deskflow/ArgsBase.h"
|
||||||
#include "ipc/IpcLogOutputter.h"
|
|
||||||
#include "ipc/IpcMessage.h"
|
|
||||||
#include "ipc/IpcServer.h"
|
|
||||||
#include "mt/Thread.h"
|
#include "mt/Thread.h"
|
||||||
|
|
||||||
#include <Shellapi.h>
|
#include <Shellapi.h>
|
||||||
|
|
@ -437,7 +432,7 @@ void MSWindowsWatchdog::outputLoop(void *)
|
||||||
// process output to the VS debug output window.
|
// process output to the VS debug output window.
|
||||||
// we could use the MSWindowsDebugOutputter, but it's really fiddly to
|
// we could use the MSWindowsDebugOutputter, but it's really fiddly to
|
||||||
// so, and there doesn't seem to be an advantage of doing that.
|
// so, and there doesn't seem to be an advantage of doing that.
|
||||||
OutputDebugString(output.c_str());
|
OutputDebugString(buffer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2009 Chris Schoeneman
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -19,8 +18,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
class IpcLogOutputter;
|
|
||||||
class IpcServer;
|
|
||||||
class FileLogOutputter;
|
class FileLogOutputter;
|
||||||
|
|
||||||
class MSWindowsWatchdog
|
class MSWindowsWatchdog
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,6 @@ macro(config_test_deps)
|
||||||
server
|
server
|
||||||
app
|
app
|
||||||
mt
|
mt
|
||||||
ipc
|
|
||||||
gui
|
gui
|
||||||
GTest::gtest
|
GTest::gtest
|
||||||
GTest::gmock
|
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(void *, getSystemTarget, (), (override));
|
||||||
MOCK_METHOD(ClientEvents &, forClient, (), (override));
|
MOCK_METHOD(ClientEvents &, forClient, (), (override));
|
||||||
MOCK_METHOD(IStreamEvents &, forIStream, (), (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(IDataSocketEvents &, forIDataSocket, (), (override));
|
||||||
MOCK_METHOD(IListenSocketEvents &, forIListenSocket, (), (override));
|
MOCK_METHOD(IListenSocketEvents &, forIListenSocket, (), (override));
|
||||||
MOCK_METHOD(ISocketEvents &, forISocket, (), (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);
|
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
|
#ifndef WINAPI_XWINDOWS
|
||||||
TEST_F(GenericArgsParsingTests, parseGenericArgs_dragDropCmdOnNonLinux_enableDragDropTrue)
|
TEST_F(GenericArgsParsingTests, parseGenericArgs_dragDropCmdOnNonLinux_enableDragDropTrue)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "gui/config/IAppConfig.h"
|
#include "gui/config/IAppConfig.h"
|
||||||
#include "gui/core/CoreProcess.h"
|
#include "gui/core/CoreProcess.h"
|
||||||
#include "gui/ipc/IQIpcClient.h"
|
|
||||||
#include "gui/proxy/QProcessProxy.h"
|
#include "gui/proxy/QProcessProxy.h"
|
||||||
#include "shared/gui/mocks/AppConfigMock.h"
|
#include "shared/gui/mocks/AppConfigMock.h"
|
||||||
#include "shared/gui/mocks/ServerConfigMock.h"
|
#include "shared/gui/mocks/ServerConfigMock.h"
|
||||||
|
|
@ -45,41 +44,23 @@ public:
|
||||||
MOCK_METHOD(QString, readAllStandardError, (), (override));
|
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
|
class DepsMock : public CoreProcess::Deps
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DepsMock()
|
DepsMock()
|
||||||
{
|
{
|
||||||
ON_CALL(*this, process()).WillByDefault(ReturnRef(m_process));
|
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, appPath(_)).WillByDefault(Return("stub app path"));
|
||||||
ON_CALL(*this, fileExists(_)).WillByDefault(Return(true));
|
ON_CALL(*this, fileExists(_)).WillByDefault(Return(true));
|
||||||
ON_CALL(*this, getProfileRoot()).WillByDefault(Return("stub profile"));
|
ON_CALL(*this, getProfileRoot()).WillByDefault(Return("stub profile"));
|
||||||
}
|
}
|
||||||
|
|
||||||
MOCK_METHOD(proxy::QProcessProxy &, process, (), (override));
|
MOCK_METHOD(proxy::QProcessProxy &, process, (), (override));
|
||||||
MOCK_METHOD(ipc::IQIpcClient &, ipcClient, (), (override));
|
|
||||||
MOCK_METHOD(QString, appPath, (const QString &name), (const, override));
|
MOCK_METHOD(QString, appPath, (const QString &name), (const, override));
|
||||||
MOCK_METHOD(bool, fileExists, (const QString &path), (const, override));
|
MOCK_METHOD(bool, fileExists, (const QString &path), (const, override));
|
||||||
MOCK_METHOD(QString, getProfileRoot, (), (const, override));
|
MOCK_METHOD(QString, getProfileRoot, (), (const, override));
|
||||||
|
|
||||||
NiceMock<QProcessProxyMock> m_process;
|
NiceMock<QProcessProxyMock> m_process;
|
||||||
NiceMock<QIpcClientMock> m_ipcClient;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CoreProcessTests : public Test
|
class CoreProcessTests : public Test
|
||||||
|
|
@ -111,15 +92,6 @@ TEST_F(CoreProcessTests, start_serverDesktop_callsProcessStart)
|
||||||
m_coreProcess.start(ProcessMode::kDesktop);
|
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)
|
TEST_F(CoreProcessTests, start_clientDesktop_callsProcessStart)
|
||||||
{
|
{
|
||||||
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
||||||
|
|
@ -130,16 +102,6 @@ TEST_F(CoreProcessTests, start_clientDesktop_callsProcessStart)
|
||||||
m_coreProcess.start(ProcessMode::kDesktop);
|
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)
|
TEST_F(CoreProcessTests, stop_serverDesktop_callsProcessClose)
|
||||||
{
|
{
|
||||||
m_coreProcess.setMode(CoreProcess::Mode::Server);
|
m_coreProcess.setMode(CoreProcess::Mode::Server);
|
||||||
|
|
@ -150,16 +112,6 @@ TEST_F(CoreProcessTests, stop_serverDesktop_callsProcessClose)
|
||||||
m_coreProcess.stop(ProcessMode::kDesktop);
|
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)
|
TEST_F(CoreProcessTests, stop_clientDesktop_callsProcessClose)
|
||||||
{
|
{
|
||||||
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
m_coreProcess.setMode(CoreProcess::Mode::Client);
|
||||||
|
|
@ -171,17 +123,6 @@ TEST_F(CoreProcessTests, stop_clientDesktop_callsProcessClose)
|
||||||
m_coreProcess.stop(ProcessMode::kDesktop);
|
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)
|
TEST_F(CoreProcessTests, restart_serverDesktop_callsProcessStart)
|
||||||
{
|
{
|
||||||
ON_CALL(m_appConfig, processMode()).WillByDefault(Return(ProcessMode::kDesktop));
|
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());
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue