Moved all IPC functions into the MUtilities libraries.
This commit is contained in:
parent
8b3e28a131
commit
563cc1c185
@ -24,6 +24,7 @@
|
||||
<ClCompile Include="src\Global.cpp" />
|
||||
<ClCompile Include="src\GUI.cpp" />
|
||||
<ClCompile Include="src\GUI_Win32.cpp" />
|
||||
<ClCompile Include="src\IPCChannel.cpp" />
|
||||
<ClCompile Include="src\JobObject_Win32.cpp" />
|
||||
<ClCompile Include="src\KeccakHash.cpp" />
|
||||
<ClCompile Include="src\OSSupport_Win32.cpp" />
|
||||
@ -39,6 +40,7 @@
|
||||
<ClInclude Include="include\MUtils\Exception.h" />
|
||||
<ClInclude Include="include\MUtils\Global.h" />
|
||||
<ClInclude Include="include\MUtils\GUI.h" />
|
||||
<ClInclude Include="include\MUtils\IPCChannel.h" />
|
||||
<ClInclude Include="include\MUtils\JobObject.h" />
|
||||
<ClInclude Include="include\MUtils\KeccakHash.h" />
|
||||
<ClInclude Include="include\MUtils\OSSupport.h" />
|
||||
|
@ -78,6 +78,9 @@
|
||||
<ClCompile Include="src\GUI_Win32.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\IPCChannel.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\CriticalSection_Win32.h">
|
||||
@ -131,6 +134,9 @@
|
||||
<ClInclude Include="include\MUtils\JobObject.h">
|
||||
<Filter>Public Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\MUtils\IPCChannel.h">
|
||||
<Filter>Public Headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="include\Mutils\UpdateChecker.h">
|
||||
|
58
include/MUtils/IPCChannel.h
Normal file
58
include/MUtils/IPCChannel.h
Normal file
@ -0,0 +1,58 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MuldeR's Utilities for Qt
|
||||
// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
// http://www.gnu.org/licenses/lgpl-2.1.txt
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <MUtils/Global.h>
|
||||
|
||||
namespace MUtils
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
IPC_RET_SUCCESS_MASTER = 0,
|
||||
IPC_RET_SUCCESS_SLAVE = 1,
|
||||
IPC_RET_ALREADY_INITIALIZED = 2,
|
||||
IPC_RET_FAILURE = 3
|
||||
}
|
||||
ipc_result_t;
|
||||
|
||||
class MUTILS_API IPCChannel_Private;
|
||||
|
||||
class MUTILS_API IPCChannel
|
||||
{
|
||||
public:
|
||||
IPCChannel(const QString &applicationId, const QString &channelId);
|
||||
~IPCChannel(void);
|
||||
|
||||
int initialize(void);
|
||||
|
||||
bool send(const unsigned int &command, const char *const message);
|
||||
bool read(unsigned int &command, char *const message, const size_t &buffSize);
|
||||
|
||||
private:
|
||||
IPCChannel(const IPCChannel&) : p(NULL) {}
|
||||
IPCChannel &operator=(const IPCChannel&) { return *this; }
|
||||
|
||||
IPCChannel_Private *const p;
|
||||
const QString m_applicationId;
|
||||
const QString m_channelId;
|
||||
};
|
||||
}
|
@ -22,7 +22,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <MUtils/Global.h>
|
||||
#include <QScopedPointer>
|
||||
|
||||
class QProcess;
|
||||
|
||||
@ -40,6 +39,6 @@ namespace MUtils
|
||||
bool terminateJob(unsigned int exitCode);
|
||||
|
||||
private:
|
||||
QScopedPointer<JobObject_Private> p;
|
||||
JobObject_Private *const p;
|
||||
};
|
||||
}
|
||||
|
337
src/IPCChannel.cpp
Normal file
337
src/IPCChannel.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MuldeR's Utilities for Qt
|
||||
// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
// http://www.gnu.org/licenses/lgpl-2.1.txt
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//MUtils
|
||||
#include <MUtils/IPCChannel.h>
|
||||
#include <MUtils/Exception.h>
|
||||
|
||||
//Qt includes
|
||||
#include <QRegExp>
|
||||
#include <QSharedMemory>
|
||||
#include <QSystemSemaphore>
|
||||
#include <QWriteLocker>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TYPES
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace MUtils
|
||||
{
|
||||
static const size_t IPC_SLOTS = 128;
|
||||
static const size_t MAX_MESSAGE_LEN = 4096;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int command;
|
||||
unsigned int reserved_1;
|
||||
unsigned int reserved_2;
|
||||
char parameter[MAX_MESSAGE_LEN];
|
||||
}
|
||||
ipc_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int pos_wr;
|
||||
unsigned int pos_rd;
|
||||
ipc_data_t data[IPC_SLOTS];
|
||||
}
|
||||
ipc_t;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTILITIES
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline QString ESCAPE(QString str)
|
||||
{
|
||||
return str.replace(QRegExp("[^A-Za-z0-9_]"), "_").toLower();
|
||||
}
|
||||
|
||||
static QString MAKE_ID(const QString &applicationId, const QString &channelId, const QString &itemId)
|
||||
{
|
||||
return QString("ipc://mutilities.muldersoft.com:37402/%1/%2/%3").arg(ESCAPE(applicationId), ESCAPE(channelId), ESCAPE(itemId));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE DATA
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace MUtils
|
||||
{
|
||||
class IPCChannel_Private
|
||||
{
|
||||
friend class IPCChannel;
|
||||
|
||||
protected:
|
||||
volatile bool initialized;
|
||||
QScopedPointer<QSharedMemory> sharedmem;
|
||||
QScopedPointer<QSystemSemaphore> semaphore_rd;
|
||||
QScopedPointer<QSystemSemaphore> semaphore_wr;
|
||||
QReadWriteLock lock;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTOR & DESTRUCTOR
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MUtils::IPCChannel::IPCChannel(const QString &applicationId, const QString &channelId)
|
||||
:
|
||||
p(new IPCChannel_Private()),
|
||||
m_applicationId(applicationId),
|
||||
m_channelId(channelId)
|
||||
{
|
||||
p->initialized = false;
|
||||
}
|
||||
|
||||
MUtils::IPCChannel::~IPCChannel(void)
|
||||
{
|
||||
if(p->initialized)
|
||||
{
|
||||
if(p->sharedmem->isAttached())
|
||||
{
|
||||
p->sharedmem->detach();
|
||||
}
|
||||
}
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// INITIALIZATION
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int MUtils::IPCChannel::initialize(void)
|
||||
{
|
||||
QWriteLocker writeLock(&p->lock);
|
||||
|
||||
if(p->initialized)
|
||||
{
|
||||
return IPC_RET_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
p->sharedmem.reset(new QSharedMemory(MAKE_ID(m_applicationId, m_channelId, "sharedmem"), NULL));
|
||||
p->semaphore_rd.reset(new QSystemSemaphore(MAKE_ID(m_applicationId, m_channelId, "semaphore_rd"), 0));
|
||||
p->semaphore_wr.reset(new QSystemSemaphore(MAKE_ID(m_applicationId, m_channelId, "semaphore_wr"), 0));
|
||||
|
||||
if(p->semaphore_rd->error() != QSystemSemaphore::NoError)
|
||||
{
|
||||
const QString errorMessage = p->semaphore_rd->errorString();
|
||||
qWarning("Failed to create system smaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
|
||||
if(p->semaphore_wr->error() != QSystemSemaphore::NoError)
|
||||
{
|
||||
const QString errorMessage = p->semaphore_wr->errorString();
|
||||
qWarning("Failed to create system smaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
|
||||
if(!p->sharedmem->create(sizeof(ipc_t)))
|
||||
{
|
||||
if(p->sharedmem->error() == QSharedMemory::AlreadyExists)
|
||||
{
|
||||
if(!p->sharedmem->attach())
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
if(p->sharedmem->error() != QSharedMemory::NoError)
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
p->initialized = true;
|
||||
return IPC_RET_SUCCESS_SLAVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if(p->sharedmem->error() != QSharedMemory::NoError)
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
|
||||
if(void *const data = p->sharedmem->data())
|
||||
{
|
||||
memset(data, 0, sizeof(ipc_t));
|
||||
}
|
||||
|
||||
if(!p->semaphore_wr->release(IPC_SLOTS))
|
||||
{
|
||||
const QString errorMessage = p->semaphore_wr->errorString();
|
||||
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return IPC_RET_FAILURE;
|
||||
}
|
||||
|
||||
p->initialized = true;
|
||||
return IPC_RET_SUCCESS_MASTER;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SEND MESSAGE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool MUtils::IPCChannel::send(const unsigned int &command, const char *const message)
|
||||
{
|
||||
bool success = false;
|
||||
QReadLocker readLock(&p->lock);
|
||||
|
||||
if(!p->initialized)
|
||||
{
|
||||
MUTILS_THROW("Shared memory for IPC not initialized yet.");
|
||||
}
|
||||
|
||||
ipc_data_t ipc_data;
|
||||
memset(&ipc_data, 0, sizeof(ipc_data_t));
|
||||
ipc_data.command = command;
|
||||
|
||||
if(message)
|
||||
{
|
||||
strncpy_s(ipc_data.parameter, MAX_MESSAGE_LEN, message, _TRUNCATE);
|
||||
}
|
||||
|
||||
if(!p->semaphore_wr->acquire())
|
||||
{
|
||||
const QString errorMessage = p->semaphore_wr->errorString();
|
||||
qWarning("Failed to acquire system semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!p->sharedmem->lock())
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to lock shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ipc_t *const ptr = reinterpret_cast<ipc_t*>(p->sharedmem->data()))
|
||||
{
|
||||
success = true;
|
||||
memcpy(&ptr->data[ptr->pos_wr], &ipc_data, sizeof(ipc_data_t));
|
||||
ptr->pos_wr = (ptr->pos_wr + 1) % IPC_SLOTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("Shared memory pointer is NULL -> unable to write data!");
|
||||
}
|
||||
|
||||
if(!p->sharedmem->unlock())
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!p->semaphore_rd->release())
|
||||
{
|
||||
const QString errorMessage = p->semaphore_rd->errorString();
|
||||
qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// READ MESSAGE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const size_t &buffSize)
|
||||
{
|
||||
bool success = false;
|
||||
QReadLocker readLock(&p->lock);
|
||||
|
||||
command = 0;
|
||||
if(message && (buffSize > 0))
|
||||
{
|
||||
message[0] = '\0';
|
||||
}
|
||||
|
||||
if(!p->initialized)
|
||||
{
|
||||
MUTILS_THROW("Shared memory for IPC not initialized yet.");
|
||||
}
|
||||
|
||||
ipc_data_t ipc_data;
|
||||
memset(&ipc_data, 0, sizeof(ipc_data_t));
|
||||
|
||||
if(!p->semaphore_rd->acquire())
|
||||
{
|
||||
const QString errorMessage = p->semaphore_rd->errorString();
|
||||
qWarning("Failed to acquire system semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!p->sharedmem->lock())
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to lock shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ipc_t *const ptr = reinterpret_cast<ipc_t*>(p->sharedmem->data()))
|
||||
{
|
||||
success = true;
|
||||
memcpy(&ipc_data, &ptr->data[ptr->pos_rd], sizeof(ipc_data_t));
|
||||
ptr->pos_rd = (ptr->pos_rd + 1) % IPC_SLOTS;
|
||||
|
||||
if(!(ipc_data.reserved_1 || ipc_data.reserved_2))
|
||||
{
|
||||
command = ipc_data.command;
|
||||
strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("Malformed IPC message, will be ignored");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("Shared memory pointer is NULL -> unable to write data!");
|
||||
}
|
||||
|
||||
if(!p->sharedmem->unlock())
|
||||
{
|
||||
const QString errorMessage = p->sharedmem->errorString();
|
||||
qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!p->semaphore_wr->release())
|
||||
{
|
||||
const QString errorMessage = p->semaphore_wr->errorString();
|
||||
qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
@ -84,6 +84,8 @@ MUtils::JobObject::~JobObject(void)
|
||||
CloseHandle(p->m_hJobObject);
|
||||
p->m_hJobObject = NULL;
|
||||
}
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
bool MUtils::JobObject::addProcessToJob(const QProcess *proc)
|
||||
|
Loading…
Reference in New Issue
Block a user