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

View File

@ -19,6 +19,7 @@
#include <QTcpSocket>
#include <QHostAddress>
#include <iostream>
#include <QTimer>
IpcClient::IpcClient()
{
@ -33,6 +34,7 @@ IpcClient::~IpcClient()
void IpcClient::connectToHost()
{
infoMessage("connecting to background service...");
m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), IPC_PORT);
}
@ -47,28 +49,19 @@ void IpcClient::read()
switch (codeBuf[0]) {
case kIpcLogLine: {
// TODO: qt must have a built in way of converting bytes to int.
char 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)
// but the following text always seems to be valid, so just read a large
// 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';
}
char* data = new char[len];
stream.readRawData(data, len);
QString s = QString::fromUtf8(data);
readLogLine(s);
readLogLine(QString::fromUtf8(data, len));
}
break;
default: {
std::cerr << "invalid code: " << codeBuf[0] << std::endl;
default: {
std::cout << "invalid code: " << codeBuf[0] << std::endl;
}
break;
}
@ -77,7 +70,16 @@ void IpcClient::read()
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)
@ -90,14 +92,36 @@ void IpcClient::write(unsigned char code, unsigned char length, const char* data
switch (code) {
case kIpcCommand: {
// TODO: qt must have a built in way of converting int to bytes.
char lenBuf[2];
lenBuf[0] = (length >> 8) & 0xff;
lenBuf[1] = length & 0xff;
intToBytes(length, lenBuf, 2);
stream.writeRawData(lenBuf, 2);
stream.writeRawData(data, length);
}
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();
virtual ~IpcClient();
void connectToHost();
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:
void read();
void error(QAbstractSocket::SocketError error);
signals:
void readLogLine(const QString& text);
void infoMessage(const QString& text);
void errorMessage(const QString& text);
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)
{
connect(&m_IpcClient, SIGNAL(readLogLine(const QString&)), this, SLOT(appendLog(const QString&)));
connect(&m_IpcClient, SIGNAL(errorMessage(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(appendLogError(const QString&)));
connect(&m_IpcClient, SIGNAL(infoMessage(const QString&)), this, SLOT(appendLogInfo(const QString&)));
m_IpcClient.connectToHost();
appendLog("INFO: connecting to background service...");
}
}
@ -260,7 +260,7 @@ void MainWindow::logOutput()
{
if (!line.isEmpty())
{
appendLog(line);
appendLogRaw(line);
if (line.contains("has connected") ||
line.contains("connected to server"))
{
@ -285,7 +285,7 @@ void MainWindow::logError()
{
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"));
}
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")))
if (!line.isEmpty())
@ -379,28 +389,28 @@ void MainWindow::startSynergy()
// put a space between last log output and new instance.
if (!m_pLogOutput->toPlainText().isEmpty())
appendLog("");
appendLogRaw("");
if (desktopMode)
{
appendLog("starting " + QString(synergyType() == synergyServer ? "server" : "client"));
appendLogInfo("starting " + QString(synergyType() == synergyServer ? "server" : "client"));
}
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...
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());
appendLog("log level: " + appConfig().logLevelText());
appendLogInfo("config file: " + configFilename());
appendLogInfo("log level: " + appConfig().logLevelText());
if (appConfig().logToFile())
appendLog("log file: " + appConfig().logFilename());
appendLogInfo("log file: " + appConfig().logFilename());
if (desktopMode)
{
@ -523,7 +533,7 @@ void MainWindow::stopSynergy()
{
if (synergyProcess())
{
appendLog("stopping synergy");
appendLogInfo("stopping synergy");
if (synergyProcess()->isOpen())
synergyProcess()->close();

View File

@ -73,6 +73,11 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
Command = 1
};
enum qLevel {
Error,
Info
};
public:
MainWindow(QSettings& settings, AppConfig& appConfig);
~MainWindow();
@ -89,7 +94,9 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void clearLog();
public slots:
void appendLog(const QString& text);
void appendLogRaw(const QString& text);
void appendLogInfo(const QString& text);
void appendLogError(const QString& text);
protected slots:
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)
return;
sendIpcMessage(kIpcShutdown, "");
// wait for process to exit gracefully.
double start = ARCH->time();
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();
HANDLE getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security);
void outputLoop(void*);
void sendIpcMessage(int type, const char* data);
void shutdownProcess(const PROCESS_INFORMATION& pi, int timeout);
public:

View File

@ -317,11 +317,6 @@ CApp::initApp(int argc, const char** argv)
// parse command line
parseArgs(argc, argv);
#if SYSAPI_WIN32
CThread pipeThread(new TMethodJob<CApp>(
this, &CApp::pipeThread, nullptr));
#endif
// setup file logging after parsing args
setupFileLogging();
@ -340,71 +335,3 @@ CApp::initApp(int argc, const char** argv)
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;
CreateTaskBarReceiverFunc m_createTaskBarReceiver;
ARCH_APP_UTIL m_appUtil;
#if SYSAPI_WIN32
void pipeThread(void*);
void handlePipeMessage(char* buffer);
#endif
};
#define BYE "\nTry `%s --help' for more information."
@ -176,7 +171,3 @@ private:
HELP_GAME_DEVICE
#endif
enum {
kIpcShutdown = 1
};