OSDN Git Service

Moved all IPC functions into the MUtilities libraries.
authorLoRd_MuldeR <mulder2@gmx.de>
Sat, 13 Dec 2014 22:21:13 +0000 (23:21 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Sat, 13 Dec 2014 22:21:13 +0000 (23:21 +0100)
MUtilities_VS2013.vcxproj
MUtilities_VS2013.vcxproj.filters
include/MUtils/IPCChannel.h [new file with mode: 0644]
include/MUtils/JobObject.h
src/IPCChannel.cpp [new file with mode: 0644]
src/JobObject_Win32.cpp

index a1f9d34..a0fab79 100644 (file)
@@ -24,6 +24,7 @@
     <ClCompile Include="src\Global.cpp" />
     <ClCompile Include="src\GUI.cpp" />
     <ClCompile Include="src\GUI_Win32.cpp" />
+    <ClCompile Include="src\IPCChannel.cpp" />
     <ClCompile Include="src\JobObject_Win32.cpp" />
     <ClCompile Include="src\KeccakHash.cpp" />
     <ClCompile Include="src\OSSupport_Win32.cpp" />
@@ -39,6 +40,7 @@
     <ClInclude Include="include\MUtils\Exception.h" />
     <ClInclude Include="include\MUtils\Global.h" />
     <ClInclude Include="include\MUtils\GUI.h" />
+    <ClInclude Include="include\MUtils\IPCChannel.h" />
     <ClInclude Include="include\MUtils\JobObject.h" />
     <ClInclude Include="include\MUtils\KeccakHash.h" />
     <ClInclude Include="include\MUtils\OSSupport.h" />
index 272fdb4..657655d 100644 (file)
@@ -78,6 +78,9 @@
     <ClCompile Include="src\GUI_Win32.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\IPCChannel.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\CriticalSection_Win32.h">
     <ClInclude Include="include\MUtils\JobObject.h">
       <Filter>Public Headers</Filter>
     </ClInclude>
+    <ClInclude Include="include\MUtils\IPCChannel.h">
+      <Filter>Public Headers</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
diff --git a/include/MUtils/IPCChannel.h b/include/MUtils/IPCChannel.h
new file mode 100644 (file)
index 0000000..a175bca
--- /dev/null
@@ -0,0 +1,58 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// http://www.gnu.org/licenses/lgpl-2.1.txt
+//////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <MUtils/Global.h>
+
+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);
+               ~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);
+
+       private:
+               IPCChannel(const IPCChannel&) : p(NULL) {}
+               IPCChannel &operator=(const IPCChannel&) { return *this; }
+
+               IPCChannel_Private *const p;
+               const QString m_applicationId;
+               const QString m_channelId;
+       };
+}
index 62fb4be..b6b47ad 100644 (file)
@@ -22,7 +22,6 @@
 #pragma once
 
 #include <MUtils/Global.h>
-#include <QScopedPointer>
 
 class QProcess;
 
@@ -40,6 +39,6 @@ namespace MUtils
                bool terminateJob(unsigned int exitCode);
 
        private:
-               QScopedPointer<JobObject_Private> p;
+               JobObject_Private *const p;
        };
 }
