Various improvements to the IPCChannel class. Messages are now protected by Adler32 checksums.
This commit is contained in:
parent
563cc1c185
commit
4385a2dfd9
@ -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" />
|
||||
|
@ -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">
|
||||
|
@ -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
25
src/3rd_party/adler32/LICENSE.txt
vendored
Normal 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
52
src/3rd_party/adler32/include/adler32.h
vendored
Normal 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
135
src/3rd_party/adler32/src/adler32.cpp
vendored
Normal 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);
|
||||
}
|
18
src/3rd_party/strnatcmp/src/strnatcmp.cpp
vendored
18
src/3rd_party/strnatcmp/src/strnatcmp.cpp
vendored
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
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<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;
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user