Various improvements to the IPCChannel class. Messages are now protected by Adler32 checksums.

This commit is contained in:
LoRd_MuldeR 2014-12-14 19:36:40 +01:00
parent 563cc1c185
commit 4385a2dfd9
8 changed files with 390 additions and 96 deletions

View File

@ -17,6 +17,7 @@
<ItemGroup>
<ClCompile Include="$(SolutionDir)\tmp\$(ProjectName)\QRC_Resource.cpp" />
<ClCompile Include="$(SolutionDir)\tmp\$(ProjectName)\MOC_UpdateChecker.cpp" />
<ClCompile Include="src\3rd_party\adler32\src\adler32.cpp" />
<ClCompile Include="src\3rd_party\strnatcmp\src\strnatcmp.cpp" />
<ClCompile Include="src\CPUFeatures_Win32.cpp" />
<ClCompile Include="src\DLLMain.cpp" />
@ -47,6 +48,7 @@
<ClInclude Include="include\MUtils\Sound.h" />
<ClInclude Include="include\MUtils\Startup.h" />
<ClInclude Include="include\MUtils\Terminal.h" />
<ClInclude Include="src\3rd_party\adler32\include\adler32.h" />
<ClInclude Include="src\3rd_party\keccak\include\keccak_impl.h" />
<ClInclude Include="src\3rd_party\strnatcmp\include\strnatcmp.h" />
<ClInclude Include="src\DirLocker.h" />

View File

@ -81,6 +81,9 @@
<ClCompile Include="src\IPCChannel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\3rd_party\adler32\src\adler32.cpp">
<Filter>Source Files\3rd Party</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CriticalSection_Win32.h">
@ -137,6 +140,9 @@
<ClInclude Include="include\MUtils\IPCChannel.h">
<Filter>Public Headers</Filter>
</ClInclude>
<ClInclude Include="src\3rd_party\adler32\include\adler32.h">
<Filter>Header Files\3rd Party</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="include\Mutils\UpdateChecker.h">

View File

@ -21,38 +21,47 @@
#pragma once
//MUtils
#include <MUtils/Global.h>
//Qt
#include <QtGlobal>
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);
static const size_t MAX_MESSAGE_LEN = 4096;
typedef enum
{
RET_SUCCESS_MASTER = 0,
RET_SUCCESS_SLAVE = 1,
RET_ALREADY_INITIALIZED = 2,
RET_FAILURE = 3
}
ipc_result_t;
IPCChannel(const QString &applicationId, const quint32 &versionNo, 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);
bool send(const quint32 &command, const quint32 &flags, const char *const message);
bool read(quint32 &command, quint32 &flags, char *const message, const size_t &buffSize);
private:
IPCChannel(const IPCChannel&) : p(NULL) {}
IPCChannel &operator=(const IPCChannel&) { return *this; }
IPCChannel(const IPCChannel&) : p(NULL), m_appVersionNo(-1) { throw "Constructor is disabled!"; }
IPCChannel &operator=(const IPCChannel&) { throw "Assignment operator is disabled!"; return *this; }
IPCChannel_Private *const p;
const QString m_applicationId;
const QString m_channelId;
const unsigned int m_appVersionNo;
const QByteArray m_headerStr;
IPCChannel_Private *const p;
};
}

25
src/3rd_party/adler32/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,25 @@
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).

52
src/3rd_party/adler32/include/adler32.h vendored Normal file
View File

@ -0,0 +1,52 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2011 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.8, April 28th, 2013
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
*/
#pragma once
#include <cstdlib>
#include <stdint.h>
namespace MUtils
{
namespace Internal
{
uint32_t adler32(uint32_t adler, const unsigned char *buf, uint32_t len);
inline uint32_t adler32(const uint32_t &adler, const void *const buf, const uint32_t &len)
{
return adler32(adler, reinterpret_cast<const unsigned char*>(buf), len);
}
}
}

135
src/3rd_party/adler32/src/adler32.cpp vendored Normal file
View File