diff --git a/src/IPCChannel.cpp b/src/IPCChannel.cpp
new file mode 100644 (file)
index 0000000..9aab938
--- /dev/null
@@ -0,0 +1,337 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// http://www.gnu.org/licenses/lgpl-2.1.txt
+//////////////////////////////////////////////////////////////////////////////////
+
+//MUtils
+#include <MUtils/IPCChannel.h>
+#include <MUtils/Exception.h>
+
+//Qt includes
+#include <QRegExp>
+#include <QSharedMemory>
+#include <QSystemSemaphore>
+#include <QWriteLocker>
+
+///////////////////////////////////////////////////////////////////////////////
+// TYPES
+///////////////////////////////////////////////////////////////////////////////
+
+namespace MUtils
+{
+       static const size_t IPC_SLOTS = 128;
+       static const size_t MAX_MESSAGE_LEN = 4096;
+
+       typedef struct
+       {
+               unsigned int command;
+               unsigned int reserved_1;
+               unsigned int reserved_2;
+               char parameter[MAX_MESSAGE_LEN];
+       }
+       ipc_data_t;
+
+       typedef struct
+       {
+               unsigned int pos_wr;
+               unsigned int pos_rd;
+               ipc_data_t data[IPC_SLOTS];
+       }
+       ipc_t;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// UTILITIES
+///////////////////////////////////////////////////////////////////////////////
+
+static inline QString ESCAPE(QString str)
+{
+       return str.replace(QRegExp("[^A-Za-z0-9_]"), "_").toLower();
+}
+
+static QString MAKE_ID(const QString &applicationId, const QString &channelId, const QString &itemId)
+{
+       return QString("ipc://mutilities.muldersoft.com:37402/%1/%2/%3").arg(ESCAPE(applicationId), ESCAPE(channelId), ESCAPE(itemId));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PRIVATE DATA
+///////////////////////////////////////////////////////////////////////////////
+
+namespace MUtils
+{
+       class IPCChannel_Private
+       {
+               friend class IPCChannel;
+
+       protected:
+               volatile bool initialized;
+               QScopedPointer<QSharedMemory> sharedmem;
+               QScopedPointer<QSystemSemaphore> semaphore_rd;
+               QScopedPointer<QSystemSemaphore> semaphore_wr;
+               QReadWriteLock lock;
+       };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CONSTRUCTOR & DESTRUCTOR
+///////////////////////////////////////////////////////////////////////////////
+
+MUtils::IPCChannel::IPCChannel(const QString &applicationId, const QString &channelId)
+:
+       p(new IPCChannel_Private()),
+       m_applicationId(applicationId),
+       m_channelId(channelId)
+{
+       p->initialized = false;
+}
+
+MUtils::IPCChannel::~IPCChannel(void)
+{
+       if(p->initialized)
+       {
+               if(p->sharedmem->isAttached())
+               {
+                       p->sharedmem->detach();
+               }
+       }
+
+       delete p;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+///////////////////////////////////////////////////////////////////////////////
+
+int MUtils::IPCChannel::initialize(void)
+{
+       QWriteLocker writeLock(&p->lock);
+       
+       if(p->initialized)
+       {
+               return IPC_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));
+
+       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;
+       }
+
+       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;
+       }
+       
+       if(!p->sharedmem->create(sizeof(ipc_t)))
+       {
+               if(p->sharedmem->error() == QSharedMemory::AlreadyExists)
+               {
+                       if(!p->sharedmem->attach())
+                       {
+                               const QString errorMessage = p->sharedmem->errorString();
+                               qWarning("Failed to attach to shared memory: %s", MUTILS_UTF8(errorMessage));
+                               return IPC_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;
+                       }
+                       p->initialized = true;
+                       return IPC_RET_SUCCESS_SLAVE;
+               }
+               else
+               {
+                       const QString errorMessage = p->sharedmem->errorString();
+                       qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
+                       return IPC_RET_FAILURE;
+               }
+       }
+       
+       if(p->sharedmem->error() != QSharedMemory::NoError)
+       {
+               const QString errorMessage = p->sharedmem->errorString();
+               qWarning("Failed to create shared memory: %s", MUTILS_UTF8(errorMessage));
+               return IPC_RET_FAILURE;
+       }
+
+       if(void *const data = p->sharedmem->data())
+       {
+               memset(data, 0, sizeof(ipc_t));
+       }
+
+       if(!p->semaphore_wr->release(IPC_SLOTS))
+       {
+               const QString errorMessage = p->semaphore_wr->errorString();
+               qWarning("Failed to release system semaphore: %s", MUTILS_UTF8(errorMessage));
+               return IPC_RET_FAILURE;
+       }
+       
+       p->initialized = true;
+       return IPC_RET_SUCCESS_MASTER;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SEND MESSAGE
+///////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::IPCChannel::send(const unsigned int &command, const char *const message)
+{
+       bool success = false;
+       QReadLocker readLock(&p->lock);
+
+       if(!p->initialized)
+       {
+               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();
+               qWarning("Failed to acquire system semaphore: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       if(!p->sharedmem->lock())
+       {
+               const QString errorMessage = p->sharedmem->errorString();
+               qWarning("Failed to lock shared memory: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       if(ipc_t *const ptr = reinterpret_cast<ipc_t*>(p->sharedmem->data()))
+       {
+               success = true;
+               memcpy(&ptr->data[ptr->pos_wr], &ipc_data, sizeof(ipc_data_t));
+               ptr->pos_wr = (ptr->pos_wr + 1) % IPC_SLOTS;
+       }
+       else
+       {
+               qWarning("Shared memory pointer is NULL -> unable to write data!");
+       }
+
+       if(!p->sharedmem->unlock())
+       {
+               const QString errorMessage = p->sharedmem->errorString();
+               qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       if(!p->semaphore_rd->release())
+       {
+               const QString errorMessage = p->semaphore_rd->errorString();
+               qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       return success;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// READ MESSAGE
+///////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::IPCChannel::read(unsigned int &command, char *const message, const size_t &buffSize)
+{
+       bool success = false;
+       QReadLocker readLock(&p->lock);
+       
+       command = 0;
+       if(message && (buffSize > 0))
+       {
+               message[0] = '\0';
+       }
+       
+       if(!p->initialized)
+       {
+               MUTILS_THROW("Shared memory for IPC not initialized yet.");
+       }
+
+       ipc_data_t ipc_data;
+       memset(&ipc_data, 0, sizeof(ipc_data_t));
+
+       if(!p->semaphore_rd->acquire())
+       {
+               const QString errorMessage = p->semaphore_rd->errorString();
+               qWarning("Failed to acquire system semaphore: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       if(!p->sharedmem->lock())
+       {
+               const QString errorMessage = p->sharedmem->errorString();
+               qWarning("Failed to lock shared memory: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       if(ipc_t *const ptr = reinterpret_cast<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;
+
+               if(!(ipc_data.reserved_1 || ipc_data.reserved_2))
+               {
+                       command = ipc_data.command;
+                       strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
+               }
+               else
+               {
+                       qWarning("Malformed IPC message, will be ignored");
+               }
+       }
+       else
+       {
+               qWarning("Shared memory pointer is NULL -> unable to write data!");
+       }
+
+       if(!p->sharedmem->unlock())
+       {
+               const QString errorMessage = p->sharedmem->errorString();
+               qWarning("Failed to unlock shared memory: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       if(!p->semaphore_wr->release())
+       {
+               const QString errorMessage = p->semaphore_wr->errorString();
+               qWarning("Failed to acquire release semaphore: %s", MUTILS_UTF8(errorMessage));
+               return false;
+       }
+
+       return success;
+}
index 51c1295..b39a54a 100644 (file)
@@ -84,6 +84,8 @@ MUtils::JobObject::~JobObject(void)
                CloseHandle(p->m_hJobObject);
                p->m_hJobObject = NULL;
        }
+
+       delete p;
 }
 
 bool MUtils::JobObject::addProcessToJob(const QProcess *proc)