diff options
Diffstat (limited to 'Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp')
| -rw-r--r-- | Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp | 577 |
1 files changed, 577 insertions, 0 deletions
diff --git a/Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp b/Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp new file mode 100644 index 0000000..4697aef --- /dev/null +++ b/Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp @@ -0,0 +1,577 @@ +/*!
+ * \file CPluginExecutor.cpp
+ * \author S. Eisenhauer
+ * \date 27.10.2011
+ * \brief Implementation of CPluginExecutor
+ */
+#include "CPluginExecutor.h"
+#include <dlfcn.h>
+#include <boost/bind.hpp>
+#include "global.h"
+#include <x2e/CAN.hpp>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include <dirent.h>
+#include "protocol.h"
+
+#define nAUTOLOAD_FILENAME "autoload_plugins"
+#define nSEPARATOR ","
+
+static tstPluginConfig g_astPluginConfigList[nNUMBER_OF_CAN_INTERFACES];
+
+CPluginExecutor::CPluginExecutor( )
+:m_u8PluginCounter(0)
+,m_xTcpServer(this,g_xIoService,nPORT)
+,m_xConnector(this,m_xTcpServer)
+,m_xConnectorThread(m_xConnector)
+,m_pxLogPlugin(NULL)
+{
+ int res = 0;
+ int schedulerPolicy = SCHED_RR;
+ sched_param sp;
+ sp.sched_priority = tenPrio::nenNORMAL; // rt priority
+
+ tenRetCodes enRetVal = enAutoLoadPlugins();
+ if( enRetVal != nenOK )
+ {
+ ERROR_PRINT("error auto loading plugins: %d",enRetVal);
+ exit(1);
+ }
+
+ if( (res = pthread_setschedparam(m_xConnectorThread.native_handle(), schedulerPolicy, &sp)) != 0 )
+ {
+ ERROR_PRINT("pthread_setschedparam failed: %d errno: %d",res,errno);
+ }
+ if( (res = pthread_getschedparam(m_xConnectorThread.native_handle(),&schedulerPolicy,&sp)) != 0 )
+ {
+ ERROR_PRINT("pthread_getschedparam failed: %d errno: %d",res,errno);
+ }
+ else
+ {
+ DEBUG_PRINT("network IO thread prio: %d scheduler: %s"
+ ,sp.sched_priority
+ ,(schedulerPolicy==SCHED_OTHER)?"SCHED_OTHER":
+ (schedulerPolicy==SCHED_FIFO)?"SCHED_FIFO":
+ (schedulerPolicy==SCHED_RR)?"SCHED_RR":"other");
+ }
+}
+
+CPluginExecutor::~CPluginExecutor()
+{
+ DEBUG_PRINT("entry");
+ DEBUG_PRINT("exit");
+}
+
+tenRetCodes CPluginExecutor::enAddPlugin( const char* pcSoFilename, const int32_t i32Interface, uint8_t& u8PluginId )
+{
+ tenRetCodes enRetCode = nenOK;
+ if( i32Interface != nALL_CAN_INTERFACES )
+ {
+ {
+ boost::lock_guard<x2e::Mutex> lock(m_xPluginListMutex);
+ if( findPluginByInterface(i32Interface) != m_astPluginConfig.end() )
+ {
+ enRetCode = enRemovePlugin(i32Interface);
+ if( enRetCode != nenOK )
+ {
+ return enRetCode;
+ }
+ }
+ }
+ }
+ tpstPluginConfig pstNewPluginConfig = NULL;
+ for(uint8_t u8Cnt = 0; u8Cnt<nNUMBER_OF_CAN_INTERFACES; u8Cnt++)
+ {
+ pstNewPluginConfig = &g_astPluginConfigList[u8Cnt];
+ if(pstNewPluginConfig->pvPluginHandle == NULL)
+ {
+// DEBUG_PRINT("using memory %d [%#X] for plugin %s",u8Cnt,(int)pstNewPluginConfig,pcSoFilename);
+ break;
+ }
+ else
+ {
+ pstNewPluginConfig = NULL;
+ }
+ }
+ if( !pstNewPluginConfig )
+ {
+ ERROR_PRINT("could not find free memory for plugin");
+ return nenERR_MAX_PLUGINS_REACHED;
+ }
+ strncpy(pstNewPluginConfig->acPluginFilename,pcSoFilename,nMAX_FILENAME_LENGTH);
+ enRetCode = this->enInitPlugin(pstNewPluginConfig,i32Interface);
+ if( enRetCode != nenOK )
+ {
+ return enRetCode;
+ }
+ {
+ boost::lock_guard<x2e::Mutex> lock(m_xPluginListMutex);
+ m_astPluginConfig.push_back(*pstNewPluginConfig);
+ m_u8PluginCounter++;
+ u8PluginId = m_u8PluginCounter;
+ }
+ return nenOK;
+}
+
+tenRetCodes CPluginExecutor::enRemovePlugin( const int32_t i32Interface, bool boLock )
+{
+ tenRetCodes enRetCode = nenOK;
+ if( boLock )
+ {
+ m_xPluginListMutex.lock();
+ }
+ tPluginIter it = findPluginByInterface(i32Interface);
+ if( it != m_astPluginConfig.end() )
+ {
+ tpstPluginConfig pstPlugin = &(*it);
+ this->enDeinitPlugin(pstPlugin);
+ if( boLock )
+ {
+ m_astPluginConfig.erase(it);
+ }
+ m_u8PluginCounter--;
+ }
+ if( boLock )
+ {
+ m_xPluginListMutex.unlock();
+ }
+ return enRetCode;
+}
+
+tenRetCodes CPluginExecutor::enLoadSoFile( const char* pcSoFilename, void** ppvSoHandle )
+{
+ char* pcError = NULL;
+ *ppvSoHandle = dlopen(pcSoFilename,RTLD_NOW|RTLD_GLOBAL|RTLD_DEEPBIND);
+ if( !(*ppvSoHandle) )
+ {
+ pcError = dlerror();
+ ERROR_PRINT("Could not open shared object %s: [%s]"
+ ,pcSoFilename,(pcError)?pcError:"dlopen gave no error");
+ return nenERR_SOFILE;
+ }
+ return nenOK;
+}
+
+void CPluginExecutor::vStop()
+{
+ DEBUG_PRINT("entry");
+ {
+ boost::lock_guard<x2e::Mutex> lock(m_xStopFlagMutex);
+ m_boDoStop = true;
+ }
+ m_xConnector.vStop();
+ DEBUG_PRINT("exit");
+}
+tenRetCodes CPluginExecutor::enLoadSymbol( const char* pcSymbolName, void* pvSoHandle, void** ppvHandle )
+{
+ char* pcError = NULL;
+ *ppvHandle = dlsym(pvSoHandle,pcSymbolName);
+ if( (pcError = dlerror()) != NULL)
+ {
+ ERROR_PRINT("Error finding symbol %s: [%s]",pcSymbolName,pcError);
+ return nenERR_SYMBOL;
+ }
+ return nenOK;
+}
+
+tenRetCodes CPluginExecutor::enInitPlugin( tpstPluginConfig& pstPluginConfig, const int32_t i32Interface )
+{
+ const char* pcPluginFactoryName = "pxCreatePlugin";
+ const char* pcPluginDestructionName = "vDestroyPlugin";
+ void* pvFunctionHandle = NULL;
+ tenRetCodes enRetCode;
+ enRetCode = this->enLoadSoFile(pstPluginConfig->acPluginFilename,
+ &(pstPluginConfig->pvPluginHandle));
+ if( enRetCode != nenOK )
+ {
+ return enRetCode;
+ }
+ enRetCode = this->enLoadSymbol(pcPluginFactoryName,
+ pstPluginConfig->pvPluginHandle,
+ &pvFunctionHandle);
+ if( enRetCode != nenOK )
+ {
+ return enRetCode;
+ }
+ pstPluginConfig->pfctPluginFactory = reinterpret_cast<tpfctCreatePlugin>(pvFunctionHandle);
+
+ enRetCode = this->enLoadSymbol(pcPluginDestructionName,
+ pstPluginConfig->pvPluginHandle,
+ &pvFunctionHandle);
+ if( enRetCode != nenOK )
+ {
+ return enRetCode;
+ }
+ pstPluginConfig->pfctPluginDestruction = reinterpret_cast<tpfctDestroyPlugin> (pvFunctionHandle);
+
+ pstPluginConfig->pxPlugin = pstPluginConfig->pfctPluginFactory(
+ reinterpret_cast<void*>(this),
+ reinterpret_cast<void*>(&m_xInterfaceManager),
+ i32Interface,
+ m_u8PluginCounter
+ );
+ if( pstPluginConfig->pxPlugin->boIsLogger() )
+ {
+ m_pxLogPlugin = pstPluginConfig->pxPlugin;
+ }
+ return nenOK;
+}
+
+void CPluginExecutor::vSendCanTxMessages()
+{
+ x2e::status_t enRes;
+ tCanTxMessageSet::iterator xTxMsgIt = m_xTxMsgList.begin();
+ int32_t i32TxInterface = 0;
+ for( ; xTxMsgIt != m_xTxMsgList.end(); ++xTxMsgIt )
+ {
+ tpstCanTxMessage pxCanTxMsg = (*xTxMsgIt).m_pstCanTxMsg;
+ i32TxInterface = (*xTxMsgIt).i32Interface;
+// DEBUG_PRINT("Sending CAN msg with ID %#x on interface %d"
+// ,pxCanTxMsg->u32CanId,i32TxInterface);
+ enRes = m_xInterfaceManager.enWriteCanMessage(
+ i32TxInterface,
+ pxCanTxMsg->u32CanId,
+ false,
+ false,
+ pxCanTxMsg->au8Data,
+ pxCanTxMsg->u8Dlc
+ );
+ if( enRes != x2e::OK)
+ {
+ ERROR_PRINT("Error sending msg 0x%X on Interface %d. Error: %d",
+ pxCanTxMsg->u32CanId, i32TxInterface, enRes);
+ enRes = m_xInterfaceManager.enDisableInterface(i32TxInterface);
+ enRes = m_xInterfaceManager.enEnableInterface(i32TxInterface);
+ if( enRes != x2e::OK )
+ {
+ break;
+ }
+ }
+ else
+ {
+ if( m_pxLogPlugin )
+ {
+ tstLogMessage stLogMessage;
+ m_xInterfaceManager.enGetTimestamp(&stLogMessage.u32TsHigh,&stLogMessage.u32TsLow);
+ stLogMessage.u32MsgId = pxCanTxMsg->u32CanId;
+ stLogMessage.i32Interface = i32TxInterface;
+ stLogMessage.u8Dir = static_cast<uint8_t>(::nenTx);
+ memcpy( (void*) stLogMessage.au8Data, (const void*) pxCanTxMsg->au8Data, pxCanTxMsg->u8Dlc );
+ m_pxLogPlugin->vLogMessage(stLogMessage);
+ }
+ }
+ }
+ m_xTxMsgList.clear();
+}
+
+void CPluginExecutor::vRun()
+{
+ static tstCanTxMsgWrapper astCanTxMessageWrappers[nMAX_CAN_TX_MESSAGES];
+
+ tPluginIter xPluginIter;
+ bool boDoStop = false;
+
+ {
+ boost::lock_guard<x2e::Mutex> lock(m_xStopFlagMutex);
+ boDoStop = m_boDoStop;
+ }
+
+ while( !m_boDoStop )
+ {
+ m_xInterfaceManager.enWait();
+ {
+ boost::lock_guard<x2e::Mutex> lock(m_xPluginListMutex);
+ for( xPluginIter = m_astPluginConfig.begin(); xPluginIter != m_astPluginConfig.end(); xPluginIter++ )
+ {
+ tpstPluginConfig pstActPlugin = &(*xPluginIter);
+ IPlugin* pxPlugin = pstActPlugin->pxPlugin;
+ if( !pxPlugin )
+ {
+ ERROR_PRINT("Plugin for file %s is NULL",pstActPlugin->acPluginFilename);
+ continue;
+ }
+ pxPlugin->vRun();
+ uint32_t u32NumOfCanTxMsg = pxPlugin->u32GetNumOfCanTxMessages();
+ int32_t i32TxInterface = pxPlugin->i32GetCanInterfaceHandle();
+ if( (i32TxInterface != 0) && (u32NumOfCanTxMsg > 0) )
+ {
+// DEBUG_PRINT("Scheduling CAN TX messages for plugin %s",pstActPlugin->acPluginFilename);
+ for( uint32_t u32CanTxMsgCount = 0; u32CanTxMsgCount < u32NumOfCanTxMsg; u32CanTxMsgCount++ )
+ {
+ if( m_xTxMsgList.size() >= nMAX_CAN_TX_MESSAGES )
+ {
+ DEBUG_PRINT("too much tx messages in plugin %s"
+ ,pstActPlugin->acPluginFilename);
+ vSendCanTxMessages();
+ }
+ tpstCanTxMessage pxCanTxMessage = pxPlugin->pxGetCanTxMessage(u32CanTxMsgCount);
+ tstCanTxMsgWrapper* pxCanMsgWrapper = &astCanTxMessageWrappers[m_xTxMsgList.size()];
+ pxCanMsgWrapper->i32Interface = i32TxInterface;
+ pxCanMsgWrapper->m_pstCanTxMsg = pxCanTxMessage;
+ pxCanTxMessage->u32MillisecondCounter++;
+ if( pxCanTxMessage->u32MillisecondCounter > pxCanTxMessage->u32TxCycleMilliseconds )
+ {
+ ERROR_PRINT("Missed TX cycle of %d msec for CAN message 0x%x"
+ ,pxCanTxMessage->u32MillisecondCounter,pxCanTxMessage->u32CanId);
+ }
+ if( pxCanTxMessage->u32MillisecondCounter >= pxCanTxMessage->u32TxCycleMilliseconds )
+ {
+ pxCanTxMessage->u32MillisecondCounter = 0;
+ m_xTxMsgList.insert(*pxCanMsgWrapper);
+ }
+ }
+ }
+ }
+ }
+ vSendCanTxMessages();
+ }
+ vDeinit();
+ DEBUG_PRINT("exit");
+}
+
+tenRetCodes CPluginExecutor::enDeinitPlugin(tpstPluginConfig& pstPluginConfig)
+{
+ tenRetCodes enRetCode = nenOK;
+ int32_t i32Res = 0;
+ if( pstPluginConfig->pxPlugin )
+ {
+ if( pstPluginConfig->pxPlugin->boIsLogger() )
+ {
+ m_pxLogPlugin = NULL;
+ }
+ pstPluginConfig->pfctPluginDestruction(pstPluginConfig->pxPlugin);
+ }
+ if( pstPluginConfig->pvPluginHandle )
+ {
+ i32Res = dlclose(pstPluginConfig->pvPluginHandle);
+ pstPluginConfig->pvPluginHandle = NULL;
+ }
+ return enRetCode;
+}
+
+tenRetCodes CPluginExecutor::enDeinitAllPlugins()
+{
+ tPluginIter xPluginIter;
+ tenRetCodes enRetCode = nenOK;
+ FILE* pxFp;
+ pxFp = fopen(nAUTOLOAD_FILENAME,"w");
+ {
+ boost::lock_guard<x2e::Mutex> lock(m_xPluginListMutex);
+ for( xPluginIter = m_astPluginConfig.begin(); xPluginIter != m_astPluginConfig.end(); xPluginIter++ )
+ {
+ tpstPluginConfig pstPluginconfig = &(*xPluginIter);
+ if( pstPluginconfig )
+ {
+ tstPluginConfig& stPluginconfig = *pstPluginconfig;
+ IPlugin* pxPlugin = stPluginconfig.pxPlugin;
+ if( pxPlugin )
+ {
+ bool boAutoload = pxPlugin->boAutoload();
+ int32_t i32Interface = pxPlugin->i32GetCanInterfaceHandle();
+ if(boAutoload)
+ {
+ const char* p = stPluginconfig.acPluginFilename;
+ char acLine[nMAX_LINE_LENGTH];
+ snprintf(acLine,nMAX_LINE_LENGTH,"%s%s%d\n",p,nSEPARATOR,i32Interface);
+ fputs(acLine,pxFp);
+ }
+ enRetCode = this->enRemovePlugin(i32Interface, false);
+ }
+ }
+ }
+ m_astPluginConfig.clear();
+ }
+ fclose(pxFp);
+ return enRetCode;
+}
+
+void CPluginExecutor::vGetInterfaces(char* pcResponse, uint32_t& u32Length)
+{
+ for( uint8_t u8IfCtr = 1; u8IfCtr < nNUMBER_OF_CAN_INTERFACES; u8IfCtr++ )
+ {
+ sprintf(&pcResponse[strlen(pcResponse)],"CAN %d\n",u8IfCtr);
+ }
+ u32Length = strlen(pcResponse);
+ return;
+}
+
+uint8_t CPluginExecutor::u8GetPluginCount()
+{
+ return m_u8PluginCounter;
+}
+
+void CPluginExecutor::vDeinit()
+{
+ m_xConnectorThread.join();
+ DEBUG_PRINT("Connector thread stopped");
+ enDeinitAllPlugins();
+ m_xInterfaceManager.vDeinit();
+}
+
+tenRetCodes CPluginExecutor::enAutoLoadPlugins()
+{
+ tenRetCodes enRetCode = nenOK;
+ char acActLine[nMAX_LINE_LENGTH];
+ int iFd = -1;
+ ssize_t xReadRes = -1;
+ int iCtr = 0;
+ memset(acActLine,0,nMAX_LINE_LENGTH);
+ iFd = open(nAUTOLOAD_FILENAME,O_RDONLY);
+ if( iFd < 0)
+ {
+ ERROR_PRINT("Error opening file %s: %d",nAUTOLOAD_FILENAME,errno);
+ }
+ while( ( xReadRes = read(iFd, (void*) &acActLine[iCtr], 1) ) > 0 )
+ {
+ if(acActLine[iCtr] == '\n')
+ {
+ char *pcFilename, *pcInterface;
+ int32_t i32Interface = -1;
+ uint8_t u8PluginId;
+ pcFilename = strtok(acActLine,nSEPARATOR);
+ pcInterface = strtok(NULL,nSEPARATOR);
+ if( (pcFilename != NULL) && (pcInterface != NULL) )
+ {
+ i32Interface = atoi(pcInterface);
+ enRetCode = enAddPlugin(pcFilename,i32Interface,u8PluginId);
+ if( enRetCode == nenOK )
+ {
+ DEBUG_PRINT("auto loaded plugin [%s] on interface [%d]",pcFilename,i32Interface);
+ }
+ else
+ {
+ ERROR_PRINT("error autoloading plugin [%s]: %d",pcFilename,enRetCode);
+ }
+ }
+ memset(acActLine,0,nMAX_LINE_LENGTH);
+ iCtr = 0;
+ }
+ else
+ {
+ iCtr++;
+ }
+ }
+ if( xReadRes == -1 )
+ {
+ ERROR_PRINT("Error reading file %s: %d",nAUTOLOAD_FILENAME,errno);
+ enRetCode = nenERR_SOFILE;
+ return enRetCode;
+ }
+ close(iFd);
+ return enRetCode;
+}
+
+tenRetCodes CPluginExecutor::enGetLog(const char* pcRequestFilename, char* pcResponseFilename, uint32_t& u32Length)
+{
+ tenRetCodes enRetCode = nenOK;
+ if( m_pxLogPlugin )
+ {
+ enRetCode = m_pxLogPlugin->enGetLog(pcRequestFilename,pcResponseFilename);
+ if( enRetCode != nenOK)
+ {
+ return enRetCode;
+ }
+ DEBUG_PRINT("logfile name: %s",pcResponseFilename);
+ u32Length = strlen(pcResponseFilename);
+ }
+ return enRetCode;
+}
+
+void CPluginExecutor::vStartPlugin(const int32_t i32Interface, const char* pcSoFilename)
+{
+ uint8_t u8PluginId;
+ tenRetCodes enRetVal = enAddPlugin(pcSoFilename,i32Interface,u8PluginId);
+ if( enRetVal == nenOK)
+ {
+ DEBUG_PRINT("Started plugin %d on interface %d from file %s"
+ ,u8PluginId,i32Interface,pcSoFilename);
+ }
+ else
+ {
+ ERROR_PRINT("Error starting plugin %s on interface %d: %d",
+ pcSoFilename,i32Interface,enRetVal);
+ }
+}
+
+void CPluginExecutor::vStopPlugin(int32_t i32Interface)
+{
+ enRemovePlugin(i32Interface,true);
+ DEBUG_PRINT("Stopped plugin on interface %d", i32Interface);
+}
+
+void CPluginExecutor::vChangeMsgData(const int32_t i32Interface, const uint32_t u32CanId, const uint8_t* pu8Data)
+{
+ tPluginIter xPluginIter;
+ boost::lock_guard<x2e::Mutex> lock(m_xPluginListMutex);
+ {
+ for( xPluginIter = m_astPluginConfig.begin(); xPluginIter != m_astPluginConfig.end(); xPluginIter++ )
+ {
+ tpstPluginConfig pstActPlugin = &(*xPluginIter);
+ if( !pstActPlugin )
+ {
+ continue;
+ }
+ IPlugin* pxPlugin = pstActPlugin->pxPlugin;
+ if( !pxPlugin )
+ {
+ continue;
+ }
+ if( pxPlugin->i32GetCanInterfaceHandle() != i32Interface )
+ {
+ continue;
+ }
+ uint32_t u32NumOfCanTxMsg = pxPlugin->u32GetNumOfCanTxMessages();
+ if( u32NumOfCanTxMsg > 0 )
+ {
+ for( uint32_t u32CanTxMsgCount = 0; u32CanTxMsgCount < u32NumOfCanTxMsg; u32CanTxMsgCount++ )
+ {
+ tpstCanTxMessage pxCanTxMessage = pxPlugin->pxGetCanTxMessage(u32CanTxMsgCount);
+ if( pxCanTxMessage->u32CanId == u32CanId )
+ {
+ memcpy( (void*)pxCanTxMessage->au8Data, pu8Data, pxCanTxMessage->u8Dlc );
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+tenRetCodes CPluginExecutor::enEnumerateLogs(char* pcLogfiles, uint32_t& u32Length)
+{
+ tenRetCodes enRes = nenOK;
+ struct dirent* pstDirEnt;
+ const char* pcLogPath = "../data/";
+ const char* pcLogFileExtension = ".log";
+ const char* pcFormat="%s%s\n";
+ DIR* pDir = opendir(pcLogPath);
+ uint32_t u32StrLen = 0;
+ uint32_t u32ActFilenameLen = 0;
+
+ while( (pstDirEnt=readdir(pDir)) != NULL )
+ {
+ u32ActFilenameLen = strlen(pcLogPath) + strlen(pstDirEnt->d_name);
+ u32StrLen = strlen(pcLogfiles) + u32ActFilenameLen + 1;
+ if( strstr(pstDirEnt->d_name,pcLogFileExtension) != NULL )
+ {
+ if( u32StrLen < u32Length )
+ {
+ sprintf(&pcLogfiles[strlen(pcLogfiles)],pcFormat,pcLogPath,pstDirEnt->d_name);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ closedir(pDir);
+ u32Length = strlen(pcLogfiles);
+ return enRes;
+}
+
+void CPluginExecutor::vUploadLogMessage(const tstLogMessage& stLogMsg)
+{
+ m_xConnector.vUploadLogMessage(stLogMsg);
+}
+
|
