From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../src/XorayaPluginExecutor/CPluginExecutor.cpp | 577 +++++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp (limited to 'Master/Masterarbeit/src/XorayaPluginExecutor/CPluginExecutor.cpp') 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 +#include +#include "global.h" +#include +#include +#include +#include +#include +#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 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; u8CntpvPluginHandle == 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 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 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(pvFunctionHandle); + + enRetCode = this->enLoadSymbol(pcPluginDestructionName, + pstPluginConfig->pvPluginHandle, + &pvFunctionHandle); + if( enRetCode != nenOK ) + { + return enRetCode; + } + pstPluginConfig->pfctPluginDestruction = reinterpret_cast (pvFunctionHandle); + + pstPluginConfig->pxPlugin = pstPluginConfig->pfctPluginFactory( + reinterpret_cast(this), + reinterpret_cast(&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(::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 lock(m_xStopFlagMutex); + boDoStop = m_boDoStop; + } + + while( !m_boDoStop ) + { + m_xInterfaceManager.enWait(); + { + boost::lock_guard 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 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 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); +} + -- cgit v1.2.3