@ -0,0 +1,135 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2011 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.8, April 28th, 2013
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
*/
#include "../include/adler32.h"
#define local static
#define uLong uint32_t
#define uInt uint32_t
#define Bytef unsigned char
#define z_off_t int32_t
#define z_off64_t int64_t
#define Z_NULL NULL
#define ZEXPORT
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#define BASE 65521 /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
#define MOD(a) a %= BASE
#define MOD28(a) a %= BASE
#define MOD63(a) a %= BASE
/* ========================================================================= */
uLong ZEXPORT MUtils::Internal::adler32(uLong adler, const Bytef *buf, uInt len)
{
unsigned long sum2;
unsigned n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD28(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}

View File

@ -43,29 +43,31 @@ misrepresented as being the original software.
#include "../include/strnatcmp.h"
typedef MUtils::Internal::NaturalSort::nat_char nat_char;
/* These are defined as macros to make it easier to adapt this code to
* different characters types or comparison functions. */
static inline int nat_isdigit(MUtils::Internal::NaturalSort::nat_char a)
static inline int nat_isdigit(nat_char a)
{
return iswdigit(a);
}
static inline int nat_isspace(MUtils::Internal::NaturalSort::nat_char a)
static inline int nat_isspace(nat_char a)
{
return iswspace(a);
}
static inline MUtils::Internal::NaturalSort::nat_char nat_isdecpoint(MUtils::Internal::NaturalSort::nat_char a)
static inline nat_char nat_isdecpoint(nat_char a)
{
return (a == L'.') || (a == L',');
}
static inline MUtils::Internal::NaturalSort::nat_char nat_toupper(MUtils::Internal::NaturalSort::nat_char a)
static inline nat_char nat_toupper(nat_char a)
{
return towupper(a);
}
static int compare_right(MUtils::Internal::NaturalSort::nat_char const *a, MUtils::Internal::NaturalSort::nat_char const *b)
static int compare_right(nat_char const *a, nat_char const *b)
{
int bias = 0;
@ -98,7 +100,7 @@ static int compare_right(MUtils::Internal::NaturalSort::nat_char const *a, MUtil
return 0;
}
static int compare_left(MUtils::Internal::NaturalSort::nat_char const *a, MUtils::Internal::NaturalSort::nat_char const *b)
static int compare_left(nat_char const *a,nat_char const *b)
{
/* Compare two left-aligned numbers: the first to have a
different value wins. */
@ -119,10 +121,10 @@ static int compare_left(MUtils::Internal::NaturalSort::nat_char const *a, MUtils
return 0;
}
static int strnatcmp0(MUtils::Internal::NaturalSort::nat_char const *a, MUtils::Internal::NaturalSort::nat_char const *b, const bool fold_case)
static int strnatcmp0(nat_char const *a, nat_char const *b, const bool fold_case)
{
int ai, bi;
MUtils::Internal::NaturalSort::nat_char ca, cb;
nat_char ca, cb;
int result;
bool fractional;
int sa, sb;

View File

@ -23,11 +23,21 @@
#include <MUtils/IPCChannel.h>
#include <MUtils/Exception.h>
//Internal
#include "3rd_party/adler32/include/adler32.h"
//Qt includes
#include <QRegExp>
#include <QSharedMemory>
#include <QSystemSemaphore>
#include <QMutex>
#include <QWriteLocker>
#include <QCryptographicHash>
//CRT
#include <cassert>
static const quint32 ADLER_SEED = 0x5D90C356;
///////////////////////////////////////////////////////////////////////////////
// TYPES
@ -35,39 +45,58 @@
namespace MUtils
{
namespace Internal
{
static const size_t HDR_LEN = 40;
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];
quint32 command_id;
quint32 flags;
char param[MUtils::IPCChannel::MAX_MESSAGE_LEN];
quint64 timestamp;
}
ipc_data_t;
typedef struct
{
unsigned int pos_wr;
unsigned int pos_rd;
ipc_data_t data[IPC_SLOTS];
ipc_data_t payload;
quint32 checksum;
}
ipc_msg_t;
typedef struct
{
char header[HDR_LEN];
quint64 counter;
quint32 pos_wr;
quint32 pos_rd;
ipc_msg_t data[IPC_SLOTS];
}
ipc_t;
}
}
///////////////////////////////////////////////////////////////////////////////
// UTILITIES
///////////////////////////////////////////////////////////////////////////////
static inline QString ESCAPE(QString str)
{
return str.replace(QRegExp("[^A-Za-z0-9_]"), "_").toLower();
}
static QScopedPointer<QRegExp> g_escape_regexp;
static QMutex g_escape_lock;
static QString MAKE_ID(const QString &applicationId, const QString &channelId, const QString &itemId)
#define ESCAPE(STR) (QString((STR)).replace(*g_escape_regexp, QLatin1String("_")).toLower())
static QString MAKE_ID(const QString &applicationId, const unsigned int &appVersionNo, const QString &channelId, const QString &itemId)
{
return QString("ipc://mutilities.muldersoft.com:37402/%1/%2/%3").arg(ESCAPE(applicationId), ESCAPE(channelId), ESCAPE(itemId));
QMutexLocker locker(&g_escape_lock);
if(g_escape_regexp.isNull())
{
g_escape_regexp.reset(new QRegExp(QLatin1String("[^A-Za-z0-9_\\-]")));
}
return QString("com.muldersoft.mutilities.ipc.%1.r%2.%3.%4").arg(ESCAPE(applicationId), QString::number(appVersionNo, 16).toUpper(), ESCAPE(channelId), ESCAPE(itemId));
}
///////////////////////////////////////////////////////////////////////////////
@ -93,12 +122,15 @@ namespace MUtils
// CONSTRUCTOR & DESTRUCTOR
///////////////////////////////////////////////////////////////////////////////
MUtils::IPCChannel::IPCChannel(const QString &applicationId, const QString &channelId)
MUtils::IPCChannel::IPCChannel(const QString &applicationId, const quint32 &appVersionNo, const QString &channelId)
:
p(new IPCChannel_Private()),
m_applicationId(applicationId),
m_channelId(channelId)
m_channelId(channelId),
m_appVersionNo(appVersionNo),
m_headerStr(QCryptographicHash::hash(MAKE_ID(applicationId, appVersionNo, channelId, "header").toLatin1(), QCryptographicHash::Sha1).toHex())
{
assert(m_headerStr.length() == HDR_LEN);
p->initialized = false;
}
@ -125,28 +157,28 @@ int MUtils::IPCChannel::initialize(void)
if(p->initialized)
{
return IPC_RET_ALREADY_INITIALIZED;
return 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));
p->sharedmem. reset(new QSharedMemory (MAKE_ID(m_applicationId, m_appVersionNo, m_channelId, "sharedmem"), 0));
p->semaphore_rd.reset(new QSystemSemaphore(MAKE_ID(m_applicationId, m_appVersionNo, m_channelId, "semaph_rd"), 0));
p->semaphore_wr.reset(new QSystemSemaphore(MAKE_ID(m_applicationId, m_appVersionNo, m_channelId, "semaph_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;
return 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;
return RET_FAILURE;
}
if(!p->sharedmem->create(sizeof(ipc_t)))
if(!p->sharedmem->create(sizeof(Internal::ipc_t)))
{
if(p->sharedmem->error() == QSharedMemory::AlreadyExists)
{
@ -154,22 +186,41 @@ int MUtils::IPCChannel::initialize(void)
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
return IPC_RET_FAILURE;
return 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;
return RET_FAILURE;
}
if(p->sharedmem->size() < sizeof(Internal::ipc_t))
{
qWarning("Failed to attach to shared memory: Size verification has failed!");
return RET_FAILURE;
}
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{
if(memcmp(&ptr->header[0], m_headerStr.constData(), Internal::HDR_LEN) != 0)
{
qWarning("Failed to attach to shared memory: Header verification has failed!");
return RET_FAILURE;
}
}
else
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to access shared memory: %s", MUTILS_UTF8(errorMessage));
return RET_FAILURE;
}
p->initialized = true;
return IPC_RET_SUCCESS_SLAVE;
return RET_SUCCESS_SLAVE;
}
else
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
return IPC_RET_FAILURE;
return RET_FAILURE;
}
}
@ -177,30 +228,41 @@ int MUtils::IPCChannel::initialize(void)
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
return IPC_RET_FAILURE;
return RET_FAILURE;
}
if(void *const data = p->sharedmem->data())
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{
memset(data, 0, sizeof(ipc_t));
memset(ptr, 0, sizeof(Internal::ipc_t));
memcpy(&ptr->header[0], m_headerStr.constData(), Internal::HDR_LEN);
}
else
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to access shared memory: %s", MUTILS_UTF8(errorMessage));
return RET_FAILURE;
}
if(!p->semaphore_wr->release(IPC_SLOTS))
if(!p->semaphore_wr->release(Internal::IPC_SLOTS))
{
const QString errorMessage = p->semaphore_wr->errorString();
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
return IPC_RET_FAILURE;
return RET_FAILURE;
}
//qDebug("IPC KEY #1: %s", MUTILS_UTF8(p->sharedmem->key()));
//qDebug("IPC KEY #2: %s", MUTILS_UTF8(p->semaphore_rd->key()));
//qDebug("IPC KEY #3: %s", MUTILS_UTF8(p->semaphore_wr->key()));
p->initialized = true;
return IPC_RET_SUCCESS_MASTER;
return RET_SUCCESS_MASTER;
}
///////////////////////////////////////////////////////////////////////////////
// SEND MESSAGE
///////////////////////////////////////////////////////////////////////////////
bool MUtils::IPCChannel::send(const unsigned int &command, const char *const message)
bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, const char *const message)
{
bool success = false;
QReadLocker readLock(&p->lock);
@ -210,15 +272,6 @@ bool MUtils::IPCChannel::send(const unsigned int &command, const char *const mes
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();
@ -233,11 +286,23 @@ bool MUtils::IPCChannel::send(const unsigned int &command, const char *const mes
return false;
}
if(ipc_t *const ptr = reinterpret_cast<ipc_t*>(p->sharedmem->data()))
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{
Internal::ipc_msg_t ipc_msg;
memset(&ipc_msg, 0, sizeof(Internal::ipc_msg_t));
ipc_msg.payload.command_id = command;
ipc_msg.payload.flags = flags;
if(message)
{
strncpy_s(ipc_msg.payload.param, MAX_MESSAGE_LEN, message, _TRUNCATE);
}
ipc_msg.payload.timestamp = ptr->counter++;
ipc_msg.checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_data_t));
memcpy(&ptr->data[ptr->pos_wr], &ipc_msg, sizeof(Internal::ipc_msg_t));
ptr->pos_wr = (ptr->pos_wr + 1) % Internal::IPC_SLOTS;
success = true;
memcpy(&ptr->data[ptr->pos_wr], &ipc_data, sizeof(ipc_data_t));
ptr->pos_wr = (ptr->pos_wr + 1) % IPC_SLOTS;
}
else
{
@ -247,15 +312,13 @@ bool MUtils::IPCChannel::send(const unsigned int &command, const char *const mes
if(!p->sharedmem->unlock())
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
return false;
qFatal("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
}
if(!p->semaphore_rd->release())
{
const QString errorMessage = p->semaphore_rd->errorString();
qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
return false;
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
}
return success;
@ -265,7 +328,7 @@ bool MUtils::IPCChannel::send(const unsigned int &command, const char *const mes
// READ MESSAGE
///////////////////////////////////////////////////////////////////////////////
bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const size_t &buffSize)
bool MUtils::IPCChannel::read(quint32 &command, quint32 &flags, char *const message, const size_t &buffSize)
{
bool success = false;
QReadLocker readLock(&p->lock);
@ -281,8 +344,8 @@ bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const
MUTILS_THROW("Shared memory for IPC not initialized yet.");
}
ipc_data_t ipc_data;
memset(&ipc_data, 0, sizeof(ipc_data_t));
Internal::ipc_msg_t ipc_msg;
memset(&ipc_msg, 0, sizeof(Internal::ipc_msg_t));
if(!p->semaphore_rd->acquire())
{
@ -298,20 +361,22 @@ bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const
return false;
}
if(ipc_t *const ptr = reinterpret_cast<ipc_t*>(p->sharedmem->data()))
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::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;
memcpy(&ipc_msg, &ptr->data[ptr->pos_rd], sizeof(Internal::ipc_msg_t));
ptr->pos_rd = (ptr->pos_rd + 1) % Internal::IPC_SLOTS;
if(!(ipc_data.reserved_1 || ipc_data.reserved_2))
const quint32 expected_checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_data_t));
if((expected_checksum == ipc_msg.checksum) || (ipc_msg.payload.timestamp < ptr->counter))
{
command = ipc_data.command;
strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
command = ipc_msg.payload.command_id;
flags = ipc_msg.payload.flags;
strncpy_s(message, buffSize, ipc_msg.payload.param, _TRUNCATE);
}
else
{
qWarning("Malformed IPC message, will be ignored");
qWarning("Malformed or corrupted IPC message, will be ignored");
}
}
else
@ -322,15 +387,13 @@ bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const
if(!p->sharedmem->unlock())
{
const QString errorMessage = p->sharedmem->errorString();
qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
return false;
qFatal("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
}
if(!p->semaphore_wr->release())
{
const QString errorMessage = p->semaphore_wr->errorString();
qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
return false;
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
}
return success;