diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj
index a0fab79..36ba503 100644
--- a/MUtilities_VS2013.vcxproj
+++ b/MUtilities_VS2013.vcxproj
@@ -17,6 +17,7 @@
+
@@ -47,6 +48,7 @@
+
diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters
index 657655d..2b0c53f 100644
--- a/MUtilities_VS2013.vcxproj.filters
+++ b/MUtilities_VS2013.vcxproj.filters
@@ -81,6 +81,9 @@
Source Files
+
+ Source Files\3rd Party
+
@@ -137,6 +140,9 @@
Public Headers
+
+ Header Files\3rd Party
+
diff --git a/include/MUtils/IPCChannel.h b/include/MUtils/IPCChannel.h
index a175bca..2c7b8dc 100644
--- a/include/MUtils/IPCChannel.h
+++ b/include/MUtils/IPCChannel.h
@@ -21,38 +21,47 @@
#pragma once
+//MUtils
#include
+//Qt
+#include
+
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;
};
}
diff --git a/src/3rd_party/adler32/LICENSE.txt b/src/3rd_party/adler32/LICENSE.txt
new file mode 100644
index 0000000..71b54b7
--- /dev/null
+++ b/src/3rd_party/adler32/LICENSE.txt
@@ -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).
diff --git a/src/3rd_party/adler32/include/adler32.h b/src/3rd_party/adler32/include/adler32.h
new file mode 100644
index 0000000..12a5271
--- /dev/null
+++ b/src/3rd_party/adler32/include/adler32.h
@@ -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
+#include
+
+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(buf), len);
+ }
+ }
+}
diff --git a/src/3rd_party/adler32/src/adler32.cpp b/src/3rd_party/adler32/src/adler32.cpp
new file mode 100644
index 0000000..c7d10b1
--- /dev/null
+++ b/src/3rd_party/adler32/src/adler32.cpp
@@ -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);
+}
diff --git a/src/3rd_party/strnatcmp/src/strnatcmp.cpp b/src/3rd_party/strnatcmp/src/strnatcmp.cpp
index 60ca371..813a69f 100644
--- a/src/3rd_party/strnatcmp/src/strnatcmp.cpp
+++ b/src/3rd_party/strnatcmp/src/strnatcmp.cpp
@@ -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;
diff --git a/src/IPCChannel.cpp b/src/IPCChannel.cpp
index 9aab938..d73189b 100644
--- a/src/IPCChannel.cpp
+++ b/src/IPCChannel.cpp
@@ -23,11 +23,21 @@
#include
#include
+//Internal
+#include "3rd_party/adler32/include/adler32.h"
+
//Qt includes
#include
#include
#include
+#include
#include
+#include
+
+//CRT
+#include
+
+static const quint32 ADLER_SEED = 0x5D90C356;
///////////////////////////////////////////////////////////////////////////////
// TYPES
@@ -35,39 +45,58 @@
namespace MUtils
{
- static const size_t IPC_SLOTS = 128;
- static const size_t MAX_MESSAGE_LEN = 4096;
-
- typedef struct
+ namespace Internal
{
- unsigned int command;
- unsigned int reserved_1;
- unsigned int reserved_2;
- char parameter[MAX_MESSAGE_LEN];
- }
- ipc_data_t;
+ static const size_t HDR_LEN = 40;
+ static const size_t IPC_SLOTS = 128;
- typedef struct
- {
- unsigned int pos_wr;
- unsigned int pos_rd;
- ipc_data_t data[IPC_SLOTS];
+ typedef struct
+ {
+ quint32 command_id;
+ quint32 flags;
+ char param[MUtils::IPCChannel::MAX_MESSAGE_LEN];
+ quint64 timestamp;
+ }
+ ipc_data_t;
+
+ typedef struct
+ {
+ 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;
}
- ipc_t;
}
///////////////////////////////////////////////////////////////////////////////
// UTILITIES
///////////////////////////////////////////////////////////////////////////////
-static inline QString ESCAPE(QString str)
-{
- return str.replace(QRegExp("[^A-Za-z0-9_]"), "_").toLower();
-}
+static QScopedPointer 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(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(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(p->sharedmem->data()))
+ if(Internal::ipc_t *const ptr = reinterpret_cast(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(p->sharedmem->data()))
+ if(Internal::ipc_t *const ptr = reinterpret_cast(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;
+ success = true;
+ 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;