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>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(SolutionDir)\tmp\$(ProjectName)\QRC_Resource.cpp" />
|
<ClCompile Include="$(SolutionDir)\tmp\$(ProjectName)\QRC_Resource.cpp" />
|
||||||
<ClCompile Include="$(SolutionDir)\tmp\$(ProjectName)\MOC_UpdateChecker.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\3rd_party\strnatcmp\src\strnatcmp.cpp" />
|
||||||
<ClCompile Include="src\CPUFeatures_Win32.cpp" />
|
<ClCompile Include="src\CPUFeatures_Win32.cpp" />
|
||||||
<ClCompile Include="src\DLLMain.cpp" />
|
<ClCompile Include="src\DLLMain.cpp" />
|
||||||
@ -47,6 +48,7 @@
|
|||||||
<ClInclude Include="include\MUtils\Sound.h" />
|
<ClInclude Include="include\MUtils\Sound.h" />
|
||||||
<ClInclude Include="include\MUtils\Startup.h" />
|
<ClInclude Include="include\MUtils\Startup.h" />
|
||||||
<ClInclude Include="include\MUtils\Terminal.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\keccak\include\keccak_impl.h" />
|
||||||
<ClInclude Include="src\3rd_party\strnatcmp\include\strnatcmp.h" />
|
<ClInclude Include="src\3rd_party\strnatcmp\include\strnatcmp.h" />
|
||||||
<ClInclude Include="src\DirLocker.h" />
|
<ClInclude Include="src\DirLocker.h" />
|
||||||
|
@ -81,6 +81,9 @@
|
|||||||
<ClCompile Include="src\IPCChannel.cpp">
|
<ClCompile Include="src\IPCChannel.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\3rd_party\adler32\src\adler32.cpp">
|
||||||
|
<Filter>Source Files\3rd Party</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\CriticalSection_Win32.h">
|
<ClInclude Include="src\CriticalSection_Win32.h">
|
||||||
@ -137,6 +140,9 @@
|
|||||||
<ClInclude Include="include\MUtils\IPCChannel.h">
|
<ClInclude Include="include\MUtils\IPCChannel.h">
|
||||||
<Filter>Public Headers</Filter>
|
<Filter>Public Headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\3rd_party\adler32\include\adler32.h">
|
||||||
|
<Filter>Header Files\3rd Party</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="include\Mutils\UpdateChecker.h">
|
<CustomBuild Include="include\Mutils\UpdateChecker.h">
|
||||||
|
@ -21,38 +21,47 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
//MUtils
|
||||||
#include <MUtils/Global.h>
|
#include <MUtils/Global.h>
|
||||||
|
|
||||||
|
//Qt
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
namespace MUtils
|
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_Private;
|
||||||
|
|
||||||
class MUTILS_API IPCChannel
|
class MUTILS_API IPCChannel
|
||||||
{
|
{
|
||||||
public:
|
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);
|
~IPCChannel(void);
|
||||||
|
|
||||||
int initialize(void);
|
int initialize(void);
|
||||||
|
|
||||||
bool send(const unsigned int &command, const char *const message);
|
bool send(const quint32 &command, const quint32 &flags, const char *const message);
|
||||||
bool read(unsigned int &command, char *const message, const size_t &buffSize);
|
bool read(quint32 &command, quint32 &flags, char *const message, const size_t &buffSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IPCChannel(const IPCChannel&) : p(NULL) {}
|
IPCChannel(const IPCChannel&) : p(NULL), m_appVersionNo(-1) { throw "Constructor is disabled!"; }
|
||||||
IPCChannel &operator=(const IPCChannel&) { return *this; }
|
IPCChannel &operator=(const IPCChannel&) { throw "Assignment operator is disabled!"; return *this; }
|
||||||
|
|
||||||
IPCChannel_Private *const p;
|
|
||||||
const QString m_applicationId;
|
const QString m_applicationId;
|
||||||
const QString m_channelId;
|
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"
|
#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
|
/* These are defined as macros to make it easier to adapt this code to
|
||||||
* different characters types or comparison functions. */
|
* 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);
|
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);
|
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',');
|
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);
|
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;
|
int bias = 0;
|
||||||
|
|
||||||
@ -98,7 +100,7 @@ static int compare_right(MUtils::Internal::NaturalSort::nat_char const *a, MUtil
|
|||||||
return 0;
|
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
|
/* Compare two left-aligned numbers: the first to have a
|
||||||
different value wins. */
|
different value wins. */
|
||||||
@ -119,10 +121,10 @@ static int compare_left(MUtils::Internal::NaturalSort::nat_char const *a, MUtils
|
|||||||
return 0;
|
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;
|
int ai, bi;
|
||||||
MUtils::Internal::NaturalSort::nat_char ca, cb;
|
nat_char ca, cb;
|
||||||
int result;
|
int result;
|
||||||
bool fractional;
|
bool fractional;
|
||||||
int sa, sb;
|
int sa, sb;
|
||||||
|
@ -23,11 +23,21 @@
|
|||||||
#include <MUtils/IPCChannel.h>
|
#include <MUtils/IPCChannel.h>
|
||||||
#include <MUtils/Exception.h>
|
#include <MUtils/Exception.h>
|
||||||
|
|
||||||
|
//Internal
|
||||||
|
#include "3rd_party/adler32/include/adler32.h"
|
||||||
|
|
||||||
//Qt includes
|
//Qt includes
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QSharedMemory>
|
#include <QSharedMemory>
|
||||||
#include <QSystemSemaphore>
|
#include <QSystemSemaphore>
|
||||||
|
#include <QMutex>
|
||||||
#include <QWriteLocker>
|
#include <QWriteLocker>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
//CRT
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
static const quint32 ADLER_SEED = 0x5D90C356;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// TYPES
|
// TYPES
|
||||||
@ -35,39 +45,58 @@
|
|||||||
|
|
||||||
namespace MUtils
|
namespace MUtils
|
||||||
{
|
{
|
||||||
static const size_t IPC_SLOTS = 128;
|
namespace Internal
|
||||||
static const size_t MAX_MESSAGE_LEN = 4096;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
unsigned int command;
|
static const size_t HDR_LEN = 40;
|
||||||
unsigned int reserved_1;
|
static const size_t IPC_SLOTS = 128;
|
||||||
unsigned int reserved_2;
|
|
||||||
char parameter[MAX_MESSAGE_LEN];
|
|
||||||
}
|
|
||||||
ipc_data_t;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned int pos_wr;
|
quint32 command_id;
|
||||||
unsigned int pos_rd;
|
quint32 flags;
|
||||||
ipc_data_t data[IPC_SLOTS];
|
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
|
// UTILITIES
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static inline QString ESCAPE(QString str)
|
static QScopedPointer<QRegExp> g_escape_regexp;
|
||||||
{
|
static QMutex g_escape_lock;
|
||||||
return str.replace(QRegExp("[^A-Za-z0-9_]"), "_").toLower();
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
// 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()),
|
p(new IPCChannel_Private()),
|
||||||
m_applicationId(applicationId),
|
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;
|
p->initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,28 +157,28 @@ int MUtils::IPCChannel::initialize(void)
|
|||||||
|
|
||||||
if(p->initialized)
|
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->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_channelId, "semaphore_rd"), 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_channelId, "semaphore_wr"), 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)
|
if(p->semaphore_rd->error() != QSystemSemaphore::NoError)
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->semaphore_rd->errorString();
|
const QString errorMessage = p->semaphore_rd->errorString();
|
||||||
qWarning("Failed to create system smaphore: %s", MUTILS_UTF8(errorMessage));
|
qWarning("Failed to create system smaphore: %s", MUTILS_UTF8(errorMessage));
|
||||||
return IPC_RET_FAILURE;
|
return RET_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p->semaphore_wr->error() != QSystemSemaphore::NoError)
|
if(p->semaphore_wr->error() != QSystemSemaphore::NoError)
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->semaphore_wr->errorString();
|
const QString errorMessage = p->semaphore_wr->errorString();
|
||||||
qWarning("Failed to create system smaphore: %s", MUTILS_UTF8(errorMessage));
|
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)
|
if(p->sharedmem->error() == QSharedMemory::AlreadyExists)
|
||||||
{
|
{
|
||||||
@ -154,22 +186,41 @@ int MUtils::IPCChannel::initialize(void)
|
|||||||
{
|
{
|
||||||
const QString errorMessage = p->sharedmem->errorString();
|
const QString errorMessage = p->sharedmem->errorString();
|
||||||
qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
|
qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||||
return IPC_RET_FAILURE;
|
return RET_FAILURE;
|
||||||
}
|
}
|
||||||
if(p->sharedmem->error() != QSharedMemory::NoError)
|
if(p->sharedmem->error() != QSharedMemory::NoError)
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->sharedmem->errorString();
|
const QString errorMessage = p->sharedmem->errorString();
|
||||||
qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
|
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;
|
p->initialized = true;
|
||||||
return IPC_RET_SUCCESS_SLAVE;
|
return RET_SUCCESS_SLAVE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->sharedmem->errorString();
|
const QString errorMessage = p->sharedmem->errorString();
|
||||||
qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
|
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();
|
const QString errorMessage = p->sharedmem->errorString();
|
||||||
qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
|
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();
|
const QString errorMessage = p->semaphore_wr->errorString();
|
||||||
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
|
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;
|
p->initialized = true;
|
||||||
return IPC_RET_SUCCESS_MASTER;
|
return RET_SUCCESS_MASTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// SEND MESSAGE
|
// 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;
|
bool success = false;
|
||||||
QReadLocker readLock(&p->lock);
|
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.");
|
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())
|
if(!p->semaphore_wr->acquire())
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->semaphore_wr->errorString();
|
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;
|
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;
|
success = true;
|
||||||
memcpy(&ptr->data[ptr->pos_wr], &ipc_data, sizeof(ipc_data_t));
|
|
||||||
ptr->pos_wr = (ptr->pos_wr + 1) % IPC_SLOTS;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -247,15 +312,13 @@ bool MUtils::IPCChannel::send(const unsigned int &command, const char *const mes
|
|||||||
if(!p->sharedmem->unlock())
|
if(!p->sharedmem->unlock())
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->sharedmem->errorString();
|
const QString errorMessage = p->sharedmem->errorString();
|
||||||
qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
|
qFatal("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!p->semaphore_rd->release())
|
if(!p->semaphore_rd->release())
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->semaphore_rd->errorString();
|
const QString errorMessage = p->semaphore_rd->errorString();
|
||||||
qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
|
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -265,7 +328,7 @@ bool MUtils::IPCChannel::send(const unsigned int &command, const char *const mes
|
|||||||
// READ MESSAGE
|
// 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;
|
bool success = false;
|
||||||
QReadLocker readLock(&p->lock);
|
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.");
|
MUTILS_THROW("Shared memory for IPC not initialized yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc_data_t ipc_data;
|
Internal::ipc_msg_t ipc_msg;
|
||||||
memset(&ipc_data, 0, sizeof(ipc_data_t));
|
memset(&ipc_msg, 0, sizeof(Internal::ipc_msg_t));
|
||||||
|
|
||||||
if(!p->semaphore_rd->acquire())
|
if(!p->semaphore_rd->acquire())
|
||||||
{
|
{
|
||||||
@ -298,20 +361,22 @@ bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const
|
|||||||
return false;
|
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;
|
success = true;
|
||||||
memcpy(&ipc_data, &ptr->data[ptr->pos_rd], sizeof(ipc_data_t));
|
memcpy(&ipc_msg, &ptr->data[ptr->pos_rd], sizeof(Internal::ipc_msg_t));
|
||||||
ptr->pos_rd = (ptr->pos_rd + 1) % IPC_SLOTS;
|
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;
|
command = ipc_msg.payload.command_id;
|
||||||
strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
|
flags = ipc_msg.payload.flags;
|
||||||
|
strncpy_s(message, buffSize, ipc_msg.payload.param, _TRUNCATE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qWarning("Malformed IPC message, will be ignored");
|
qWarning("Malformed or corrupted IPC message, will be ignored");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -322,15 +387,13 @@ bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const
|
|||||||
if(!p->sharedmem->unlock())
|
if(!p->sharedmem->unlock())
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->sharedmem->errorString();
|
const QString errorMessage = p->sharedmem->errorString();
|
||||||
qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
|
qFatal("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!p->semaphore_wr->release())
|
if(!p->semaphore_wr->release())
|
||||||
{
|
{
|
||||||
const QString errorMessage = p->semaphore_wr->errorString();
|
const QString errorMessage = p->semaphore_wr->errorString();
|
||||||
qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
|
qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
Loading…
Reference in New Issue
Block a user