ripped out rest of shitty named pipes ipc stuff.

fixed the byte to int reader on the gui ipc (unsigned chars, argh!!!).
retry on fail for gui ipc connect.
This commit is contained in:
Nick Bolton 2012-07-04 23:27:03 +00:00
parent a8ce3418fe
commit 4e268760b3
11 changed files with 84 additions and 264 deletions

View File

@ -36,7 +36,6 @@ 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/IpcClient.cpp src/IpcClient.cpp
HEADERS += src/MainWindow.h \ HEADERS += src/MainWindow.h \
src/AboutDialog.h \ src/AboutDialog.h \
@ -60,7 +59,6 @@ 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/IpcClient.h src/IpcClient.h
RESOURCES += res/Synergy.qrc RESOURCES += res/Synergy.qrc
RC_FILE = res/win/Synergy.rc RC_FILE = res/win/Synergy.rc

View File

@ -19,6 +19,7 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QHostAddress> #include <QHostAddress>
#include <iostream> #include <iostream>
#include <QTimer>
IpcClient::IpcClient() IpcClient::IpcClient()
{ {
@ -33,6 +34,7 @@ IpcClient::~IpcClient()
void IpcClient::connectToHost() void IpcClient::connectToHost()
{ {
infoMessage("connecting to background service...");
m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), IPC_PORT); m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), IPC_PORT);
} }
@ -47,28 +49,19 @@ void IpcClient::read()
switch (codeBuf[0]) { switch (codeBuf[0]) {
case kIpcLogLine: { case kIpcLogLine: {
// TODO: qt must have a built in way of converting bytes to int.
char lenBuf[2]; char lenBuf[2];
stream.readRawData(lenBuf, 2); stream.readRawData(lenBuf, 2);
int len = (lenBuf[0] << 8) + lenBuf[1]; int len = bytesToInt(lenBuf, 2);
// HACK: sometimes the size is wrong (probably a bug in the above code) char* data = new char[len];
// but the following text always seems to be valid, so just read a large stream.readRawData(data, len);
// amount from the buffer and put a \0 at the end if the number looks
// valid (ugh, this sucks).
char* data = new char[1024];
stream.readRawData(data, 1024);
if (len > -1) {
data[len] = '\0';
}
QString s = QString::fromUtf8(data); readLogLine(QString::fromUtf8(data, len));
readLogLine(s);
} }
break; break;
default: { default: {
std::cerr << "invalid code: " << codeBuf[0] << std::endl; std::cout << "invalid code: " << codeBuf[0] << std::endl;
} }
break; break;
} }
@ -77,7 +70,16 @@ void IpcClient::read()
void IpcClient::error(QAbstractSocket::SocketError error) void IpcClient::error(QAbstractSocket::SocketError error)
{ {
errorMessage(QString("ERROR: could not connect to background service, code=%1").arg(error)); QString text;
switch (error) {
case 0: text = "connection refused"; break;
case 1: text = "remote host closed"; break;
default: text = QString("code=%1").arg(error); break;
}
errorMessage(QString("ipc connection error, %1").arg(text));
QTimer::singleShot(1000, this, SLOT(connectToHost()));
} }
void IpcClient::write(unsigned char code, unsigned char length, const char* data) void IpcClient::write(unsigned char code, unsigned char length, const char* data)
@ -90,14 +92,36 @@ void IpcClient::write(unsigned char code, unsigned char length, const char* data
switch (code) { switch (code) {
case kIpcCommand: { case kIpcCommand: {
// TODO: qt must have a built in way of converting int to bytes.
char lenBuf[2]; char lenBuf[2];
lenBuf[0] = (length >> 8) & 0xff; intToBytes(length, lenBuf, 2);
lenBuf[1] = length & 0xff;
stream.writeRawData(lenBuf, 2); stream.writeRawData(lenBuf, 2);
stream.writeRawData(data, length); stream.writeRawData(data, length);
} }
break; break;
} }
} }
// TODO: qt must have a built in way of converting bytes to int.
int IpcClient::bytesToInt(const char *buffer, int size)
{
if (size == 2) {
return (((unsigned char)buffer[0]) << 8)
+ (unsigned char)buffer[1];
}
else {
// TODO: other sizes, if needed.
return 0;
}
}
// TODO: qt must have a built in way of converting int to bytes.
void IpcClient::intToBytes(int value, char *buffer, int size)
{
if (size == 2) {
buffer[0] = (value >> 8) & 0xff;
buffer[1] = value & 0xff;
}
else {
// TODO: other sizes, if needed.
}
}

