OSDN Git Service

Code refactoring.
[mutilities/MUtilities.git] / src / IPCChannel.cpp
index 403c21c..1192e68 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // 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
@@ -67,10 +89,17 @@ namespace MUtils
 
                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;
 
@@ -123,7 +152,7 @@ namespace MUtils
                friend class IPCChannel;
 
        protected:
-               volatile bool initialized;
+               QAtomicInt initialized;
                QScopedPointer<QSharedMemory> sharedmem;
                QScopedPointer<QSystemSemaphore> semaphore_rd;
                QScopedPointer<QSystemSemaphore> semaphore_wr;
@@ -143,7 +172,6 @@ MUtils::IPCChannel::IPCChannel(const QString &applicationId, const quint32 &appV
        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!");
@@ -152,7 +180,7 @@ MUtils::IPCChannel::IPCChannel(const QString &applicationId, const quint32 &appV
 
 MUtils::IPCChannel::~IPCChannel(void)
 {
-       if(p->initialized)
+       if(MUTILS_BOOLIFY(p->initialized))
        {
                if(p->sharedmem->isAttached())
                {
@@ -171,7 +199,7 @@ int MUtils::IPCChannel::initialize(void)
 {
        QWriteLocker writeLock(&p->lock);
        
-       if(p->initialized)
+       if(MUTILS_BOOLIFY(p->initialized))
        {
                return RET_ALREADY_INITIALIZED;
        }
@@ -229,7 +257,7 @@ int MUtils::IPCChannel::initialize(void)
                                qWarning("Failed to access shared memory: %s", MUTILS_UTF8(errorMessage));
                                return RET_FAILURE;
                        }
-                       p->initialized = true;
+                       p->initialized.ref();
                        return RET_SUCCESS_SLAVE;
                }
                else
@@ -251,7 +279,7 @@ int MUtils::IPCChannel::initialize(void)
        {
                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
        {
@@ -271,7 +299,7 @@ int MUtils::IPCChannel::initialize(void)
        //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;
 }
 
@@ -279,7 +307,7 @@ int MUtils::IPCChannel::initialize(void)
 // 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 &params)
 {
        bool success = false;
        QReadLocker readLock(&p->lock);
@@ -305,24 +333,28 @@ bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, cons
 
        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;
                }
@@ -355,17 +387,13 @@ bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, cons
 // 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 &params)
 {
        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.");
@@ -390,19 +418,23 @@ bool MUtils::IPCChannel::read(quint32 &command, quint32 &flags, char *const mess
 
        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