///////////////////////////////////////////////////////////////////////////////
// MuldeR's Utilities for Qt
-// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+// Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include <QMutex>
#include <QWriteLocker>
#include <QCryptographicHash>
-
+#include <QStringList>
//CRT
#include <cassert>
-static const quint32 ADLER_SEED = 0x5D90C356;
+///////////////////////////////////////////////////////////////////////////////
+// UTILITIES
+///////////////////////////////////////////////////////////////////////////////
+
+namespace MUtils
+{
+ namespace Internal
+ {
+ static const quint32 ADLER_SEED = 0x5D90C356;
+
+ template<class T>
+ static inline void UPDATE_CHECKSUM(T &data)
+ {
+ data.checksum = Internal::adler32(ADLER_SEED, &data.payload, sizeof(data.payload));
+ }
+
+ template<class T>
+ static inline bool VERIFY_CHECKSUM(const T &data)
+ {
+ return (data.checksum == Internal::adler32(ADLER_SEED, &data.payload, sizeof(data.payload)));
+ }
+ }
+}
///////////////////////////////////////////////////////////////////////////////
// TYPES
typedef struct
{
- quint32 command_id;
- quint32 flags;
- char param[MUtils::IPCChannel::MAX_MESSAGE_LEN];
- quint64 timestamp;
+ char values[MUtils::IPCChannel::MAX_PARAM_CNT][MUtils::IPCChannel::MAX_PARAM_LEN];
+ quint32 count;
+ }
+ ipc_msg_data_params_t;
+
+ typedef struct
+ {
+ quint32 command_id;
+ quint32 flags;
+ ipc_msg_data_params_t params;
+ quint64 timestamp;
}
ipc_msg_data_t;
friend class IPCChannel;
protected:
- volatile bool initialized;
+ QAtomicInt initialized;
QScopedPointer<QSharedMemory> sharedmem;
QScopedPointer<QSystemSemaphore> semaphore_rd;
QScopedPointer<QSystemSemaphore> semaphore_wr;
m_appVersionNo(appVersionNo),
m_headerStr(QCryptographicHash::hash(MAKE_ID(applicationId, appVersionNo, channelId, "header").toLatin1(), QCryptographicHash::Sha1).toHex())
{
- p->initialized = false;
if(m_headerStr.length() != Internal::HDR_LEN)
{
MUTILS_THROW("Invalid header length has been detected!");
MUtils::IPCChannel::~IPCChannel(void)
{
- if(p->initialized)
+ if(MUTILS_BOOLIFY(p->initialized))
{
if(p->sharedmem->isAttached())
{
{
QWriteLocker writeLock(&p->lock);
- if(p->initialized)
+ if(MUTILS_BOOLIFY(p->initialized))
{
return RET_ALREADY_INITIALIZED;
}
qWarning("Failed to access shared memory: %s", MUTILS_UTF8(errorMessage));
return RET_FAILURE;
}
- p->initialized = true;
+ p->initialized.ref();
return RET_SUCCESS_SLAVE;
}
else
{
memset(ptr, 0, sizeof(Internal::ipc_t));
memcpy(&ptr->header[0], m_headerStr.constData(), Internal::HDR_LEN);
- ptr->status.checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
+ UPDATE_CHECKSUM(ptr->status);
}
else
{
//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.ref();
return RET_SUCCESS_MASTER;
}
// SEND MESSAGE
///////////////////////////////////////////////////////////////////////////////
-bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, const char *const message)
+bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, const QStringList ¶ms)
{
bool success = false;
QReadLocker readLock(&p->lock);
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{
- const quint32 status_checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
- if(status_checksum == ptr->status.checksum)
+ if(VERIFY_CHECKSUM(ptr->status))
{
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)
+ if(!params.isEmpty())
{
- strncpy_s(ipc_msg.payload.param, MAX_MESSAGE_LEN, message, _TRUNCATE);
+ const quint32 param_count = qMin(MAX_PARAM_CNT, (quint32)params.count());
+ for(quint32 i = 0; i < param_count; i++)
+ {
+ strncpy_s(ipc_msg.payload.params.values[i], MAX_PARAM_LEN, MUTILS_UTF8(params[i].trimmed()), _TRUNCATE);
+ }
+ ipc_msg.payload.params.count = param_count;
}
ipc_msg.payload.timestamp = ptr->status.payload.counter++;
- ipc_msg.checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_msg_data_t));
+ UPDATE_CHECKSUM(ipc_msg);
memcpy(&ptr->data[ptr->status.payload.pos_wr], &ipc_msg, sizeof(Internal::ipc_msg_t));
ptr->status.payload.pos_wr = (ptr->status.payload.pos_wr + 1) % Internal::IPC_SLOTS;
- ptr->status.checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
+ UPDATE_CHECKSUM(ptr->status);
success = true;
}
// READ MESSAGE
///////////////////////////////////////////////////////////////////////////////
-bool MUtils::IPCChannel::read(quint32 &command, quint32 &flags, char *const message, const size_t &buffSize)
+bool MUtils::IPCChannel::read(quint32 &command, quint32 &flags, QStringList ¶ms)
{
bool success = false;
QReadLocker readLock(&p->lock);
-
command = 0;
- if(message && (buffSize > 0))
- {
- message[0] = '\0';
- }
-
+ params.clear();
+
if(!p->initialized)
{
MUTILS_THROW("Shared memory for IPC not initialized yet.");
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{
- const quint32 status_checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
- if(status_checksum == ptr->status.checksum)
+ if(VERIFY_CHECKSUM(ptr->status))
{
memcpy(&ipc_msg, &ptr->data[ptr->status.payload.pos_rd], sizeof(Internal::ipc_msg_t));
ptr->status.payload.pos_rd = (ptr->status.payload.pos_rd + 1) % Internal::IPC_SLOTS;
- ptr->status.checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
+ UPDATE_CHECKSUM(ptr->status);
- const quint32 msg_checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_msg_data_t));
- if((msg_checksum == ipc_msg.checksum) || (ipc_msg.payload.timestamp < ptr->status.payload.counter))
+ if(VERIFY_CHECKSUM(ipc_msg) || (ipc_msg.payload.timestamp < ptr->status.payload.counter))
{
command = ipc_msg.payload.command_id;
flags = ipc_msg.payload.flags;
- strncpy_s(message, buffSize, ipc_msg.payload.param, _TRUNCATE);
+ const quint32 param_count = qMin(ipc_msg.payload.params.count, MAX_PARAM_CNT);
+ char temp[MAX_PARAM_LEN];
+ for(quint32 i = 0; i < param_count; i++)
+ {
+ strncpy_s(temp, MAX_PARAM_LEN, ipc_msg.payload.params.values[i], _TRUNCATE);
+ params.append(QString::fromUtf8(temp));
+ }
success = true;
}
else