View File

@ -32,15 +32,22 @@ public:
IpcClient(); IpcClient();
virtual ~IpcClient(); virtual ~IpcClient();
void connectToHost();
void write(unsigned char code, unsigned char length, const char* data); void write(unsigned char code, unsigned char length, const char* data);
public slots:
void connectToHost();
private:
int bytesToInt(const char* buffer, int size);
void intToBytes(int value, char* buffer, int size);
private slots: private slots:
void read(); void read();
void error(QAbstractSocket::SocketError error); void error(QAbstractSocket::SocketError error);
signals: signals:
void readLogLine(const QString& text); void readLogLine(const QString& text);
void infoMessage(const QString& text);
void errorMessage(const QString& text); void errorMessage(const QString& text);
private: private:

View File

@ -1,67 +0,0 @@
/*
* 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 "IpcLogReader.h"
#if defined(Q_OS_WIN)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
IpcLogReader::IpcLogReader()
{
}
IpcLogReader::~IpcLogReader()
{
}
void
IpcLogReader::run()
{
#if defined(Q_OS_WIN)
const WCHAR* name = L"\\\\.\\pipe\\SynergyLog";
HANDLE pipe = CreateFile(
name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
receivedLine(
QString("ERROR: could not connect to service log, error: ") +
QString::number(GetLastError()));
return;
}
char buffer[1024];
DWORD bytesRead;
while (true)
{
if (!ReadFile(pipe, buffer, sizeof(buffer), &bytesRead, NULL)) {
break;
}
buffer[bytesRead] = '\0';
QString text = QString::fromAscii(buffer, bytesRead);
text = text.trimmed().append("\n");
receivedLine(text);
}
#endif
}

View File

@ -1,32 +0,0 @@
/*
* 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/>.
*/
#pragma once
#include <QThread>
#include <string>
class IpcLogReader : public QThread
{
Q_OBJECT
public:
IpcLogReader();
virtual ~IpcLogReader();
void run();
signals:
void receivedLine(const QString& text);
};

View File

