fully replaced gui/daemon named pipes ipc with tcp ipc.
This commit is contained in:
parent
79d73bd163
commit
7d5fbde71d
|
@ -22,6 +22,7 @@ set(inc
|
||||||
../../lib/base
|
../../lib/base
|
||||||
../../lib/common
|
../../lib/common
|
||||||
../../lib/io
|
../../lib/io
|
||||||
|
../../lib/ipc
|
||||||
../../lib/mt
|
../../lib/mt
|
||||||
../../lib/net
|
../../lib/net
|
||||||
../../lib/platform
|
../../lib/platform
|
||||||
|
@ -47,7 +48,7 @@ if (VNC_SUPPORT)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(synergyd
|
target_link_libraries(synergyd
|
||||||
arch base common io mt net platform synergy ${libs})
|
arch base common io ipc mt net platform synergy ${libs})
|
||||||
|
|
||||||
if (CONF_CPACK)
|
if (CONF_CPACK)
|
||||||
install(TARGETS
|
install(TARGETS
|
||||||
|
|
|
@ -36,7 +36,8 @@ SOURCES += src/main.cpp \
|
||||||
src/QSynergyApplication.cpp \
|
src/QSynergyApplication.cpp \
|
||||||
src/VersionChecker.cpp \
|
src/VersionChecker.cpp \
|
||||||
src/SetupWizard.cpp \
|
src/SetupWizard.cpp \
|
||||||
src/IpcLogReader.cpp
|
src/IpcLogReader.cpp \
|
||||||
|
src/IpcClient.cpp
|
||||||
HEADERS += src/MainWindow.h \
|
HEADERS += src/MainWindow.h \
|
||||||
src/AboutDialog.h \
|
src/AboutDialog.h \
|
||||||
src/ServerConfig.h \
|
src/ServerConfig.h \
|
||||||
|
@ -59,7 +60,8 @@ HEADERS += src/MainWindow.h \
|
||||||
src/QSynergyApplication.h \
|
src/QSynergyApplication.h \
|
||||||
src/VersionChecker.h \
|
src/VersionChecker.h \
|
||||||
src/SetupWizard.h \
|
src/SetupWizard.h \
|
||||||
src/IpcLogReader.h
|
src/IpcLogReader.h \
|
||||||
|
src/IpcClient.h
|
||||||
RESOURCES += res/Synergy.qrc
|
RESOURCES += res/Synergy.qrc
|
||||||
RC_FILE = res/win/Synergy.rc
|
RC_FILE = res/win/Synergy.rc
|
||||||
TRANSLATIONS = res/lang/nl_NL.ts
|
TRANSLATIONS = res/lang/nl_NL.ts
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2012 Nick Bolton
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IpcClient.h"
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
|
IpcClient::IpcClient()
|
||||||
|
{
|
||||||
|
m_Socket = new QTcpSocket(this);
|
||||||
|
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
||||||
|
connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcClient::~IpcClient()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcClient::connectToHost()
|
||||||
|
{
|
||||||
|
m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), IPC_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcClient::read()
|
||||||
|
{
|
||||||
|
QDataStream stream(m_Socket);
|
||||||
|
|
||||||
|
char codeBuf[1];
|
||||||
|
stream.readRawData(codeBuf, 1);
|
||||||
|
|
||||||
|
switch (codeBuf[0]) {
|
||||||
|
case kIpcLogLine: {
|
||||||
|
char lenBuf[1];
|
||||||
|
stream.readRawData(lenBuf, 1);
|
||||||
|
|
||||||
|
char* data = new char[lenBuf[0] + 1];
|
||||||
|
stream.readRawData(data, lenBuf[0]);
|
||||||
|
data[(int)lenBuf[0]] = 0;
|
||||||
|
|
||||||
|
QString s(data);
|
||||||
|
readLogLine(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcClient::error(QAbstractSocket::SocketError error)
|
||||||
|
{
|
||||||
|
errorMessage("ERROR: Could not connect to background service.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcClient::write(unsigned char code, unsigned char length, const char* data)
|
||||||
|
{
|
||||||
|
QDataStream stream(m_Socket);
|
||||||
|
|
||||||
|
char codeBuf[1];
|
||||||
|
codeBuf[0] = code;
|
||||||
|
stream.writeRawData(codeBuf, 1);
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case kIpcCommand: {
|
||||||
|
char lenBuf[1];
|
||||||
|
lenBuf[0] = length;
|
||||||
|
stream.writeRawData(lenBuf, 1);
|
||||||
|
stream.writeRawData(data, length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,32 +17,37 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include <QObject>
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
|
||||||
#include "IArchLog.h"
|
#define IPC_PORT 24801
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#define ARCH_IPC_LOG CArchIpcLogWindows
|
class QTcpSocket;
|
||||||
|
|
||||||
class CThread;
|
class IpcClient : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
//! Win32 implementation of IArchLog (IPC version)
|
|
||||||
class CArchIpcLogWindows : public IArchLog {
|
|
||||||
public:
|
public:
|
||||||
CArchIpcLogWindows();
|
IpcClient();
|
||||||
virtual ~CArchIpcLogWindows();
|
virtual ~IpcClient();
|
||||||
|
|
||||||
// IArchLog overrides
|
void connectToHost();
|
||||||
virtual void openLog(const char* name);
|
void write(unsigned char code, unsigned char length, const char* data);
|
||||||
virtual void closeLog();
|
|
||||||
virtual void showLog(bool showIfEmpty);
|
private slots:
|
||||||
virtual void writeLog(ELevel, const char*);
|
void read();
|
||||||
|
void error(QAbstractSocket::SocketError error);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void readLogLine(const QString& text);
|
||||||
|
void errorMessage(const QString& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void connectThread(void*);
|
QTcpSocket* m_Socket;
|
||||||
|
};
|
||||||
private:
|
|
||||||
HANDLE m_pipe;
|
enum EIpcMessage {
|
||||||
CThread* m_listenThread;
|
kIpcLogLine,
|
||||||
bool m_connected;
|
kIpcCommand
|
||||||
};
|
};
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#define WEBSITE_ADDRESS "synergy-foss.org"
|
#define WEBSITE_ADDRESS "synergy-foss.org"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "AboutDialog.h"
|
#include "AboutDialog.h"
|
||||||
#include "ServerConfigDialog.h"
|
#include "ServerConfigDialog.h"
|
||||||
|
@ -88,8 +90,10 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
|
||||||
|
|
||||||
if (appConfig.processMode() == Service)
|
if (appConfig.processMode() == Service)
|
||||||
{
|
{
|
||||||
connect(&m_IpcLogReader, SIGNAL(receivedLine(const QString&)), this, SLOT(appendLog(const QString&)));
|
connect(&m_IpcClient, SIGNAL(readLogLine(const QString&)), this, SLOT(appendLog(const QString&)));
|
||||||
m_IpcLogReader.start();
|
connect(&m_IpcClient, SIGNAL(errorMessage(const QString&)), this, SLOT(appendLog(const QString&)));
|
||||||
|
m_IpcClient.connectToHost();
|
||||||
|
appendLog("INFO: Connecting to background service...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,55 +669,9 @@ void MainWindow::on_m_pButtonConfigureServer_clicked()
|
||||||
|
|
||||||
void MainWindow::sendDaemonCommand(const QString& command, bool showErrors)
|
void MainWindow::sendDaemonCommand(const QString& command, bool showErrors)
|
||||||
{
|
{
|
||||||
sendIpcMessage(Command, command.toStdString().c_str(), showErrors);
|
std::string s = command.toStdString();
|
||||||
}
|
const char* data = s.c_str();
|
||||||
|
m_IpcClient.write(Command, strlen(data), data);
|
||||||
// TODO: put this in an IPC client class.
|
|
||||||
void MainWindow::sendIpcMessage(qIpcMessage type, const char* data, bool showErrors)
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
|
|
||||||
const WCHAR* name = L"\\\\.\\pipe\\Synergy";
|
|
||||||
char message[1024];
|
|
||||||
message[0] = type;
|
|
||||||
char* messagePtr = message;
|
|
||||||
messagePtr++;
|
|
||||||
strcpy(messagePtr, data);
|
|
||||||
|
|
||||||
HANDLE pipe = CreateFile(
|
|
||||||
name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
||||||
|
|
||||||
if (showErrors && pipe == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
appendLog(QString("ERROR: could not connect to service, error: ") +
|
|
||||||
QString::number(GetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD dwMode = PIPE_READMODE_MESSAGE;
|
|
||||||
BOOL stateSuccess = SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
|
|
||||||
|
|
||||||
if (showErrors && !stateSuccess)
|
|
||||||
{
|
|
||||||
appendLog(QString("ERROR: could not set service pipe state, error: ") +
|
|
||||||
QString::number(GetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD written;
|
|
||||||
BOOL writeSuccess = WriteFile(
|
|
||||||
pipe, message, strlen(message), &written, NULL);
|
|
||||||
|
|
||||||
if (showErrors && !writeSuccess)
|
|
||||||
{
|
|
||||||
appendLog(QString("ERROR: could not write to service pipe, error: ") +
|
|
||||||
QString::number(GetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(pipe);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_m_pActionWizard_triggered()
|
void MainWindow::on_m_pActionWizard_triggered()
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "ServerConfig.h"
|
#include "ServerConfig.h"
|
||||||
#include "AppConfig.h"
|
#include "AppConfig.h"
|
||||||
#include "VersionChecker.h"
|
#include "VersionChecker.h"
|
||||||
#include "IpcLogReader.h"
|
#include "IpcClient.h"
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
class QMenu;
|
class QMenu;
|
||||||
|
@ -142,7 +142,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
|
||||||
bool m_alreadyHidden;
|
bool m_alreadyHidden;
|
||||||
VersionChecker m_versionChecker;
|
VersionChecker m_versionChecker;
|
||||||
SetupWizard* m_SetupWizard;
|
SetupWizard* m_SetupWizard;
|
||||||
IpcLogReader m_IpcLogReader;
|
IpcClient m_IpcClient;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
# include "CArchDaemonWindows.h"
|
# include "CArchDaemonWindows.h"
|
||||||
# include "CArchFileWindows.h"
|
# include "CArchFileWindows.h"
|
||||||
# include "CArchLogWindows.h"
|
# include "CArchLogWindows.h"
|
||||||
# include "CArchIpcLogWindows.h"
|
|
||||||
# include "CArchMiscWindows.h"
|
# include "CArchMiscWindows.h"
|
||||||
# include "CArchMultithreadWindows.h"
|
# include "CArchMultithreadWindows.h"
|
||||||
# include "CArchNetworkWinsock.h"
|
# include "CArchNetworkWinsock.h"
|
||||||
|
@ -57,7 +56,6 @@
|
||||||
# include "CArchDaemonUnix.h"
|
# include "CArchDaemonUnix.h"
|
||||||
# include "CArchFileUnix.h"
|
# include "CArchFileUnix.h"
|
||||||
# include "CArchLogUnix.h"
|
# include "CArchLogUnix.h"
|
||||||
# include "CArchIpcLogUnix.h"
|
|
||||||
# if HAVE_PTHREAD
|
# if HAVE_PTHREAD
|
||||||
# include "CArchMultithreadPosix.h"
|
# include "CArchMultithreadPosix.h"
|
||||||
# endif
|
# endif
|
||||||
|
@ -111,7 +109,6 @@ public:
|
||||||
*/
|
*/
|
||||||
static CArch* getInstance();
|
static CArch* getInstance();
|
||||||
|
|
||||||
ARCH_IPC_LOG& ipcLog() const { return (ARCH_IPC_LOG&)m_ipcLog; }
|
|
||||||
ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; }
|
ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -120,7 +117,6 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CArch* s_instance;
|
static CArch* s_instance;
|
||||||
ARCH_IPC_LOG m_ipcLog;
|
|
||||||
ARCH_PLUGIN m_plugin;
|
ARCH_PLUGIN m_plugin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman, Nick Bolton, Sorin Sbarnea
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CArchIpcLogWindows.h"
|
|
||||||
#include "CArchMiscWindows.h"
|
|
||||||
#include "XArch.h"
|
|
||||||
#include "CThread.h"
|
|
||||||
#include "TMethodJob.h"
|
|
||||||
#include "CArch.h"
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// CArchIpcLogWindows
|
|
||||||
//
|
|
||||||
|
|
||||||
CArchIpcLogWindows::CArchIpcLogWindows() :
|
|
||||||
m_pipe(NULL),
|
|
||||||
m_listenThread(NULL),
|
|
||||||
m_connected(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CArchIpcLogWindows::~CArchIpcLogWindows()
|
|
||||||
{
|
|
||||||
if (m_listenThread != NULL)
|
|
||||||
delete m_listenThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CArchIpcLogWindows::openLog(const char* name)
|
|
||||||
{
|
|
||||||
// grant access to everyone.
|
|
||||||
SECURITY_DESCRIPTOR sd;
|
|
||||||
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
|
||||||
SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);
|
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
||||||
sa.lpSecurityDescriptor = &sd;
|
|
||||||
|
|
||||||
HANDLE pipe = CreateNamedPipe(
|
|
||||||
TEXT("\\\\.\\pipe\\SynergyLog"),
|
|
||||||
PIPE_ACCESS_DUPLEX,
|
|
||||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
|
||||||
PIPE_UNLIMITED_INSTANCES,
|
|
||||||
1024, 1024, 0, &sa);
|
|
||||||
|
|
||||||
if (pipe == INVALID_HANDLE_VALUE)
|
|
||||||
XArch("could not create named pipe.");
|
|
||||||
|
|
||||||
m_pipe = pipe;
|
|
||||||
|
|
||||||
m_listenThread = new CThread(new TMethodJob<CArchIpcLogWindows>(
|
|
||||||
this, &CArchIpcLogWindows::connectThread, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CArchIpcLogWindows::connectThread(void*)
|
|
||||||
{
|
|
||||||
// HACK: this seems like a hacky pile of bollocks. it will continuously call
|
|
||||||
// ConnectNamedPipe every second. if there is no client, it will block,
|
|
||||||
// but if there is a client it will return FALSE and GetLastError() will
|
|
||||||
// be ERROR_PIPE_CONNECTED. in any other case, the client has gone away
|
|
||||||
// and ConnectNamedPipe will go back to blocking (waiting for the client
|
|
||||||
// to reconnect).
|
|
||||||
while (true) {
|
|
||||||
BOOL result = ConnectNamedPipe(m_pipe, NULL);
|
|
||||||
if ((result == TRUE) || (GetLastError() == ERROR_PIPE_CONNECTED)) {
|
|
||||||
m_connected = true;
|
|
||||||
ARCH->sleep(1);
|
|
||||||
} else {
|
|
||||||
DisconnectNamedPipe(m_pipe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CArchIpcLogWindows::closeLog()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CArchIpcLogWindows::showLog(bool)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CArchIpcLogWindows::writeLog(ELevel level, const char* data)
|
|
||||||
{
|
|
||||||
if (!m_connected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DWORD bytesWritten;
|
|
||||||
WriteFile(m_pipe, data, (DWORD)strlen(data), &bytesWritten, NULL);
|
|
||||||
}
|
|
|
@ -27,7 +27,6 @@ if (WIN32)
|
||||||
CArchDaemonWindows.h
|
CArchDaemonWindows.h
|
||||||
CArchFileWindows.h
|
CArchFileWindows.h
|
||||||
CArchLogWindows.h
|
CArchLogWindows.h
|
||||||
CArchIpcLogWindows.h
|
|
||||||
CArchMiscWindows.h
|
CArchMiscWindows.h
|
||||||
CArchMultithreadWindows.h
|
CArchMultithreadWindows.h
|
||||||
CArchNetworkWinsock.h
|
CArchNetworkWinsock.h
|
||||||
|
@ -51,7 +50,6 @@ if (WIN32)
|
||||||
CArchDaemonWindows.cpp
|
CArchDaemonWindows.cpp
|
||||||
CArchFileWindows.cpp
|
CArchFileWindows.cpp
|
||||||
CArchLogWindows.cpp
|
CArchLogWindows.cpp
|
||||||
CArchIpcLogWindows.cpp
|
|
||||||
CArchMiscWindows.cpp
|
CArchMiscWindows.cpp
|
||||||
CArchMultithreadWindows.cpp
|
CArchMultithreadWindows.cpp
|
||||||
CArchNetworkWinsock.cpp
|
CArchNetworkWinsock.cpp
|
||||||
|
@ -71,7 +69,6 @@ elseif (UNIX)
|
||||||
CArchDaemonUnix.cpp
|
CArchDaemonUnix.cpp
|
||||||
CArchFileUnix.cpp
|
CArchFileUnix.cpp
|
||||||
CArchLogUnix.cpp
|
CArchLogUnix.cpp
|
||||||
CArchIpcLogUnix.cpp
|
|
||||||
CArchMultithreadPosix.cpp
|
CArchMultithreadPosix.cpp
|
||||||
CArchNetworkBSD.cpp
|
CArchNetworkBSD.cpp
|
||||||
CArchSleepUnix.cpp
|
CArchSleepUnix.cpp
|
||||||
|
|
|
@ -262,41 +262,3 @@ CFileLogOutputter::close() {}
|
||||||
|
|
||||||
void
|
void
|
||||||
CFileLogOutputter::show(bool showIfEmpty) {}
|
CFileLogOutputter::show(bool showIfEmpty) {}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// CConsoleLogOutputter
|
|
||||||
//
|
|
||||||
|
|
||||||
CIpcLogOutputter::CIpcLogOutputter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CIpcLogOutputter::~CIpcLogOutputter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CIpcLogOutputter::open(const char* title)
|
|
||||||
{
|
|
||||||
ARCH->ipcLog().openLog(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CIpcLogOutputter::close()
|
|
||||||
{
|
|
||||||
ARCH->ipcLog().closeLog();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CIpcLogOutputter::show(bool showIfEmpty)
|
|
||||||
{
|
|
||||||
ARCH->ipcLog().showLog(showIfEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CIpcLogOutputter::write(ELevel level, const char* msg)
|
|
||||||
{
|
|
||||||
ARCH->ipcLog().writeLog(level, msg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -99,22 +99,6 @@ public:
|
||||||
virtual bool write(ELevel level, const char* message);
|
virtual bool write(ELevel level, const char* message);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Write log to GUI over IPC
|
|
||||||
/*!
|
|
||||||
This outputter writes output to the GUI via IPC.
|
|
||||||
*/
|
|
||||||
class CIpcLogOutputter : public ILogOutputter {
|
|
||||||
public:
|
|
||||||
CIpcLogOutputter();
|
|
||||||
virtual ~CIpcLogOutputter();
|
|
||||||
|
|
||||||
// ILogOutputter overrides
|
|
||||||
virtual void open(const char* title);
|
|
||||||
virtual void close();
|
|
||||||
virtual void show(bool showIfEmpty);
|
|
||||||
virtual bool write(ELevel level, const char* message);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Write log to system log only
|
//! Write log to system log only
|
||||||
/*!
|
/*!
|
||||||
Creating an object of this type inserts a CStopLogOutputter followed
|
Creating an object of this type inserts a CStopLogOutputter followed
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
CEvent::Type CIpcClientProxy::s_messageReceivedEvent = CEvent::kUnknown;
|
CEvent::Type CIpcClientProxy::s_messageReceivedEvent = CEvent::kUnknown;
|
||||||
|
|
||||||
CIpcClientProxy::CIpcClientProxy(IStream& stream) :
|
CIpcClientProxy::CIpcClientProxy(IStream& stream) :
|
||||||
m_stream(stream)
|
m_stream(stream),
|
||||||
|
m_enableLog(false)
|
||||||
{
|
{
|
||||||
EVENTQUEUE->adoptHandler(m_stream.getInputReadyEvent(),
|
EVENTQUEUE->adoptHandler(m_stream.getInputReadyEvent(),
|
||||||
stream.getEventTarget(),
|
stream.getEventTarget(),
|
||||||
|
@ -45,12 +46,16 @@ CIpcClientProxy::handleData(const CEvent&, void*)
|
||||||
UInt8 code[1];
|
UInt8 code[1];
|
||||||
UInt32 n = m_stream.read(code, 1);
|
UInt32 n = m_stream.read(code, 1);
|
||||||
while (n != 0) {
|
while (n != 0) {
|
||||||
|
UInt8 type = code[0];
|
||||||
|
|
||||||
CIpcMessage* m = new CIpcMessage();
|
CIpcMessage* m = new CIpcMessage();
|
||||||
m->m_type = code[1];
|
m->m_type = type;
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "ipc client proxy read: %d", code[0]));
|
if (m_enableLog) {
|
||||||
switch (code[0]) {
|
LOG((CLOG_DEBUG "ipc client proxy read: %d", code[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
case kIpcCommand:
|
case kIpcCommand:
|
||||||
m->m_data = parseCommand();
|
m->m_data = parseCommand();
|
||||||
break;
|
break;
|
||||||
|
@ -71,7 +76,9 @@ CIpcClientProxy::handleData(const CEvent&, void*)
|
||||||
void
|
void
|
||||||
CIpcClientProxy::send(const CIpcMessage& message)
|
CIpcClientProxy::send(const CIpcMessage& message)
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG "ipc client proxy write: %d", message.m_type));
|
if (m_enableLog) {
|
||||||
|
LOG((CLOG_DEBUG "ipc client proxy write: %d", message.m_type));
|
||||||
|
}
|
||||||
|
|
||||||
UInt8 code[1];
|
UInt8 code[1];
|
||||||
code[0] = message.m_type;
|
code[0] = message.m_type;
|
||||||
|
@ -80,17 +87,21 @@ CIpcClientProxy::send(const CIpcMessage& message)
|
||||||
switch (message.m_type) {
|
switch (message.m_type) {
|
||||||
case kIpcLogLine: {
|
case kIpcLogLine: {
|
||||||
CString* s = (CString*)message.m_data;
|
CString* s = (CString*)message.m_data;
|
||||||
|
const char* data = s->c_str();
|
||||||
|
int len = strlen(data);
|
||||||
|
|
||||||
UInt8 len[1];
|
UInt8 lenBuf[1];
|
||||||
len[0] = s->size();
|
lenBuf[0] = len;
|
||||||
m_stream.write(len, 1);
|
m_stream.write(lenBuf, 1);
|
||||||
|
|
||||||
m_stream.write(s->c_str(), s->size());
|
m_stream.write(data, len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG((CLOG_ERR "message not supported: %d", message.m_type));
|
if (m_enableLog) {
|
||||||
|
LOG((CLOG_ERR "message not supported: %d", message.m_type));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +121,9 @@ CIpcClientProxy::parseCommand()
|
||||||
void
|
void
|
||||||
CIpcClientProxy::disconnect()
|
CIpcClientProxy::disconnect()
|
||||||
{
|
{
|
||||||
LOG((CLOG_NOTE "disconnect, closing stream"));
|
if (m_enableLog) {
|
||||||
|
LOG((CLOG_NOTE "disconnect, closing stream"));
|
||||||
|
}
|
||||||
m_stream.close();
|
m_stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IStream& m_stream;
|
IStream& m_stream;
|
||||||
|
bool m_enableLog;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CEvent::Type s_messageReceivedEvent;
|
static CEvent::Type s_messageReceivedEvent;
|
||||||
|
|
|
@ -15,32 +15,41 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CArchIpcLogUnix.h"
|
#include "CIpcLogOutputter.h"
|
||||||
|
#include "CIpcServer.h"
|
||||||
|
#include "CIpcMessage.h"
|
||||||
|
#include "Ipc.h"
|
||||||
|
|
||||||
CArchIpcLogUnix::CArchIpcLogUnix()
|
CIpcLogOutputter::CIpcLogOutputter(CIpcServer& ipcServer) :
|
||||||
|
m_ipcServer(ipcServer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CArchIpcLogUnix::~CArchIpcLogUnix()
|
CIpcLogOutputter::~CIpcLogOutputter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArchIpcLogUnix::openLog(const char* name)
|
CIpcLogOutputter::open(const char* title)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArchIpcLogUnix::closeLog()
|
CIpcLogOutputter::close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArchIpcLogUnix::showLog(bool showIfEmpty)
|
CIpcLogOutputter::show(bool showIfEmpty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CArchIpcLogUnix::writeLog(ELevel, const char*)
|
CIpcLogOutputter::write(ELevel level, const char* msg)
|
||||||
{
|
{
|
||||||
|
CIpcMessage message;
|
||||||
|
message.m_type = kIpcLogLine;
|
||||||
|
message.m_data = new CString(msg);
|
||||||
|
m_ipcServer.send(message);
|
||||||
|
return true;
|
||||||
}
|
}
|
|
@ -17,18 +17,25 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IArchLog.h"
|
#include "ILogOutputter.h"
|
||||||
|
|
||||||
#define ARCH_IPC_LOG CArchIpcLogUnix
|
class CIpcServer;
|
||||||
|
|
||||||
class CArchIpcLogUnix : public IArchLog {
|
//! Write log to GUI over IPC
|
||||||
|
/*!
|
||||||
|
This outputter writes output to the GUI via IPC.
|
||||||
|
*/
|
||||||
|
class CIpcLogOutputter : public ILogOutputter {
|
||||||
public:
|
public:
|
||||||
CArchIpcLogUnix();
|
CIpcLogOutputter(CIpcServer& ipcServer);
|
||||||
virtual ~CArchIpcLogUnix();
|
virtual ~CIpcLogOutputter();
|
||||||
|
|
||||||
// IArchLog overrides
|
// ILogOutputter overrides
|
||||||
virtual void openLog(const char* name);
|
virtual void open(const char* title);
|
||||||
virtual void closeLog();
|
virtual void close();
|
||||||
virtual void showLog(bool showIfEmpty);
|
virtual void show(bool showIfEmpty);
|
||||||
virtual void writeLog(ELevel, const char*);
|
virtual bool write(ELevel level, const char* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CIpcServer& m_ipcServer;
|
||||||
};
|
};
|
|
@ -17,11 +17,15 @@
|
||||||
|
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
|
|
||||||
CIpcMessage::CIpcMessage()
|
CIpcMessage::CIpcMessage() :
|
||||||
|
m_type(0),
|
||||||
|
m_data(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CIpcMessage::~CIpcMessage()
|
CIpcMessage::~CIpcMessage()
|
||||||
{
|
{
|
||||||
delete m_data;
|
if (m_data != nullptr) {
|
||||||
|
delete m_data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,13 +57,15 @@ CIpcServer::handleClientConnecting(const CEvent&, void*)
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// when there is already a client connected, this causes stack overflow,
|
||||||
|
//
|
||||||
LOG((CLOG_NOTE "accepted ipc client connection"));
|
LOG((CLOG_NOTE "accepted ipc client connection"));
|
||||||
|
|
||||||
// TODO: delete on disconnect
|
// TODO: delete on disconnect
|
||||||
CIpcClientProxy* proxy = new CIpcClientProxy(*stream);
|
CIpcClientProxy* proxy = new CIpcClientProxy(*stream);
|
||||||
m_clients.insert(proxy);
|
m_clients.insert(proxy);
|
||||||
|
|
||||||
EVENTQUEUE->addEvent(CEvent(getClientConnectedEvent(), this, proxy));
|
EVENTQUEUE->addEvent(CEvent(getClientConnectedEvent(), this, proxy, CEvent::kDontFreeData));
|
||||||
}
|
}
|
||||||
|
|
||||||
CEvent::Type
|
CEvent::Type
|
||||||
|
|
|
@ -20,6 +20,7 @@ set(inc
|
||||||
CIpcServerProxy.h
|
CIpcServerProxy.h
|
||||||
CIpcClientProxy.h
|
CIpcClientProxy.h
|
||||||
CIpcMessage.h
|
CIpcMessage.h
|
||||||
|
CIpcLogOutputter.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
|
@ -28,6 +29,7 @@ set(src
|
||||||
CIpcServerProxy.cpp
|
CIpcServerProxy.cpp
|
||||||
CIpcClientProxy.cpp
|
CIpcClientProxy.cpp
|
||||||
CIpcMessage.cpp
|
CIpcMessage.cpp
|
||||||
|
CIpcLogOutputter.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "XArchWindows.h"
|
#include "XArchWindows.h"
|
||||||
#include "CApp.h"
|
#include "CApp.h"
|
||||||
#include "CArgsBase.h"
|
#include "CArgsBase.h"
|
||||||
|
#include "CIpcLogOutputter.h"
|
||||||
|
|
||||||
#include <Tlhelp32.h>
|
#include <Tlhelp32.h>
|
||||||
#include <UserEnv.h>
|
#include <UserEnv.h>
|
||||||
|
@ -42,7 +43,8 @@ CMSWindowsRelauncher::CMSWindowsRelauncher(bool autoDetectCommand) :
|
||||||
m_running(true),
|
m_running(true),
|
||||||
m_commandChanged(false),
|
m_commandChanged(false),
|
||||||
m_stdOutWrite(NULL),
|
m_stdOutWrite(NULL),
|
||||||
m_stdOutRead(NULL)
|
m_stdOutRead(NULL),
|
||||||
|
m_ipcLogOutputter(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +405,7 @@ CMSWindowsRelauncher::outputLoop(void*)
|
||||||
else {
|
else {
|
||||||
// send process output over IPC to GUI.
|
// send process output over IPC to GUI.
|
||||||
buffer[bytesRead] = '\0';
|
buffer[bytesRead] = '\0';
|
||||||
ARCH->ipcLog().writeLog(kINFO, buffer);
|
m_ipcLogOutputter->write(kINFO, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
class CThread;
|
class CThread;
|
||||||
|
class CIpcLogOutputter;
|
||||||
|
|
||||||
class CMSWindowsRelauncher {
|
class CMSWindowsRelauncher {
|
||||||
public:
|
public:
|
||||||
|
@ -42,6 +43,9 @@ private:
|
||||||
void sendIpcMessage(int type, const char* data);
|
void sendIpcMessage(int type, const char* data);
|
||||||
void shutdownProcess(const PROCESS_INFORMATION& pi, int timeout);
|
void shutdownProcess(const PROCESS_INFORMATION& pi, int timeout);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CIpcLogOutputter* m_ipcLogOutputter;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CThread* m_thread;
|
CThread* m_thread;
|
||||||
bool m_autoDetectCommand;
|
bool m_autoDetectCommand;
|
||||||
|
|
|
@ -137,6 +137,7 @@ set(inc
|
||||||
../common
|
../common
|
||||||
../mt
|
../mt
|
||||||
../synergy
|
../synergy
|
||||||
|
../ipc
|
||||||
)
|
)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
|
@ -191,5 +192,5 @@ if (WIN32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(platform synergy ${libs})
|
target_link_libraries(platform ipc synergy ${libs})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
#include "CMSWindowsRelauncher.h"
|
#include "CMSWindowsRelauncher.h"
|
||||||
#include "CMSWindowsDebugOutputter.h"
|
#include "CMSWindowsDebugOutputter.h"
|
||||||
#include "TMethodJob.h"
|
#include "TMethodJob.h"
|
||||||
|
#include "TMethodEventJob.h"
|
||||||
|
#include "CIpcClientProxy.h"
|
||||||
|
#include "CIpcMessage.h"
|
||||||
|
#include "CSocketMultiplexer.h"
|
||||||
|
#include "CIpcLogOutputter.h"
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
@ -69,9 +74,11 @@ winMainLoopStatic(int, const char**)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CDaemonApp::CDaemonApp()
|
CDaemonApp::CDaemonApp() :
|
||||||
|
m_ipcServer(nullptr),
|
||||||
|
m_ipcLogOutputter(nullptr)
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
: m_relauncher(false)
|
,m_relauncher(false)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
@ -91,15 +98,9 @@ CDaemonApp::run(int argc, char** argv)
|
||||||
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// send logging to gui via ipc
|
|
||||||
CLOG->insert(new CIpcLogOutputter());
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
// sends debug messages to visual studio console window.
|
// sends debug messages to visual studio console window.
|
||||||
CLOG->insert(new CMSWindowsDebugOutputter());
|
CLOG->insert(new CMSWindowsDebugOutputter());
|
||||||
|
|
||||||
CThread pipeThread(new TMethodJob<CDaemonApp>(
|
|
||||||
this, &CDaemonApp::pipeThread, nullptr));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// default log level to system setting.
|
// default log level to system setting.
|
||||||
|
@ -174,6 +175,23 @@ CDaemonApp::mainLoop(bool logToFile)
|
||||||
|
|
||||||
CEventQueue eventQueue;
|
CEventQueue eventQueue;
|
||||||
|
|
||||||
|
// create socket multiplexer. this must happen after daemonization
|
||||||
|
// on unix because threads evaporate across a fork().
|
||||||
|
CSocketMultiplexer multiplexer;
|
||||||
|
|
||||||
|
// uses event queue, must be created here.
|
||||||
|
m_ipcServer = new CIpcServer();
|
||||||
|
|
||||||
|
eventQueue.adoptHandler(
|
||||||
|
CIpcServer::getClientConnectedEvent(), m_ipcServer,
|
||||||
|
new TMethodEventJob<CDaemonApp>(this, &CDaemonApp::handleIpcConnected));
|
||||||
|
|
||||||
|
m_ipcServer->listen();
|
||||||
|
|
||||||
|
// send logging to gui via ipc, log system adopts outputter.
|
||||||
|
m_ipcLogOutputter = new CIpcLogOutputter(*m_ipcServer);
|
||||||
|
CLOG->insert(m_ipcLogOutputter);
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
// HACK: create a dummy screen, which can handle system events
|
// HACK: create a dummy screen, which can handle system events
|
||||||
// (such as a stop request from the service controller).
|
// (such as a stop request from the service controller).
|
||||||
|
@ -181,6 +199,8 @@ CDaemonApp::mainLoop(bool logToFile)
|
||||||
CGameDeviceInfo gameDevice;
|
CGameDeviceInfo gameDevice;
|
||||||
CScreen dummyScreen(new CMSWindowsScreen(false, true, gameDevice));
|
CScreen dummyScreen(new CMSWindowsScreen(false, true, gameDevice));
|
||||||
|
|
||||||
|
m_relauncher.m_ipcLogOutputter = m_ipcLogOutputter;
|
||||||
|
|
||||||
string command = ARCH->setting("Command");
|
string command = ARCH->setting("Command");
|
||||||
if (command != "") {
|
if (command != "") {
|
||||||
LOG((CLOG_INFO "using last known command: %s", command.c_str()));
|
LOG((CLOG_INFO "using last known command: %s", command.c_str()));
|
||||||
|
@ -190,22 +210,27 @@ CDaemonApp::mainLoop(bool logToFile)
|
||||||
m_relauncher.startAsync();
|
m_relauncher.startAsync();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EVENTQUEUE->loop();
|
eventQueue.loop();
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
m_relauncher.stop();
|
m_relauncher.stop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
eventQueue.removeHandler(
|
||||||
|
CIpcServer::getClientConnectedEvent(), m_ipcServer);
|
||||||
|
|
||||||
|
delete m_ipcServer;
|
||||||
|
|
||||||
DAEMON_RUNNING(false);
|
DAEMON_RUNNING(false);
|
||||||
}
|
}
|
||||||
catch (XArch& e) {
|
catch (XArch& e) {
|
||||||
LOG((CLOG_ERR, e.what().c_str()));
|
LOG((CLOG_ERR "xarch exception: %s", e.what().c_str()));
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e) {
|
||||||
LOG((CLOG_ERR, e.what()));
|
LOG((CLOG_ERR "std exception: %s", e.what()));
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
LOG((CLOG_ERR, "Unrecognized error."));
|
LOG((CLOG_ERR "unrecognized error."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,71 +262,35 @@ CDaemonApp::logPath()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SYSAPI_WIN32
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CDaemonApp::pipeThread(void*)
|
CDaemonApp::handleIpcConnected(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
// TODO: move this to an IPC server class.
|
LOG((CLOG_INFO "ipc client connected"));
|
||||||
while (true) {
|
EVENTQUEUE->adoptHandler(
|
||||||
|
CIpcClientProxy::getMessageReceivedEvent(), e.getData(),
|
||||||
// grant access to everyone.
|
new TMethodEventJob<CDaemonApp>(
|
||||||
SECURITY_DESCRIPTOR sd;
|
this, &CDaemonApp::handleIpcMessage));
|
||||||
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
|
||||||
SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);
|
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
||||||
sa.lpSecurityDescriptor = &sd;
|
|
||||||
|
|
||||||
HANDLE pipe = CreateNamedPipe(
|
|
||||||
_T("\\\\.\\pipe\\Synergy"),
|
|
||||||
PIPE_ACCESS_DUPLEX,
|
|
||||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
|
||||||
PIPE_UNLIMITED_INSTANCES,
|
|
||||||
1024, 1024, 0, &sa);
|
|
||||||
|
|
||||||
if (pipe == INVALID_HANDLE_VALUE)
|
|
||||||
XArch("could not create named pipe.");
|
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "opened daemon pipe: %d", pipe));
|
|
||||||
BOOL connectResult = ConnectNamedPipe(pipe, NULL);
|
|
||||||
|
|
||||||
char buffer[1024];
|
|
||||||
DWORD bytesRead;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (!ReadFile(pipe, buffer, sizeof(buffer), &bytesRead, NULL)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[bytesRead] = '\0';
|
|
||||||
LOG((CLOG_DEBUG "ipc daemon server read: %s", buffer));
|
|
||||||
|
|
||||||
try {
|
|
||||||
handlePipeMessage(buffer);
|
|
||||||
}
|
|
||||||
catch (XArch& ex) {
|
|
||||||
LOG((CLOG_ERR "handle message failed: %s", ex.what().c_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DisconnectNamedPipe(pipe);
|
|
||||||
CloseHandle(pipe);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CDaemonApp::handlePipeMessage(char* buffer)
|
CDaemonApp::handleIpcMessage(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
switch (buffer[0]) {
|
CIpcMessage& m = *reinterpret_cast<CIpcMessage*>(e.getData());
|
||||||
case kIpcCommand:
|
|
||||||
{
|
|
||||||
string command(++buffer);
|
|
||||||
|
|
||||||
// store command in system settings. this is used when the daemon
|
LOG((CLOG_DEBUG "ipc message: %d", m.m_type));
|
||||||
// next starts.
|
|
||||||
ARCH->setting("Command", command);
|
switch (m.m_type) {
|
||||||
|
case kIpcCommand: {
|
||||||
|
CString& command = *reinterpret_cast<CString*>(m.m_data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// store command in system settings. this is used when the daemon
|
||||||
|
// next starts.
|
||||||
|
ARCH->setting("Command", command);
|
||||||
|
}
|
||||||
|
catch (XArch& e) {
|
||||||
|
//LOG((CLOG_ERR "failed to save setting: %s", e.what().c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
// tell the relauncher about the new command. this causes the
|
// tell the relauncher about the new command. this causes the
|
||||||
// relauncher to stop the existing command and start the new
|
// relauncher to stop the existing command and start the new
|
||||||
|
@ -310,11 +299,8 @@ CDaemonApp::handlePipeMessage(char* buffer)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG((CLOG_WARN "unrecognized ipc message: %d", buffer[0]));
|
LOG((CLOG_ERR "ipc message not supported: %d", m.m_type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
|
#include "CIpcServer.h"
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
#include "CMSWindowsRelauncher.h"
|
#include "CMSWindowsRelauncher.h"
|
||||||
|
@ -25,6 +26,9 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class CEvent;
|
||||||
|
class CIpcLogOutputter;
|
||||||
|
|
||||||
class CDaemonApp {
|
class CDaemonApp {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -37,16 +41,19 @@ private:
|
||||||
void daemonize();
|
void daemonize();
|
||||||
void foregroundError(const char* message);
|
void foregroundError(const char* message);
|
||||||
std::string logPath();
|
std::string logPath();
|
||||||
#if SYSAPI_WIN32
|
void handleIpcConnected(const CEvent&, void*);
|
||||||
void pipeThread(void*);
|
void handleIpcMessage(const CEvent&, void*);
|
||||||
void handlePipeMessage(char* buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CDaemonApp* s_instance;
|
static CDaemonApp* s_instance;
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
CMSWindowsRelauncher m_relauncher;
|
CMSWindowsRelauncher m_relauncher;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
CIpcServer* m_ipcServer;
|
||||||
|
CIpcLogOutputter* m_ipcLogOutputter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOG_FILENAME "synergyd.log"
|
#define LOG_FILENAME "synergyd.log"
|
||||||
|
|
|
@ -102,6 +102,7 @@ set(inc
|
||||||
../client
|
../client
|
||||||
../common
|
../common
|
||||||
../io
|
../io
|
||||||
|
../ipc
|
||||||
../mt
|
../mt
|
||||||
../net
|
../net
|
||||||
../platform
|
../platform
|
||||||
|
@ -125,5 +126,5 @@ include_directories(${inc})
|
||||||
add_library(synergy STATIC ${src})
|
add_library(synergy STATIC ${src})
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(synergy arch client net base platform mt server)
|
target_link_libraries(synergy arch client ipc net base platform mt server)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -180,7 +180,7 @@ CIpcTests::sendMessageToClient_handleConnected(const CEvent& e, void*)
|
||||||
void
|
void
|
||||||
CIpcTests::sendMessageToClient_handleMessageReceived(const CEvent& e, void*)
|
CIpcTests::sendMessageToClient_handleMessageReceived(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
CIpcMessage* m = (CIpcMessage*)e.getData();
|
CIpcMessage* m = reinterpret_cast<CIpcMessage*>(e.getData());
|
||||||
m_sendMessageToClient_receivedString = *((CString*)m->m_data);
|
m_sendMessageToClient_receivedString = *((CString*)m->m_data);
|
||||||
raiseQuitEvent();
|
raiseQuitEvent();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue