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;