@ -90,10 +90,10 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
if (appConfig.processMode() == Service) if (appConfig.processMode() == Service)
{ {
connect(&m_IpcClient, SIGNAL(readLogLine(const QString&)), this, SLOT(appendLog(const QString&))); connect(&m_IpcClient, SIGNAL(readLogLine(const QString&)), this, SLOT(appendLogRaw(const QString&)));
connect(&m_IpcClient, SIGNAL(errorMessage(const QString&)), this, SLOT(appendLog(const QString&))); connect(&m_IpcClient, SIGNAL(errorMessage(const QString&)), this, SLOT(appendLogError(const QString&)));
connect(&m_IpcClient, SIGNAL(infoMessage(const QString&)), this, SLOT(appendLogInfo(const QString&)));
m_IpcClient.connectToHost(); m_IpcClient.connectToHost();
appendLog("INFO: connecting to background service...");
} }
} }
@ -260,7 +260,7 @@ void MainWindow::logOutput()
{ {
if (!line.isEmpty()) if (!line.isEmpty())
{ {
appendLog(line); appendLogRaw(line);
if (line.contains("has connected") || if (line.contains("has connected") ||
line.contains("connected to server")) line.contains("connected to server"))
{ {
@ -285,7 +285,7 @@ void MainWindow::logError()
{ {
if (m_pSynergy) if (m_pSynergy)
{ {
appendLog(m_pSynergy->readAllStandardError()); appendLogRaw(m_pSynergy->readAllStandardError());
} }
} }
@ -298,7 +298,17 @@ void MainWindow::updateFound(const QString &version)
.arg(version).arg("http://synergy-foss.org")); .arg(version).arg("http://synergy-foss.org"));
} }
void MainWindow::appendLog(const QString& text) void MainWindow::appendLogInfo(const QString& text)
{
appendLogRaw("INFO: " + text);
}
void MainWindow::appendLogError(const QString& text)
{
appendLogRaw("ERROR: " + text);
}
void MainWindow::appendLogRaw(const QString& text)
{ {
foreach(QString line, text.split(QRegExp("\r|\n|\r\n"))) foreach(QString line, text.split(QRegExp("\r|\n|\r\n")))
if (!line.isEmpty()) if (!line.isEmpty())
@ -379,28 +389,28 @@ void MainWindow::startSynergy()
// put a space between last log output and new instance. // put a space between last log output and new instance.
if (!m_pLogOutput->toPlainText().isEmpty()) if (!m_pLogOutput->toPlainText().isEmpty())
appendLog(""); appendLogRaw("");
if (desktopMode) if (desktopMode)
{ {
appendLog("starting " + QString(synergyType() == synergyServer ? "server" : "client")); appendLogInfo("starting " + QString(synergyType() == synergyServer ? "server" : "client"));
} }
if (serviceMode) if (serviceMode)
{ {
appendLog("applying service mode: " + QString(synergyType() == synergyServer ? "server" : "client")); appendLogInfo("applying service mode: " + QString(synergyType() == synergyServer ? "server" : "client"));
} }
// show command if debug log level... // show command if debug log level...
if (appConfig().logLevel() >= 4) { if (appConfig().logLevel() >= 4) {
appendLog(QString("command: %1 %2").arg(app, args.join(" "))); appendLogInfo(QString("command: %1 %2").arg(app, args.join(" ")));
} }
appendLog("config file: " + configFilename()); appendLogInfo("config file: " + configFilename());
appendLog("log level: " + appConfig().logLevelText()); appendLogInfo("log level: " + appConfig().logLevelText());
if (appConfig().logToFile()) if (appConfig().logToFile())
appendLog("log file: " + appConfig().logFilename()); appendLogInfo("log file: " + appConfig().logFilename());
if (desktopMode) if (desktopMode)
{ {
@ -523,7 +533,7 @@ void MainWindow::stopSynergy()
{ {
if (synergyProcess()) if (synergyProcess())
{ {
appendLog("stopping synergy"); appendLogInfo("stopping synergy");
if (synergyProcess()->isOpen()) if (synergyProcess()->isOpen())
synergyProcess()->close(); synergyProcess()->close();

View File

@ -73,6 +73,11 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
Command = 1 Command = 1
}; };
enum qLevel {
Error,
Info
};
public: public:
MainWindow(QSettings& settings, AppConfig& appConfig); MainWindow(QSettings& settings, AppConfig& appConfig);
~MainWindow(); ~MainWindow();
@ -89,7 +94,9 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void clearLog(); void clearLog();
public slots: public slots:
void appendLog(const QString& text); void appendLogRaw(const QString& text);
void appendLogInfo(const QString& text);
void appendLogError(const QString& text);
protected slots: protected slots:
void on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); } void on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); }

View File

@ -419,8 +419,6 @@ CMSWindowsRelauncher::shutdownProcess(const PROCESS_INFORMATION& pi, int timeout
if (exitCode != STILL_ACTIVE) if (exitCode != STILL_ACTIVE)
return; return;
sendIpcMessage(kIpcShutdown, "");
// wait for process to exit gracefully. // wait for process to exit gracefully.
double start = ARCH->time(); double start = ARCH->time();
while (true) while (true)
@ -446,45 +444,3 @@ CMSWindowsRelauncher::shutdownProcess(const PROCESS_INFORMATION& pi, int timeout
} }
} }
} }
// TODO: put this in an IPC client class.
void
CMSWindowsRelauncher::sendIpcMessage(int type, const char* data)
{
char message[1024];
message[0] = type;
char* messagePtr = message;
messagePtr++;
strcpy(messagePtr, data);
HANDLE pipe = CreateFile(
_T("\\\\.\\pipe\\SynergyNode"),
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
LOG((CLOG_ERR "could not connect to node, error: %d", GetLastError()));
return;
}
DWORD dwMode = PIPE_READMODE_MESSAGE;
BOOL stateSuccess = SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
if (!stateSuccess)
{
LOG((CLOG_ERR "could not set node pipe state, error: %d", GetLastError()));
return;
}
DWORD written;
BOOL writeSuccess = WriteFile(
pipe, message, (DWORD)strlen(message), &written, NULL);
if (!writeSuccess)
{
LOG((CLOG_ERR "could not write to node pipe, error: %d", GetLastError()));
return;
}
CloseHandle(pipe);
}

View File

@ -40,7 +40,6 @@ private:
DWORD getSessionId(); DWORD getSessionId();
HANDLE getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security); HANDLE getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security);
void outputLoop(void*); void outputLoop(void*);
void sendIpcMessage(int type, const char* data);
void shutdownProcess(const PROCESS_INFORMATION& pi, int timeout); void shutdownProcess(const PROCESS_INFORMATION& pi, int timeout);
public: public:

View File

@ -317,11 +317,6 @@ CApp::initApp(int argc, const char** argv)
// parse command line // parse command line
parseArgs(argc, argv); parseArgs(argc, argv);
#if SYSAPI_WIN32
CThread pipeThread(new TMethodJob<CApp>(
this, &CApp::pipeThread, nullptr));
#endif
// setup file logging after parsing args // setup file logging after parsing args
setupFileLogging(); setupFileLogging();
@ -340,71 +335,3 @@ CApp::initApp(int argc, const char** argv)
m_taskBarReceiver = m_createTaskBarReceiver(logBuffer); m_taskBarReceiver = m_createTaskBarReceiver(logBuffer);
} }
} }
#ifdef SYSAPI_WIN32
void
CApp::pipeThread(void*)
{
// TODO: move this to an IPC server class.
while (true) {
// 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(
_T("\\\\.\\pipe\\SynergyNode"),
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 node 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 node server read: %s", buffer));
handlePipeMessage(buffer);
}
DisconnectNamedPipe(pipe);
CloseHandle(pipe);
}
}
void
CApp::handlePipeMessage(char* buffer)
{
switch (buffer[0]) {
case kIpcShutdown:
{
LOG((CLOG_INFO "queueing quit event"));
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
break;
default:
LOG((CLOG_WARN "unrecognized ipc message: %d", buffer[0]));
break;
}
}
#endif

View File

@ -105,11 +105,6 @@ private:
CFileLogOutputter* m_fileLog; CFileLogOutputter* m_fileLog;
CreateTaskBarReceiverFunc m_createTaskBarReceiver; CreateTaskBarReceiverFunc m_createTaskBarReceiver;
ARCH_APP_UTIL m_appUtil; ARCH_APP_UTIL m_appUtil;
#if SYSAPI_WIN32
void pipeThread(void*);
void handlePipeMessage(char* buffer);
#endif
}; };
#define BYE "\nTry `%s --help' for more information." #define BYE "\nTry `%s --help' for more information."
@ -176,7 +171,3 @@ private:
HELP_GAME_DEVICE HELP_GAME_DEVICE
#endif #endif
enum {
kIpcShutdown = 1
};