diff --git a/CMakeLists.txt b/CMakeLists.txt index a182a0519..9f147cae7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,10 +312,6 @@ SET(FORTE_IPLayerRecvBufferSize "1500" CACHE STRING "FORTE IP layer recv buffer endif(FORTE_DYNAMIC_TYPE_LOAD) mark_as_advanced(FORTE_IPLayerRecvBufferSize) -SET(FORTE_MGMCOMMANDPROTOCOL "DEV_MGR" CACHE STRING "FORTE management command protocol") -set_property(CACHE FORTE_MGMCOMMANDPROTOCOL PROPERTY STRINGS DEV_MGR) -mark_as_advanced(FORTE_MGMCOMMANDPROTOCOL) - SET(FORTE_MGM_MAX_SUPPORTED_NAME_HIERACHY "30" CACHE STRING "Max supported hierarchy that can be provided in a management commands") mark_as_advanced(FORTE_MGM_MAX_SUPPORTED_NAME_HIERACHY) diff --git a/forte_config.h.in b/forte_config.h.in index 02332e678..52f581b0a 100644 --- a/forte_config.h.in +++ b/forte_config.h.in @@ -44,14 +44,6 @@ const unsigned int cgCommunicationInterruptQueueSize = ${FORTE_CommunicationInte */ const unsigned int cgIPLayerRecvBufferSize = ${FORTE_IPLayerRecvBufferSize}; -/*! \brief Define the management encapsulation protocol - * - * Currently two protocols are supported: - * # DEV_MGR for FBDK compliant XML encoded commands - * # WBXML_DEV_MGR for WAP Binary XML encoded commands - */ -#define FORTE_MGM_COMMAND_PROTOCOL ${FORTE_MGMCOMM-ANDPROTOCOL} - //! Max supported hierarchy that can be provided in a management commands #define FORTE_MGM_MAX_SUPPORTED_NAME_HIERARCHY ${FORTE_MGM_MAX_SUPPORTED_NAME_HIERACHY} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c2d3a366d..e986d46e0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -29,8 +29,8 @@ forte_add_subdirectory(fmi) forte_add_sourcefile_hcpp(conn dataconn inoutdataconn eventconn) forte_add_sourcefile_h(connectiondestinationtype.h) -forte_add_sourcefile_h(esfb.h event.h mgmcmd.h fortenode.h fortelist.h genfb.h simplefb.h) -forte_add_sourcefile_hcpp(basicfb cfb device devexec forteinstance) +forte_add_sourcefile_h(esfb.h event.h fortenode.h fortelist.h genfb.h simplefb.h) +forte_add_sourcefile_hcpp(basicfb cfb device devexec forteinstance mgmcmd) forte_add_sourcefile_hcpp(extevhan funcbloc fbcontainer if2indco) forte_add_sourcefile_hcpp(resource stringdict typelib ecet) forte_add_sourcefile_hcpp(adapterconn adapter anyadapter iec61131_functions) diff --git a/src/core/mgmcmd.cpp b/src/core/mgmcmd.cpp new file mode 100644 index 000000000..d610272df --- /dev/null +++ b/src/core/mgmcmd.cpp @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2024 Jose Cabral + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Jose Cabral: + * - initial implementation and rework communication infrastructure + *******************************************************************************/ + +#include "mgmcmd.h" + +#include + +namespace forte::mgm_cmd { + + /*!\brief Type for the response of MGM command messages + * + * TODO fully define all responses as defined in IEC 61499 inc. numbers. + */ + const std::string scmMGMResponseTexts[] = { + "RDY", + "BAD_PARAMS", + "LOCAL_TERMINATION", + "SYSTEM_TERMINATION", + "NOT_READY", + "UNSUPPORTED_CMD", + "UNSUPPORTED_TYPE", + "NO_SUCH_OBJECT", + "INVALID_OBJECT", + "INVALID_OPERATION", + "INVALID_STATE", + "OVERFLOW", + "INVALID_DST" + }; + + const std::string& getResponseText(EMGMResponse paResp) { + return scmMGMResponseTexts[static_cast>(paResp)]; + } + +} // namespace forte::mgm_cmd \ No newline at end of file diff --git a/src/core/mgmcmd.h b/src/core/mgmcmd.h index 47bb5b02c..d4ac0f282 100644 --- a/src/core/mgmcmd.h +++ b/src/core/mgmcmd.h @@ -14,7 +14,9 @@ #ifndef _MGMCMD_H_ #define _MGMCMD_H_ -#include +#include + +#include /** \ingroup CORE \defgroup MGMCommands Management Commands Internal Representation * \brief In this section the FORTE representation of the management commands is described. @@ -266,5 +268,11 @@ enum class EMGMResponse { InvalidDst }; +namespace forte::mgm_cmd { + + const std::string& getResponseText(EMGMResponse paResp); + +} // namespace forte::mgm_cmd + /*@}*/ #endif /*MGMCMD_H_*/ diff --git a/src/modules/reconfiguration/EC_KILL_ELEM_fbt.cpp b/src/modules/reconfiguration/EC_KILL_ELEM_fbt.cpp index d16d3d4e0..97baf5957 100644 --- a/src/modules/reconfiguration/EC_KILL_ELEM_fbt.cpp +++ b/src/modules/reconfiguration/EC_KILL_ELEM_fbt.cpp @@ -17,7 +17,6 @@ #include "criticalregion.h" #include "resource.h" -#include "../../stdfblib/ita/DEV_MGR.h" #include "device.h" DEFINE_FIRMWARE_FB(FORTE_EC_KILL_ELEM, g_nStringIdEC_KILL_ELEM) @@ -88,7 +87,7 @@ void FORTE_EC_KILL_ELEM::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/EC_SET_EVT_fbt.cpp b/src/modules/reconfiguration/EC_SET_EVT_fbt.cpp index 09c13387e..efed95b67 100644 --- a/src/modules/reconfiguration/EC_SET_EVT_fbt.cpp +++ b/src/modules/reconfiguration/EC_SET_EVT_fbt.cpp @@ -19,7 +19,6 @@ #include "device.h" #include "mgmcmdstruct.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_EC_SET_EVT, g_nStringIdEC_SET_EVT) @@ -91,7 +90,7 @@ void FORTE_EC_SET_EVT::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/EC_START_ELEM_fbt.cpp b/src/modules/reconfiguration/EC_START_ELEM_fbt.cpp index 2dde8b518..c9d4c7d7d 100644 --- a/src/modules/reconfiguration/EC_START_ELEM_fbt.cpp +++ b/src/modules/reconfiguration/EC_START_ELEM_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_EC_START_ELEM, g_nStringIdEC_START_ELEM) @@ -88,7 +87,7 @@ void FORTE_EC_START_ELEM::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/EC_STOP_ELEM_fbt.cpp b/src/modules/reconfiguration/EC_STOP_ELEM_fbt.cpp index 0b882d226..52f5e22fd 100644 --- a/src/modules/reconfiguration/EC_STOP_ELEM_fbt.cpp +++ b/src/modules/reconfiguration/EC_STOP_ELEM_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_EC_STOP_ELEM, g_nStringIdEC_STOP_ELEM) @@ -88,7 +87,7 @@ void FORTE_EC_STOP_ELEM::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/ST_CREATE_CONN_fbt.cpp b/src/modules/reconfiguration/ST_CREATE_CONN_fbt.cpp index 05bf11bb2..e1bbe654e 100644 --- a/src/modules/reconfiguration/ST_CREATE_CONN_fbt.cpp +++ b/src/modules/reconfiguration/ST_CREATE_CONN_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_ST_CREATE_CONN, g_nStringIdST_CREATE_CONN) @@ -97,7 +96,7 @@ void FORTE_ST_CREATE_CONN::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/ST_CREATE_FB_fbt.cpp b/src/modules/reconfiguration/ST_CREATE_FB_fbt.cpp index 1630f1f57..f311b3ca8 100644 --- a/src/modules/reconfiguration/ST_CREATE_FB_fbt.cpp +++ b/src/modules/reconfiguration/ST_CREATE_FB_fbt.cpp @@ -19,7 +19,6 @@ #include "device.h" #include "mgmcmdstruct.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_ST_CREATE_FB, g_nStringIdST_CREATE_FB) @@ -92,7 +91,7 @@ void FORTE_ST_CREATE_FB::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/ST_DEL_CONN_fbt.cpp b/src/modules/reconfiguration/ST_DEL_CONN_fbt.cpp index 7e52bf34f..06a38da28 100644 --- a/src/modules/reconfiguration/ST_DEL_CONN_fbt.cpp +++ b/src/modules/reconfiguration/ST_DEL_CONN_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_ST_DEL_CONN, g_nStringIdST_DEL_CONN) @@ -97,7 +96,7 @@ void FORTE_ST_DEL_CONN::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/ST_DEL_FB_fbt.cpp b/src/modules/reconfiguration/ST_DEL_FB_fbt.cpp index 58600b16e..117807198 100644 --- a/src/modules/reconfiguration/ST_DEL_FB_fbt.cpp +++ b/src/modules/reconfiguration/ST_DEL_FB_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_ST_DEL_FB, g_nStringIdST_DEL_FB) @@ -88,7 +87,7 @@ void FORTE_ST_DEL_FB::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/ST_REC_CONN_fbt.cpp b/src/modules/reconfiguration/ST_REC_CONN_fbt.cpp index 9e4681a48..3d1f3a15d 100644 --- a/src/modules/reconfiguration/ST_REC_CONN_fbt.cpp +++ b/src/modules/reconfiguration/ST_REC_CONN_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_ST_REC_CONN, g_nStringIdST_REC_CONN) @@ -117,7 +116,7 @@ void FORTE_ST_REC_CONN::executeRQST(){ //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/modules/reconfiguration/ST_SET_PARM_fbt.cpp b/src/modules/reconfiguration/ST_SET_PARM_fbt.cpp index 1770bc08f..3cf716d6b 100644 --- a/src/modules/reconfiguration/ST_SET_PARM_fbt.cpp +++ b/src/modules/reconfiguration/ST_SET_PARM_fbt.cpp @@ -18,7 +18,6 @@ #include "resource.h" #include "device.h" -#include "../../stdfblib/ita/DEV_MGR.h" DEFINE_FIRMWARE_FB(FORTE_ST_SET_PARM, g_nStringIdST_SET_PARM) @@ -93,7 +92,7 @@ void FORTE_ST_SET_PARM::executeRQST() { //calculate return value var_QO = CIEC_BOOL(resp == EMGMResponse::Ready); - const std::string retVal(DEV_MGR::getResponseText(resp)); + const std::string retVal(forte::mgm_cmd::getResponseText(resp)); DEVLOG_DEBUG("%s\n", retVal.c_str()); var_STATUS = CIEC_WSTRING(retVal.c_str()); } diff --git a/src/stdfblib/ita/CMakeLists.txt b/src/stdfblib/ita/CMakeLists.txt index 34c0272d7..5cb317ea3 100644 --- a/src/stdfblib/ita/CMakeLists.txt +++ b/src/stdfblib/ita/CMakeLists.txt @@ -16,7 +16,7 @@ # Ita FB ############################################################################# SET(SOURCE_GROUP ${SOURCE_GROUP}\\ita) -forte_add_sourcefile_hcpp(DEV_MGR EMB_RES RMT_DEV RMT_RES) +forte_add_sourcefile_hcpp(DEV_MGR EMB_RES RMT_DEV RMT_RES CommandParser) forte_add_device(RMT_DEV) diff --git a/src/stdfblib/ita/CommandParser.cpp b/src/stdfblib/ita/CommandParser.cpp new file mode 100644 index 000000000..f43be8953 --- /dev/null +++ b/src/stdfblib/ita/CommandParser.cpp @@ -0,0 +1,634 @@ +/******************************************************************************* + * Copyright (c) 2024 Jose Cabral + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Jose Cabral + * - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#include "CommandParser.h" + +#include + +#include "core/utils/string_utils.h" +#include "core/device.h" + + +namespace forte::ita { + +CommandParser::CommandParser(CDevice& paDevice) : mDevice{paDevice}{ + mCommand.mAdditionalParams.reserve(255); +} + +EMGMResponse CommandParser::parseAndExecuteMGMCommand(const char *const paDest, char *paCommand){ + mLastResponse = EMGMResponse::InvalidObject; + + if(nullptr != strchr(paCommand, '>')){ + mCommand.mID = nullptr; + mCommand.mAdditionalParams.clear(); + mCommand.mFirstParam.clear(); + mCommand.mSecondParam.clear(); +#ifdef FORTE_SUPPORT_MONITORING + mCommand.mMonitorResponse.clear(); +#endif // FORTE_SUPPORT_MONITORING + + mCommand.mDestination = (strlen(paDest) != 0) ? CStringDictionary::getInstance().insert(paDest) : CStringDictionary::scmInvalidStringId; + if ( 255 <= mCommand.mAdditionalParams.capacity()) { + mCommand.mAdditionalParams.reserve(255); + } + + char *acRequestPartLeft = parseRequest(paCommand); + if(nullptr != acRequestPartLeft){ + acRequestPartLeft = strchr(acRequestPartLeft, '<'); + if(nullptr != acRequestPartLeft){ + acRequestPartLeft++; //point to the next character after the < + } + // we got the command for execution + // now check the rest of the data + switch (mCommand.mCMD){ + case EMGMCommandType::CreateGroup: // create something + parseCreateData(acRequestPartLeft); + break; + case EMGMCommandType::DeleteGroup: //delete something + parseDeleteData(acRequestPartLeft); + break; + case EMGMCommandType::Start: + case EMGMCommandType::Stop: + case EMGMCommandType::Kill: + case EMGMCommandType::Reset: + parseAdditionalStateCommandData(acRequestPartLeft); + break; + case EMGMCommandType::Read: + parseReadData(acRequestPartLeft); + break; + case EMGMCommandType::Write: + parseWriteData(acRequestPartLeft); + break; +#ifdef FORTE_SUPPORT_QUERY_CMD + case EMGMCommandType::QueryGroup: // query something + parseQueryData(acRequestPartLeft); +#endif + break; + default: + break; + } + + if(EMGMCommandType::INVALID != mCommand.mCMD) { + mLastResponse = mDevice.executeMGMCommand(mCommand); + } + } + else { + mLastResponse = EMGMResponse::UnsupportedCmd; + } + } + return mLastResponse; +} + + +std::string CommandParser::generateResponse(){ +#ifdef FORTE_SUPPORT_MONITORING + if (0 != mCommand.mMonitorResponse.length()) { + return generateMonitorResponse(); + } +#endif //FORTE_SUPPORT_MONITORING + + if(0 < mCommand.mAdditionalParams.length()){ + return generateLongResponse(); + } + + return generateShortResponse(); +} + +std::string CommandParser::generateShortResponse(){ + std::string response; + response.append(""); + return response; +} + +std::string CommandParser::generateLongResponse(){ + std::string response; + response.reserve(static_cast(255 + (mCommand.mAdditionalParams.length()))); + response.append("\n "); + } + else{ + response.append(">\n "); + if(mCommand.mCMD == EMGMCommandType::Read){ + response.append(""); + } +#ifdef FORTE_SUPPORT_QUERY_CMD + else if(mCommand.mCMD == EMGMCommandType::QueryConnection){ + if ((mCommand.mFirstParam.isEmpty()) && + (mCommand.mSecondParam.isEmpty())) { //src & dst = * + response.append(mCommand.mAdditionalParams); + } + else { //either src or dst = * (both != * should be treated by generateResponse + response.append("\n "); + response.append(mCommand.mAdditionalParams); + response.append("\n "); + } + } + else if(mCommand.mCMD == EMGMCommandType::QueryFB){ + if(!mCommand.mFirstParam.isEmpty()) { //Name != "*" + if(!mCommand.mSecondParam.isEmpty()){ //Type != "*" + response.append(""); + } else { //Type == "*" + response.append(""); + } + } + else{ + response.append("\n "); + response.append(mCommand.mAdditionalParams); + response.append("\n "); + } + } + else if(mCommand.mCMD == EMGMCommandType::QueryFBTypes || mCommand.mCMD == EMGMCommandType::QueryAdapterTypes){ + response.append("\n "); + response.append(mCommand.mAdditionalParams); + response.append("\n "); + } + else if(mCommand.mCMD == EMGMCommandType::QueryDTTypes){ + response.append("\n "); + response.append(mCommand.mAdditionalParams); + response.append("\n "); + } + else if(mCommand.mCMD == EMGMCommandType::QueryFBType){ + response.append(""); + } + else if(mCommand.mCMD == EMGMCommandType::QueryAdapterType){ + response.append("\n"); + } +#endif + } + response.append("\n"); + return response; +} + +char* CommandParser::parseRequest(char *paRequestString){ + //first check if it is an management request + char *acCommandStart = nullptr; + static const int scnCommandLength[] = {7, 7, 6, 5, 5, 6, 5, 6, 6}; + + if(!strncmp("= 7){ + return nullptr; + } + } + paRequestString[i] = '\0'; //close ID + ++i; + acCommandStart = strchr((&paRequestString[i]), '\"'); + if(acCommandStart != nullptr){ + acCommandStart++; //this is the real start of the command + if(!strncmp("CREATE", acCommandStart, 6)){ + mCommand.mCMD = EMGMCommandType::CreateGroup; + } + else if(!strncmp("DELETE", acCommandStart, 6)){ + mCommand.mCMD = EMGMCommandType::DeleteGroup; + } + else if(!strncmp("START", acCommandStart, 5)){ + mCommand.mCMD = EMGMCommandType::Start; + } + else if(!strncmp("STOP", acCommandStart, 4)){ + mCommand.mCMD = EMGMCommandType::Stop; + } + else if(!strncmp("KILL", acCommandStart, 4)){ + mCommand.mCMD = EMGMCommandType::Kill; + } + else if(!strncmp("RESET", acCommandStart, 5)){ + mCommand.mCMD = EMGMCommandType::Reset; + } + else if(!strncmp("READ", acCommandStart, 4)){ + mCommand.mCMD = EMGMCommandType::Read; + } + else if(!strncmp("WRITE", acCommandStart, 5)){ + mCommand.mCMD = EMGMCommandType::Write; + } +#ifdef FORTE_SUPPORT_QUERY_CMD + else if(!strncmp("QUERY", acCommandStart, 5)){ + mCommand.mCMD = EMGMCommandType::QueryGroup; + } +#endif // FORTE_SUPPORT_QUERY_CMD + else{ + return nullptr; + } + acCommandStart += scnCommandLength[static_cast(mCommand.mCMD)]; + } + } + return acCommandStart; +} + +#ifdef FORTE_DYNAMIC_TYPE_LOAD +bool CommandParser::parseXType(char *paRequestPartLeft, const char *paRequestType) { + bool retVal = false; + size_t nReqLength = strlen(paRequestType); + if(!strncmp(paRequestType, paRequestPartLeft, nReqLength)){ + paRequestPartLeft = &(paRequestPartLeft[nReqLength]); + if('*' != paRequestPartLeft[0]){ + int i = parseIdentifier(paRequestPartLeft, mCommand.mFirstParam); + paRequestPartLeft = (-1 == i) ? nullptr : strchr(&(paRequestPartLeft[i + 1]), '>'); + } + if(nullptr != paRequestPartLeft){ + paRequestPartLeft++; + char* endOfRequest = strchr(paRequestPartLeft, '<'); + *endOfRequest = '\0'; + forte::core::util::transformEscapedXMLToNonEscapedText(paRequestPartLeft); + mCommand.mAdditionalParams = paRequestPartLeft; + retVal = true; + } + } + return retVal; +} +#endif // FORTE_DYNAMIC_TYPE_LOAD + +bool CommandParser::parseFBData(char *paRequestPartLeft){ + bool retVal = false; + + if(!strncmp("FB Name=\"", paRequestPartLeft, 9)){ + char *acBuf = &(paRequestPartLeft[9]); + int i = 0; + if(acBuf[0] != '*'){ + i = parseIdentifier(acBuf, mCommand.mFirstParam); + acBuf = (-1 == i) ? nullptr : strchr(&(acBuf[i + 1]), '\"'); + } + else{ + acBuf = strchr(&(acBuf[i + 2]), '\"'); + } + + if(acBuf != nullptr){ + if(acBuf[1] != '*'){ + ++acBuf; + i = parseIdentifier(acBuf, mCommand.mSecondParam); + if(-1 != i){ + acBuf = strchr(&(acBuf[i + 1]), '\"'); + if(acBuf != nullptr){ + // We have an application name given + ++acBuf; + TForteUInt16 nBufLength = static_cast(strcspn(acBuf, "\"") + 1); + mCommand.mAdditionalParams.assign(acBuf, nBufLength); + } + } + else{ + return false; + } + } + retVal = true; + } + } + return retVal; +} + +int CommandParser::parseIdentifier(char *paIdentifierStart, forte::core::TNameIdentifier &paIdentifier){ + for(char *runner = paIdentifierStart, *start = paIdentifierStart; '\0' != *runner; ++runner){ + if('.' == *runner){ + *runner = '\0'; + if(!paIdentifier.pushBack(CStringDictionary::getInstance().insert(start))){ + return -1; + } + *runner = '.'; + start = runner + 1; + } else if ('"' == *runner){ + *runner = '\0'; + if(!paIdentifier.pushBack(CStringDictionary::getInstance().insert(start))){ + return -1; + } + *runner = '"'; + return static_cast(runner - paIdentifierStart); + } + } + return -1; +} + +bool CommandParser::parseConnectionData(char *paRequestPartLeft){ + bool bRetVal = false; + if(!strncmp("Connection Source=\"", paRequestPartLeft, sizeof("Connection Source=\"") - 1)){ + int i = parseIdentifier(&(paRequestPartLeft[19]), mCommand.mFirstParam); + if(-1 != i){ + char *acBuf = strchr(&(paRequestPartLeft[i + 21]), '\"'); + if(acBuf != nullptr){ + parseIdentifier(&(acBuf[1]), mCommand.mSecondParam); + bRetVal = (-1 != i); + } + } + } + return bRetVal; +} + +bool CommandParser::parseWriteConnectionData(char *paRequestPartLeft){ + bool retVal = false; + if(!strncmp("Connection Source=\"", paRequestPartLeft, sizeof("Connection Source=\"") - 1)){ + paRequestPartLeft = &(paRequestPartLeft[19]); + + char* endOfSource = strchr(paRequestPartLeft, '\"'); + if(nullptr == endOfSource){ + return false; + } + *endOfSource = '\0'; + char *addParams = new char[strlen(paRequestPartLeft) + 1](); + strcpy(addParams, paRequestPartLeft); + forte::core::util::transformEscapedXMLToNonEscapedText(addParams); + mCommand.mAdditionalParams = addParams; + delete[](addParams); + *endOfSource = '"'; // restore the string + paRequestPartLeft = strchr(endOfSource + 1, '\"'); + if(nullptr != paRequestPartLeft){ + retVal = (-1 != parseIdentifier(&paRequestPartLeft[1], mCommand.mFirstParam)); + } + } + return retVal; +} + +void CommandParser::parseCreateData(char *paRequestPartLeft){ + mCommand.mCMD = EMGMCommandType::INVALID; + if(nullptr != paRequestPartLeft){ + switch (paRequestPartLeft[0]){ +#ifdef FORTE_DYNAMIC_TYPE_LOAD + case 'A': // we have an Adapter to Create + if(parseXType(paRequestPartLeft, "AdapterType Name=\"")){ + mCommand.mCMD = EMGMCommandType::CreateAdapterType; + } + break; +#endif // FORTE_DYNAMIC_TYPE_LOAD + case 'F': // we have an FB to Create + if(parseFBData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::CreateFBInstance; + } +#ifdef FORTE_DYNAMIC_TYPE_LOAD + else if(parseXType(paRequestPartLeft, "FBType Name=\"")){ + mCommand.mCMD = EMGMCommandType::CreateFBType; + } +#endif // FORTE_DYNAMIC_TYPE_LOAD + break; + case 'C': // we have an Connection to Create + if(parseConnectionData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::CreateConnection; + } + break; +#ifdef FORTE_SUPPORT_MONITORING + case 'W': // we have an Watch to Add + if(parseMonitoringData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::MonitoringAddWatch; + } + break; +#endif //FORTE_SUPPORT_MONITORING + default: + break; + } + } +} + +void CommandParser::parseDeleteData(char *paRequestPartLeft){ + mCommand.mCMD = EMGMCommandType::INVALID; + if(nullptr != paRequestPartLeft){ + switch (paRequestPartLeft[0]){ + case 'F': // we have an FB to delete + if(parseFBData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::DeleteFBInstance; + } + break; + case 'C': // we have an Connection to delete + if(parseConnectionData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::DeleteConnection; + } + break; +#ifdef FORTE_SUPPORT_MONITORING + case 'W': // we have an Watch to remove + if(parseMonitoringData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::MonitoringRemoveWatch; + } + break; +#endif // FORTE_SUPPORT_MONITORING + default: + break; + } + } +} + +void CommandParser::parseAdditionalStateCommandData(char *paRequestPartLeft){ + if(nullptr != paRequestPartLeft && '/' != paRequestPartLeft[0] && //if we have an additional xml token parse if it is an FB definition + !parseFBData(paRequestPartLeft)) { + mCommand.mCMD = EMGMCommandType::INVALID; + } +} + +void CommandParser::parseReadData(char *paRequestPartLeft){ + mCommand.mCMD = EMGMCommandType::INVALID; + if(nullptr != paRequestPartLeft){ +#ifdef FORTE_SUPPORT_MONITORING + if('W' == paRequestPartLeft[0]){ + mCommand.mCMD = EMGMCommandType::MonitoringReadWatches; + } else +#endif // FORTE_SUPPORT_MONITORING + if(parseConnectionData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::Read; + } + } +} + +void CommandParser::parseWriteData(char *paRequestPartLeft){ + //We need an additional xml connection token parse if it is an connection definition + mCommand.mCMD = EMGMCommandType::INVALID; + if(nullptr != paRequestPartLeft && parseWriteConnectionData(paRequestPartLeft)){ +#ifdef FORTE_SUPPORT_MONITORING + char *pch = strstr(paRequestPartLeft, "force=\""); + if (nullptr != pch) { + if (!strncmp(&pch[7], "true", sizeof("true") - 1)) { + mCommand.mCMD = EMGMCommandType::MonitoringForce; + } else if (!strncmp(&pch[7], "false", sizeof("false") - 1)) { + mCommand.mCMD = EMGMCommandType::MonitoringClearForce; + } + } else if ((2 == mCommand.mAdditionalParams.length()) && + (('$' == mCommand.mAdditionalParams[0]) && + (('e' == mCommand.mAdditionalParams[1]) ||('E' == mCommand.mAdditionalParams[1]) ))){ + mCommand.mCMD = EMGMCommandType::MonitoringTriggerEvent; + }else if ((3 == mCommand.mAdditionalParams.length()) && + (('$' == mCommand.mAdditionalParams[0]) && + (('e' == mCommand.mAdditionalParams[1]) ||('E' == mCommand.mAdditionalParams[1]) ) && + (('r' == mCommand.mAdditionalParams[2]) ||('R' == mCommand.mAdditionalParams[2]) ) )){ + mCommand.mCMD = EMGMCommandType::MonitoringResetEventCount; + }else +#endif // FORTE_SUPPORT_MONITORING + mCommand.mCMD = EMGMCommandType::Write; + } +} + +#ifdef FORTE_SUPPORT_QUERY_CMD +void CommandParser::parseQueryData(char *paRequestPartLeft){ + mCommand.mCMD = EMGMCommandType::INVALID; + if(nullptr != paRequestPartLeft){ + switch (paRequestPartLeft[0]){ + case 'F': // query fb or fb type list + if(!strncmp(paRequestPartLeft, "FBT", sizeof("FBT") - 1)){ + if(parseTypeListData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::QueryFBTypes; + } +#ifdef FORTE_DYNAMIC_TYPE_LOAD + else if(parseXType(paRequestPartLeft, "FBType Name=\"")){ + mCommand.mCMD = EMGMCommandType::QueryFBType; + } +#endif + else { + mCommand.mCMD = EMGMCommandType::QueryGroup; + } + }else if(parseFBData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::QueryFB; + } + break; + case 'C': // query connection list + if(parseConnectionData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::QueryConnection; + } + break; + case 'D': // query datatype list + if(!strncmp(paRequestPartLeft, "DataType", sizeof("DataType") - 1)){ + if(parseTypeListData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::QueryDTTypes; + } else { + mCommand.mCMD = EMGMCommandType::QueryGroup; + } + } + break; + case 'A': // query adaptertype list + if(!strncmp(paRequestPartLeft, "AdapterT", sizeof("AdapterT") - 1)){ + if(parseTypeListData(paRequestPartLeft)){ + mCommand.mCMD = EMGMCommandType::QueryAdapterTypes; + } +#ifdef FORTE_DYNAMIC_TYPE_LOAD + else if(parseXType(paRequestPartLeft, "AdapterType Name=\"")){ + mCommand.mCMD = EMGMCommandType::QueryAdapterType; + } +#endif + else { + mCommand.mCMD = EMGMCommandType::QueryGroup; + } + } + + break; + default: + break; + } + } +} + +bool CommandParser::parseTypeListData(char *paRequestPartLeft){ + bool retVal = true; + + if (!strncmp("DataType Name=\"", paRequestPartLeft, sizeof("DataType Name=\"") - 1)) { + if(paRequestPartLeft[15] != '*'){ //does not support query for DataType-Declaration + retVal = false; + } + } + else if(!strncmp("FBType Name=\"", paRequestPartLeft, sizeof("FBType Name=\"") - 1)){ + if(paRequestPartLeft[13] != '*'){ //supports query for FBType-Declaration only for DynamicTypeLoad profile (LUA enabled) + retVal = false; + } + } + else if(!strncmp("AdapterType Name=\"", paRequestPartLeft, sizeof("AdapterType Name=\"") - 1)){ + if(paRequestPartLeft[18] != '*'){ //does not support query for AdapterType-Declaration + retVal = false; + } + } + return retVal; +} +#endif + + +void CommandParser::appendIdentifierName(std::string& paDest, forte::core::TNameIdentifier& paIdentifier) { + if(!paIdentifier.isEmpty()){ + for(forte::core::TNameIdentifier::CIterator runner(paIdentifier.begin()); + runner != paIdentifier.end(); ++runner){ + paDest.append(CStringDictionary::getInstance().get(*runner)); + paDest.append("."); + } + paDest.append(CStringDictionary::getInstance().get(paIdentifier.back())); + } +} + +#ifdef FORTE_SUPPORT_MONITORING + +bool CommandParser::parseMonitoringData(char *paRequestPartLeft){ + bool bRetVal = false; + if(!strncmp("Watch Source=\"", paRequestPartLeft, sizeof("Watch Source=\"") - 1)){ + int i = parseIdentifier(&(paRequestPartLeft[14]), mCommand.mFirstParam); + if(-1 != i){ + char *acBuf = strchr(&(paRequestPartLeft[i + 16]), '\"'); + if(acBuf != nullptr){ + parseIdentifier(&(acBuf[1]), mCommand.mSecondParam); + bRetVal = (-1 != i); + } + } + } + return bRetVal; +} + +std::string CommandParser::generateMonitorResponse(){ + std::string response; + if(EMGMResponse::Ready != mLastResponse){ + response.append("\n "); + response.append("\n"); + }else{ + TForteUInt16 size = static_cast(mCommand.mMonitorResponse.length() + strlen(mCommand.mID) + 74); + response.reserve(size); + + response.clear(); + response.append("\n "); + if(mCommand.mCMD == EMGMCommandType::MonitoringReadWatches) { + response.append("\n "); + response.append(mCommand.mMonitorResponse); + response.append("\n "); + } + response.append("\n"); + } + return response; +} + +#endif // FORTE_SUPPORT_MONITORING + +} // namespace forte::ita diff --git a/src/stdfblib/ita/CommandParser.h b/src/stdfblib/ita/CommandParser.h new file mode 100644 index 000000000..409946abc --- /dev/null +++ b/src/stdfblib/ita/CommandParser.h @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2024 Jose Cabral + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Jose Cabral + * - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#ifndef _COMMAND_PARSER_H +#define _COMMAND_PARSER_H + +#include "core/mgmcmd.h" +#include "core/mgmcmdstruct.h" + +#include + +class CDevice; + +namespace forte::ita { + + class CommandParser { + + public: + + CommandParser(CDevice& paDevice); + + /** + * @brief Parse and executes a commmand on a destination in a device + * + * @param paDest destination where to executed the command + * @param paCommand the command to be executed + * @param paDevice device where to execute the command + * @return EMGMResponse response of the execution of the command + */ + EMGMResponse parseAndExecuteMGMCommand(const char *const paDest, char *paCommand); + + /*! \brief Generate a response string according to the previous executed command + * + * @return generated response + */ + std::string generateResponse(); + + private: + + forte::core::SManagementCMD mCommand; + + EMGMResponse mLastResponse{EMGMResponse::InvalidObject}; + + CDevice& mDevice; + + /*! \brief Parse the given request header to determine the ID and the requested command + * + * \param paRequestString data of the request + * \param paCommand the command structure for holding command information + * \return pointer to the next part of the command zero on error + */ + char* parseRequest(char *paRequestString); + + /*! \brief Parse the given request that is left after parsing the header to parse FB data + * + * \param paRequestPartLeft data of the request that has been left after parsing the header + * \param paCommand the command structure for holding command information + * \return true if the FB data could be parsed + */ + bool parseFBData(char *paRequestPartLeft); + +#ifdef FORTE_DYNAMIC_TYPE_LOAD + + /*! \brief Parse the given request that is left after parsing the header to parse FB or Adapter type + * + * \param paRequestPartLeft data of the request that has been left after parsing the header + * \param paCommand the command structure for holding command information + * \param pa_requestType the type that should be searched + * \return true if the FB type could be parsed + */ + bool parseXType(char *paRequestPartLeft, const char *paRequestType); +#endif // FORTE_DYNAMIC_TYPE_LOAD + + /*! \brief Parse the given request that is left after parsing the header to parse connection data + * + * \param paRequestPartLeft data of the request that has been left after parsing the header + * \param paCommand the command structure for holding command information + * \return true if the connection data could be parsed + */ + bool parseConnectionData(char *paRequestPartLeft); + bool parseWriteConnectionData(char *paRequestPartLeft); + + + void parseCreateData(char *paRequestPartLeft); + void parseDeleteData(char *paRequestPartLeft); + //! Check if an FB is given for a state change command (i.e., START, STOP, KILL, RESET) + void parseAdditionalStateCommandData(char *paRequestPartLeft); + void parseReadData(char *paRequestPartLeft); + void parseWriteData(char *paRequestPartLeft); + + #ifdef FORTE_SUPPORT_QUERY_CMD + void parseQueryData(char *paRequestPartLeft); + bool parseTypeListData(char *paRequestPartLeft); + #endif + + + /*! \brief parse a hierarchical identifier list + * + * The identifiers are separated by '.' and the end character for the list is '\"' + * + * @param paIdentifierStart pointer to the start of the identifier that will be parsed + * @param paIdentifier identifier vector where to write the parsed identifiers to + * @return number of bytes used from the character array or -1 if the identifier could not be parsed + */ + int parseIdentifier(char *paIdentifierStart, forte::core::TNameIdentifier &paIdentifier); + + #ifdef FORTE_SUPPORT_MONITORING + bool parseMonitoringData(char *paRequestPartLeft); + std::string generateMonitorResponse(); + #endif //FORTE_SUPPORT_MONITORING + + /*! \brief Generate a short response string according to the previous executed command + * + * @return generated response + */ + std::string generateShortResponse(); + + /*! \brief Generate a response string according to the previous executed command + * + * @return generated response + */ + std::string generateLongResponse(); + + void appendIdentifierName(std::string& paDest, forte::core::TNameIdentifier& paIdentifier); + + }; + +} // namespace forte::ita + +#endif /*_COMMAND_PARSER_H*/ diff --git a/src/stdfblib/ita/DEV_MGR.cpp b/src/stdfblib/ita/DEV_MGR.cpp index 42068a74f..29f69cc35 100644 --- a/src/stdfblib/ita/DEV_MGR.cpp +++ b/src/stdfblib/ita/DEV_MGR.cpp @@ -56,14 +56,15 @@ const SFBInterfaceSpec DEV_MGR::scmFBInterfaceSpec = { 0, nullptr }; -const char * const DEV_MGR::scmMGMResponseTexts[13] = { "RDY", "BAD_PARAMS", "LOCAL_TERMINATION", "SYSTEM_TERMINATION", "NOT_READY", "UNSUPPORTED_CMD", "UNSUPPORTED_TYPE", "NO_SUCH_OBJECT", "INVALID_OBJECT", "INVALID_OPERATION", "INVALID_STATE", "OVERFLOW", "INVALID_DST" }; - void DEV_MGR::executeEvent(TEventID paEIID, CEventChainExecutionThread *const paECET) { if(scmEventINITID == paEIID){ #ifdef FORTE_SUPPORT_BOOT_FILE if((true == QI()) && (false == QO())){ //this is the first time init is called try to load a boot file - ForteBootFileLoader loader(*this); + ForteBootFileLoader loader( + [this](const char *const paDest, char *paCommand) -> bool { + return this->executeCommand(paDest, paCommand); + }); if(loader.needsExit()){ getDevice()->changeExecutionState(EMGMCommandType::Kill); return; @@ -85,506 +86,18 @@ void DEV_MGR::executeEvent(TEventID paEIID, CEventChainExecutionThread *const pa } void DEV_MGR::executeRQST(){ - mCommand.mAdditionalParams.clear(); char *request = new char[RQST().length() + 1]; strcpy(request, RQST().getStorage().c_str()); - EMGMResponse resp = parseAndExecuteMGMCommand(DST().getStorage().c_str(), request); - -#ifdef FORTE_SUPPORT_MONITORING - if (0 != mCommand.mMonitorResponse.length()) { - generateMonitorResponse(resp, mCommand); - } else -#endif //FORTE_SUPPORT_MONITORING - if(0 < mCommand.mAdditionalParams.length()){ - generateLongResponse(resp, mCommand); - } - else{ - generateResponse(mCommand.mID, resp); - } + mCommandParser.parseAndExecuteMGMCommand(DST().getStorage().c_str(), request); + RESP() = CIEC_STRING(mCommandParser.generateResponse()); delete[](request); } -char *DEV_MGR::parseRequest(char *paRequestString, forte::core::SManagementCMD &paCommand){ -//first check if it is an management request - char *acCommandStart = nullptr; - static const int scnCommandLength[] = {7, 7, 6, 5, 5, 6, 5, 6, 6}; - - if(!strncmp("= 7){ - return nullptr; - } - } - paRequestString[i] = '\0'; //close ID - ++i; - acCommandStart = strchr((&paRequestString[i]), '\"'); - if(acCommandStart != nullptr){ - acCommandStart++; //this is the real start of the command - if(!strncmp("CREATE", acCommandStart, 6)){ - paCommand.mCMD = EMGMCommandType::CreateGroup; - } - else if(!strncmp("DELETE", acCommandStart, 6)){ - paCommand.mCMD = EMGMCommandType::DeleteGroup; - } - else if(!strncmp("START", acCommandStart, 5)){ - paCommand.mCMD = EMGMCommandType::Start; - } - else if(!strncmp("STOP", acCommandStart, 4)){ - paCommand.mCMD = EMGMCommandType::Stop; - } - else if(!strncmp("KILL", acCommandStart, 4)){ - paCommand.mCMD = EMGMCommandType::Kill; - } - else if(!strncmp("RESET", acCommandStart, 5)){ - paCommand.mCMD = EMGMCommandType::Reset; - } - else if(!strncmp("READ", acCommandStart, 4)){ - paCommand.mCMD = EMGMCommandType::Read; - } - else if(!strncmp("WRITE", acCommandStart, 5)){ - paCommand.mCMD = EMGMCommandType::Write; - } -#ifdef FORTE_SUPPORT_QUERY_CMD - else if(!strncmp("QUERY", acCommandStart, 5)){ - paCommand.mCMD = EMGMCommandType::QueryGroup; - } -#endif - else{ - return nullptr; - } - acCommandStart += scnCommandLength[static_cast(paCommand.mCMD)]; - } - } - return acCommandStart; -} - -#ifdef FORTE_DYNAMIC_TYPE_LOAD -bool DEV_MGR::parseXType(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand, const char *paRequestType) { - bool retVal = false; - size_t nReqLength = strlen(paRequestType); - if(!strncmp(paRequestType, paRequestPartLeft, nReqLength)){ - paRequestPartLeft = &(paRequestPartLeft[nReqLength]); - if('*' != paRequestPartLeft[0]){ - int i = parseIdentifier(paRequestPartLeft, paCommand.mFirstParam); - paRequestPartLeft = (-1 == i) ? nullptr : strchr(&(paRequestPartLeft[i + 1]), '>'); - } - if(nullptr != paRequestPartLeft){ - paRequestPartLeft++; - char* endOfRequest = strchr(paRequestPartLeft, '<'); - *endOfRequest = '\0'; - forte::core::util::transformEscapedXMLToNonEscapedText(paRequestPartLeft); - paCommand.mAdditionalParams = paRequestPartLeft; - retVal = true; - } - } - return retVal; -} -#endif - -bool DEV_MGR::parseFBData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - bool retVal = false; - - if(!strncmp("FB Name=\"", paRequestPartLeft, 9)){ - char *acBuf = &(paRequestPartLeft[9]); - int i = 0; - if(acBuf[0] != '*'){ - i = parseIdentifier(acBuf, paCommand.mFirstParam); - acBuf = (-1 == i) ? nullptr : strchr(&(acBuf[i + 1]), '\"'); - } - else{ - acBuf = strchr(&(acBuf[i + 2]), '\"'); - } - - if(acBuf != nullptr){ - if(acBuf[1] != '*'){ - ++acBuf; - i = parseIdentifier(acBuf, paCommand.mSecondParam); - if(-1 != i){ - acBuf = strchr(&(acBuf[i + 1]), '\"'); - if(acBuf != nullptr){ - // We have an application name given - ++acBuf; - TForteUInt16 nBufLength = static_cast(strcspn(acBuf, "\"") + 1); - paCommand.mAdditionalParams.assign(acBuf, nBufLength); - } - } - else{ - return false; - } - } - retVal = true; - } - } - return retVal; -} - -int DEV_MGR::parseIdentifier(char *paIdentifierStart, forte::core::TNameIdentifier &paIdentifier){ - for(char *runner = paIdentifierStart, *start = paIdentifierStart; '\0' != *runner; ++runner){ - if('.' == *runner){ - *runner = '\0'; - if(!paIdentifier.pushBack(CStringDictionary::getInstance().insert(start))){ - return -1; - } - *runner = '.'; - start = runner + 1; - } else if ('"' == *runner){ - *runner = '\0'; - if(!paIdentifier.pushBack(CStringDictionary::getInstance().insert(start))){ - return -1; - } - *runner = '"'; - return static_cast(runner - paIdentifierStart); - } - } - return -1; -} - -bool DEV_MGR::parseConnectionData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - bool bRetVal = false; - if(!strncmp("Connection Source=\"", paRequestPartLeft, sizeof("Connection Source=\"") - 1)){ - int i = parseIdentifier(&(paRequestPartLeft[19]), paCommand.mFirstParam); - if(-1 != i){ - char *acBuf = strchr(&(paRequestPartLeft[i + 21]), '\"'); - if(acBuf != nullptr){ - parseIdentifier(&(acBuf[1]), paCommand.mSecondParam); - bRetVal = (-1 != i); - } - } - } - return bRetVal; -} - -bool DEV_MGR::parseWriteConnectionData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - bool retVal = false; - if(!strncmp("Connection Source=\"", paRequestPartLeft, sizeof("Connection Source=\"") - 1)){ - paRequestPartLeft = &(paRequestPartLeft[19]); - - char* endOfSource = strchr(paRequestPartLeft, '\"'); - if(nullptr == endOfSource){ - return false; - } - *endOfSource = '\0'; - char *addParams = new char[strlen(paRequestPartLeft) + 1](); - strcpy(addParams, paRequestPartLeft); - forte::core::util::transformEscapedXMLToNonEscapedText(addParams); - paCommand.mAdditionalParams = addParams; - delete[](addParams); - *endOfSource = '"'; // restore the string - paRequestPartLeft = strchr(endOfSource + 1, '\"'); - if(nullptr != paRequestPartLeft){ - retVal = (-1 != parseIdentifier(&paRequestPartLeft[1], paCommand.mFirstParam)); - } - } - return retVal; -} - -void DEV_MGR::parseCreateData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - paCommand.mCMD = EMGMCommandType::INVALID; - if(nullptr != paRequestPartLeft){ - switch (paRequestPartLeft[0]){ -#ifdef FORTE_DYNAMIC_TYPE_LOAD - case 'A': // we have an Adapter to Create - if(parseXType(paRequestPartLeft, paCommand, "AdapterType Name=\"")){ - paCommand.mCMD = EMGMCommandType::CreateAdapterType; - } - break; -#endif - case 'F': // we have an FB to Create - if(parseFBData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::CreateFBInstance; - } -#ifdef FORTE_DYNAMIC_TYPE_LOAD - else if(parseXType(paRequestPartLeft, paCommand, "FBType Name=\"")){ - paCommand.mCMD = EMGMCommandType::CreateFBType; - } -#endif - break; - case 'C': // we have an Connection to Create - if(parseConnectionData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::CreateConnection; - } - break; -#ifdef FORTE_SUPPORT_MONITORING - case 'W': // we have an Watch to Add - if(parseMonitoringData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::MonitoringAddWatch; - } - break; -#endif //FORTE_SUPPORT_MONITORING - default: - break; - } - } -} - -void DEV_MGR::parseDeleteData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - paCommand.mCMD = EMGMCommandType::INVALID; - if(nullptr != paRequestPartLeft){ - switch (paRequestPartLeft[0]){ - case 'F': // we have an FB to delete - if(parseFBData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::DeleteFBInstance; - } - break; - case 'C': // we have an Connection to delete - if(parseConnectionData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::DeleteConnection; - } - break; -#ifdef FORTE_SUPPORT_MONITORING - case 'W': // we have an Watch to remove - if(parseMonitoringData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::MonitoringRemoveWatch; - } - break; -#endif // FORTE_SUPPORT_MONITORING - default: - break; - } - } -} - -void DEV_MGR::parseAdditionalStateCommandData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - if(nullptr != paRequestPartLeft && '/' != paRequestPartLeft[0] && //if we have an additional xml token parse if it is an FB definition - !parseFBData(paRequestPartLeft, paCommand)) { - paCommand.mCMD = EMGMCommandType::INVALID; - } -} - -void DEV_MGR::parseReadData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - paCommand.mCMD = EMGMCommandType::INVALID; - if(nullptr != paRequestPartLeft){ -#ifdef FORTE_SUPPORT_MONITORING - if('W' == paRequestPartLeft[0]){ - paCommand.mCMD = EMGMCommandType::MonitoringReadWatches; - } else -#endif // FORTE_SUPPORT_MONITORING - if(parseConnectionData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::Read; - } - } -} - -void DEV_MGR::parseWriteData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - //We need an additional xml connection token parse if it is an connection definition - paCommand.mCMD = EMGMCommandType::INVALID; - if(nullptr != paRequestPartLeft && parseWriteConnectionData(paRequestPartLeft, paCommand)){ -#ifdef FORTE_SUPPORT_MONITORING - char *pch = strstr(paRequestPartLeft, "force=\""); - if (nullptr != pch) { - if (!strncmp(&pch[7], "true", sizeof("true") - 1)) { - paCommand.mCMD = EMGMCommandType::MonitoringForce; - } else if (!strncmp(&pch[7], "false", sizeof("false") - 1)) { - paCommand.mCMD = EMGMCommandType::MonitoringClearForce; - } - } else if ((2 == paCommand.mAdditionalParams.length()) && - (('$' == paCommand.mAdditionalParams[0]) && - (('e' == paCommand.mAdditionalParams[1]) ||('E' == paCommand.mAdditionalParams[1]) ))){ - paCommand.mCMD = EMGMCommandType::MonitoringTriggerEvent; - }else if ((3 == paCommand.mAdditionalParams.length()) && - (('$' == paCommand.mAdditionalParams[0]) && - (('e' == paCommand.mAdditionalParams[1]) ||('E' == paCommand.mAdditionalParams[1]) ) && - (('r' == paCommand.mAdditionalParams[2]) ||('R' == paCommand.mAdditionalParams[2]) ) )){ - paCommand.mCMD = EMGMCommandType::MonitoringResetEventCount; - }else -#endif // FORTE_SUPPORT_MONITORING - paCommand.mCMD = EMGMCommandType::Write; - } -} - -#ifdef FORTE_SUPPORT_QUERY_CMD -void DEV_MGR::parseQueryData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - paCommand.mCMD = EMGMCommandType::INVALID; - if(nullptr != paRequestPartLeft){ - switch (paRequestPartLeft[0]){ - case 'F': // query fb or fb type list - if(!strncmp(paRequestPartLeft, "FBT", sizeof("FBT") - 1)){ - if(parseTypeListData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::QueryFBTypes; - } -#ifdef FORTE_DYNAMIC_TYPE_LOAD - else if(parseXType(paRequestPartLeft, paCommand, "FBType Name=\"")){ - paCommand.mCMD = EMGMCommandType::QueryFBType; - } -#endif - else { - paCommand.mCMD = EMGMCommandType::QueryGroup; - } - }else if(parseFBData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::QueryFB; - } - break; - case 'C': // query connection list - if(parseConnectionData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::QueryConnection; - } - break; - case 'D': // query datatype list - if(!strncmp(paRequestPartLeft, "DataType", sizeof("DataType") - 1)){ - if(parseTypeListData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::QueryDTTypes; - } else { - paCommand.mCMD = EMGMCommandType::QueryGroup; - } - } - break; - case 'A': // query adaptertype list - if(!strncmp(paRequestPartLeft, "AdapterT", sizeof("AdapterT") - 1)){ - if(parseTypeListData(paRequestPartLeft, paCommand)){ - paCommand.mCMD = EMGMCommandType::QueryAdapterTypes; - } -#ifdef FORTE_DYNAMIC_TYPE_LOAD - else if(parseXType(paRequestPartLeft, paCommand, "AdapterType Name=\"")){ - paCommand.mCMD = EMGMCommandType::QueryAdapterType; - } -#endif - else { - paCommand.mCMD = EMGMCommandType::QueryGroup; - } - } - - break; - default: - break; - } - } -} - -bool DEV_MGR::parseTypeListData(char *paRequestPartLeft, forte::core::SManagementCMD &){ - bool retVal = true; - - if (!strncmp("DataType Name=\"", paRequestPartLeft, sizeof("DataType Name=\"") - 1)) { - if(paRequestPartLeft[15] != '*'){ //does not support query for DataType-Declaration - retVal = false; - } - } - else if(!strncmp("FBType Name=\"", paRequestPartLeft, sizeof("FBType Name=\"") - 1)){ - if(paRequestPartLeft[13] != '*'){ //supports query for FBType-Declaration only for DynamicTypeLoad profile (LUA enabled) - retVal = false; - } - } - else if(!strncmp("AdapterType Name=\"", paRequestPartLeft, sizeof("AdapterType Name=\"") - 1)){ - if(paRequestPartLeft[18] != '*'){ //does not support query for AdapterType-Declaration - retVal = false; - } - } - return retVal; -} -#endif - -void DEV_MGR::generateResponse(const char *paID, EMGMResponse paResp){ - RESP().clear(); - RESP().append(""); -} - -void DEV_MGR::generateLongResponse(EMGMResponse paResp, forte::core::SManagementCMD &paCMD){ - RESP().clear(); - RESP().reserve(static_cast(255 + (paCMD.mAdditionalParams.length()))); - RESP().append("\n "); - } - else{ - RESP().append(">\n "); - if(paCMD.mCMD == EMGMCommandType::Read){ - RESP().append(""); - } -#ifdef FORTE_SUPPORT_QUERY_CMD - else if(paCMD.mCMD == EMGMCommandType::QueryConnection){ - if ((paCMD.mFirstParam.isEmpty()) && - (paCMD.mSecondParam.isEmpty())) { //src & dst = * - RESP().append(paCMD.mAdditionalParams); - } - else { //either src or dst = * (both != * should be treated by generateResponse - RESP().append("\n "); - RESP().append(paCMD.mAdditionalParams); - RESP().append("\n "); - } - } - else if(paCMD.mCMD == EMGMCommandType::QueryFB){ - if(!paCMD.mFirstParam.isEmpty()) { //Name != "*" - if(!paCMD.mSecondParam.isEmpty()){ //Type != "*" - RESP().append(""); - } else { //Type == "*" - RESP().append(""); - } - } - else{ - RESP().append("\n "); - RESP().append(paCMD.mAdditionalParams); - RESP().append("\n "); - } - } - else if(paCMD.mCMD == EMGMCommandType::QueryFBTypes || paCMD.mCMD == EMGMCommandType::QueryAdapterTypes){ - RESP().append("\n "); - RESP().append(paCMD.mAdditionalParams); - RESP().append("\n "); - } - else if(paCMD.mCMD == EMGMCommandType::QueryDTTypes){ - RESP().append("\n "); - RESP().append(paCMD.mAdditionalParams); - RESP().append("\n "); - } - else if(paCMD.mCMD == EMGMCommandType::QueryFBType){ - RESP().append(""); - } - else if(paCMD.mCMD == EMGMCommandType::QueryAdapterType){ - RESP().append("\n"); - } -#endif - } - RESP().append("\n"); -} - -void DEV_MGR::appendIdentifierName(CIEC_STRING& paDest, forte::core::TNameIdentifier& paIdentifier) { - if(!paIdentifier.isEmpty()){ - for(forte::core::TNameIdentifier::CIterator runner(paIdentifier.begin()); - runner != paIdentifier.end(); ++runner){ - paDest.append(CStringDictionary::getInstance().get(*runner)); - paDest.append("."); - } - paDest.append(CStringDictionary::getInstance().get(paIdentifier.back())); - } -} - DEV_MGR::DEV_MGR(CStringDictionary::TStringId paInstanceNameId, forte::core::CFBContainer &paContainer) : CCommFB(paInstanceNameId, paContainer, forte::com_infra::e_Server), - mDevice(*paContainer.getDevice()) { + mDevice(*paContainer.getDevice()), mCommandParser(mDevice) { getGenInterfaceSpec() = scmFBInterfaceSpec; } @@ -592,8 +105,6 @@ bool DEV_MGR::initialize() { if(!CCommFB::initialize()) { return false; } - mCommand.mAdditionalParams.reserve(255); - mCommand.mAdditionalParams.clear(); return true; } @@ -602,118 +113,10 @@ DEV_MGR::~DEV_MGR(){ getGenInterfaceSpec() = {}; //block any wrong cleanup in the generic fb base class of CBaseCommFB } -EMGMResponse DEV_MGR::parseAndExecuteMGMCommand(const char *const paDest, char *paCommand){ - EMGMResponse eResp = EMGMResponse::InvalidObject; - if(nullptr != strchr(paCommand, '>')){ - mCommand.mDestination = (strlen(paDest) != 0) ? CStringDictionary::getInstance().insert(paDest) : CStringDictionary::scmInvalidStringId; - mCommand.mFirstParam.clear(); - mCommand.mSecondParam.clear(); - if ( 255 <= mCommand.mAdditionalParams.capacity()) { - mCommand.mAdditionalParams.reserve(255); - } - mCommand.mID=nullptr; -#ifdef FORTE_SUPPORT_MONITORING - mCommand.mMonitorResponse.clear(); -#endif // FORTE_SUPPORT_MONITORING - char *acRequestPartLeft = parseRequest(paCommand, mCommand); - if(nullptr != acRequestPartLeft){ - acRequestPartLeft = strchr(acRequestPartLeft, '<'); - if(nullptr != acRequestPartLeft){ - acRequestPartLeft++; //point to the next character after the < - } - // we got the command for execution - // now check the rest of the data - switch (mCommand.mCMD){ - case EMGMCommandType::CreateGroup: // create something - parseCreateData(acRequestPartLeft, mCommand); - break; - case EMGMCommandType::DeleteGroup: //delete something - parseDeleteData(acRequestPartLeft, mCommand); - break; - case EMGMCommandType::Start: - case EMGMCommandType::Stop: - case EMGMCommandType::Kill: - case EMGMCommandType::Reset: - parseAdditionalStateCommandData(acRequestPartLeft, mCommand); - break; - case EMGMCommandType::Read: - parseReadData(acRequestPartLeft, mCommand); - break; - case EMGMCommandType::Write: - parseWriteData(acRequestPartLeft, mCommand); - break; -#ifdef FORTE_SUPPORT_QUERY_CMD - case EMGMCommandType::QueryGroup: // query something - parseQueryData(acRequestPartLeft, mCommand); -#endif - break; - default: - break; - } - - if(EMGMCommandType::INVALID != mCommand.mCMD) { - eResp = mDevice.executeMGMCommand(mCommand); - } - } - else { - eResp = EMGMResponse::UnsupportedCmd; - } - } - return eResp; -} - -#ifdef FORTE_SUPPORT_MONITORING - -bool DEV_MGR::parseMonitoringData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand){ - bool bRetVal = false; - if(!strncmp("Watch Source=\"", paRequestPartLeft, sizeof("Watch Source=\"") - 1)){ - int i = parseIdentifier(&(paRequestPartLeft[14]), paCommand.mFirstParam); - if(-1 != i){ - char *acBuf = strchr(&(paRequestPartLeft[i + 16]), '\"'); - if(acBuf != nullptr){ - parseIdentifier(&(acBuf[1]), paCommand.mSecondParam); - bRetVal = (-1 != i); - } - } - } - return bRetVal; -} - -void DEV_MGR::generateMonitorResponse(EMGMResponse paResp, forte::core::SManagementCMD &paCMD){ - RESP().clear(); - if(EMGMResponse::Ready != paResp){ - RESP().append("\n "); - RESP().append("\n"); - }else{ - TForteUInt16 size = static_cast(paCMD.mMonitorResponse.length() + strlen(paCMD.mID) + 74); - RESP().reserve(size); - - RESP().clear(); - RESP().append("\n "); - if(paCMD.mCMD == EMGMCommandType::MonitoringReadWatches) { - RESP().append("\n "); - RESP().append(paCMD.mMonitorResponse); - RESP().append("\n "); - } - RESP().append("\n"); - } - paCMD.mMonitorResponse.clear(); -} - -#endif // FORTE_SUPPORT_MONITORING - bool DEV_MGR::executeCommand(const char *const paDest, char *paCommand){ - EMGMResponse eResp = parseAndExecuteMGMCommand(paDest, paCommand); + EMGMResponse eResp = mCommandParser.parseAndExecuteMGMCommand(paDest, paCommand); if(eResp != EMGMResponse::Ready){ - DEVLOG_ERROR("Boot file error. DEV_MGR says error is %s\n", DEV_MGR::getResponseText(eResp)); + DEVLOG_ERROR("Boot file error. DEV_MGR says error is %s\n", forte::mgm_cmd::getResponseText(eResp).c_str()); } return (eResp == EMGMResponse::Ready); } diff --git a/src/stdfblib/ita/DEV_MGR.h b/src/stdfblib/ita/DEV_MGR.h index 5d34ef89c..5d1997755 100644 --- a/src/stdfblib/ita/DEV_MGR.h +++ b/src/stdfblib/ita/DEV_MGR.h @@ -17,13 +17,13 @@ #include #include #include -#include "IBootFileCallback.h" +#include "CommandParser.h" class CDevice; /*! \brief Implementation of the DEV_MGR FB. */ -class DEV_MGR: public forte::com_infra::CCommFB, public IBootFileCallback { +class DEV_MGR: public forte::com_infra::CCommFB { DECLARE_FIRMWARE_FB(DEV_MGR) public: @@ -32,18 +32,9 @@ class DEV_MGR: public forte::com_infra::CCommFB, public IBootFileCallback { bool initialize() override; - bool executeCommand(const char *const paDest, char *paCommand) override; - - static const char *getResponseText(EMGMResponse paResp) { - return scmMGMResponseTexts[static_cast>(paResp)]; - } - private: - /*!\brief Type for the response of MGM command messages - * - * TODO fully define all responses as defined in IEC 61499 inc. numbers. - */ - static const char * const scmMGMResponseTexts[13]; + + bool executeCommand(const char *const paDest, char *paCommand); EMGMResponse parseAndExecuteMGMCommand(const char *const paDest, char *paCommand); @@ -71,84 +62,12 @@ class DEV_MGR: public forte::com_infra::CCommFB, public IBootFileCallback { //! The device the block is contained in CDevice &mDevice; + forte::ita::CommandParser mCommandParser; + void executeRQST(); - /*! \brief Parse the given request header to determine the ID and the requested command - * - * \param paRequestString data of the request - * \param paCommand the command structure for holding command information - * \return pointer to the next part of the command zero on error - */ - static char* parseRequest(char *paRequestString, forte::core::SManagementCMD &paCommand); - /*! \brief Parse the given request that is left after parsing the header to parse FB data - * - * \param paRequestPartLeft data of the request that has been left after parsing the header - * \param paCommand the command structure for holding command information - * \return true if the FB data could be parsed - */ - static bool parseFBData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - /*! \brief Parse the given request that is left after parsing the header to parse FB or Adapter type - * - * \param paRequestPartLeft data of the request that has been left after parsing the header - * \param paCommand the command structure for holding command information - * \param pa_requestType the type that should be searched - * \return true if the FB type could be parsed - */ - static bool parseXType(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand, const char *paRequestType); - /*! \brief Parse the given request that is left after parsing the header to parse connection data - * - * \param paRequestPartLeft data of the request that has been left after parsing the header - * \param paCommand the command structure for holding command information - * \return true if the connection data could be parsed - */ - static bool parseConnectionData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - static bool parseWriteConnectionData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - - - static void parseCreateData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - static void parseDeleteData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - //! Check if an FB is given for a state change command (i.e., START, STOP, KILL, RESET) - static void parseAdditionalStateCommandData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - static void parseReadData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - static void parseWriteData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - -#ifdef FORTE_SUPPORT_QUERY_CMD - static void parseQueryData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - static bool parseTypeListData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); -#endif - - - /*! \brief parse a hierarchical identifier list - * - * The identifiers are separated by '.' and the end character for the list is '\"' - * - * @param paIdentifierStart pointer to the start of the identifier that will be parsed - * @param paIdentifier identifier vector where to write the parsed identifiers to - * @return number of bytes used from the character array or -1 if the identifier could not be parsed - */ - static int parseIdentifier(char *paIdentifierStart, forte::core::TNameIdentifier &paIdentifier); void executeEvent(TEventID paEIID, CEventChainExecutionThread *const paECET) override; -#ifdef FORTE_SUPPORT_MONITORING - static bool parseMonitoringData(char *paRequestPartLeft, forte::core::SManagementCMD &paCommand); - void generateMonitorResponse(EMGMResponse paResp, forte::core::SManagementCMD &paCMD); -#endif //FORTE_SUPPORT_MONITORING - - /*! \brief set the RESP output of the DEV_MGR according to the given response data - * - * \param paID id of the response - * \param paResp qualifier of the response - */ - void generateResponse(const char *paID, EMGMResponse paResp); - /*! \brief set the RESP output of the DEV_MGR according to the given response data - * - * \param paID id of the response - * \param paResp qualifier of the response - * \param paCMD the command type - */ - void generateLongResponse(EMGMResponse paResp, forte::core::SManagementCMD &paCMD); - static void appendIdentifierName(CIEC_STRING& paDest, forte::core::TNameIdentifier& paIdentifier); - CIEC_BOOL &QI() { return *static_cast(getDI(0)); }; @@ -177,7 +96,6 @@ class DEV_MGR: public forte::com_infra::CCommFB, public IBootFileCallback { return *static_cast(getDO(3)); }; - forte::core::SManagementCMD mCommand; }; #endif /*DEV_MGR_H_*/ diff --git a/src/stdfblib/ita/ForteBootFileLoader.cpp b/src/stdfblib/ita/ForteBootFileLoader.cpp index afcb7f668..493a7dcdd 100644 --- a/src/stdfblib/ita/ForteBootFileLoader.cpp +++ b/src/stdfblib/ita/ForteBootFileLoader.cpp @@ -17,15 +17,14 @@ #include "ForteBootFileLoader.h" #include "../../arch/devlog.h" #include "../../../src/core/datatypes/forte_string.h" -#include "IBootFileCallback.h" #include "mgmcmd.h" #include "mgmcmdstruct.h" #include "../../core/device.h" char* gCommandLineBootFile = nullptr; -ForteBootFileLoader::ForteBootFileLoader(IBootFileCallback &paCallback) : mBootfile(nullptr), mCallback(paCallback), mNeedsExit(false){ - openBootFile(); +ForteBootFileLoader::ForteBootFileLoader(BootFileCallback paCallback, std::optional paPathToFile) : mCallback(paCallback) { + openBootFile(paPathToFile); } ForteBootFileLoader::~ForteBootFileLoader() { @@ -35,23 +34,29 @@ ForteBootFileLoader::~ForteBootFileLoader() { } } -bool ForteBootFileLoader::openBootFile() { +bool ForteBootFileLoader::openBootFile(std::optional paPathToFile) { bool retVal = false; std::string bootFileName; - if(gCommandLineBootFile) { - DEVLOG_INFO("Using provided bootfile location set in the command line: %s\n", gCommandLineBootFile); - bootFileName = std::string(gCommandLineBootFile); + if(paPathToFile.has_value()){ + bootFileName = paPathToFile.value(); + DEVLOG_INFO("Using provided bootfile location passed as parameter: %s\n", bootFileName.c_str()); } else { - // select provided or default boot file name - char * envBootFileName = forte_getenv("FORTE_BOOT_FILE"); - if(nullptr != envBootFileName) { - DEVLOG_INFO("Using provided bootfile location from environment variable: %s\n", envBootFileName); - bootFileName = std::string(envBootFileName); + if(gCommandLineBootFile) { + DEVLOG_INFO("Using provided bootfile location set in the command line: %s\n", gCommandLineBootFile); + bootFileName = std::string(gCommandLineBootFile); } else { - DEVLOG_INFO("Using provided bootfile location set in CMake: %s\n", FORTE_BOOT_FILE_LOCATION); - bootFileName = std::string(FORTE_BOOT_FILE_LOCATION); + // select provided or default boot file name + char * envBootFileName = forte_getenv("FORTE_BOOT_FILE"); + if(nullptr != envBootFileName) { + DEVLOG_INFO("Using provided bootfile location from environment variable: %s\n", envBootFileName); + bootFileName = std::string(envBootFileName); + } else { + DEVLOG_INFO("Using provided bootfile location set in CMake: %s\n", FORTE_BOOT_FILE_LOCATION); + bootFileName = std::string(FORTE_BOOT_FILE_LOCATION); + } } } + // check if we finally have a boot file name if(bootFileName.empty()){ @@ -92,7 +97,7 @@ LoadBootResult ForteBootFileLoader::loadBootFile(){ std::string destination(line.substr(0, sepPosition)); char *commandBuffer = new char[command.length() + 1]{}; strcpy(commandBuffer, command.c_str()); - if(!mCallback.executeCommand(destination.c_str(), commandBuffer)) { + if(!mCallback(destination.c_str(), commandBuffer)) { //command was not successful DEVLOG_ERROR("Boot file command could not be executed. Line: %d: %s\n", nLineCount, commandBuffer); eResp = EXTERNAL_ERROR; diff --git a/src/stdfblib/ita/ForteBootFileLoader.h b/src/stdfblib/ita/ForteBootFileLoader.h index b1beb5500..fd75abff4 100644 --- a/src/stdfblib/ita/ForteBootFileLoader.h +++ b/src/stdfblib/ita/ForteBootFileLoader.h @@ -19,9 +19,10 @@ #include "../../arch/forte_fileio.h" #include +#include +#include class CIEC_STRING; -class IBootFileCallback; enum LoadBootResult { LOAD_RESULT_OK, @@ -33,11 +34,14 @@ enum LoadBootResult { class ForteBootFileLoader { public: + using BootFileCallback = std::function; + + /** * Constructor which uses the the default values for the boot file location * @param paCallback Object to be called for each command */ - explicit ForteBootFileLoader(IBootFileCallback &paCallback); + explicit ForteBootFileLoader(BootFileCallback paCallback, std::optional paPathToFile = std::nullopt); ~ForteBootFileLoader(); @@ -52,11 +56,11 @@ class ForteBootFileLoader { } private: - decltype(forte_fopen(nullptr, nullptr)) mBootfile; - IBootFileCallback &mCallback; //for now with one callback is enough for all cases - bool mNeedsExit; + decltype(forte_fopen(nullptr, nullptr)) mBootfile{nullptr}; + BootFileCallback mCallback; //for now with one callback is enough for all cases + bool mNeedsExit{false}; - bool openBootFile(); + bool openBootFile(std::optional paPathToFile); bool readLine(std::string &line); bool hasCommandEnded(const std::string &line) const; }; diff --git a/src/stdfblib/ita/IBootFileCallback.h b/src/stdfblib/ita/IBootFileCallback.h deleted file mode 100644 index fa47448af..000000000 --- a/src/stdfblib/ita/IBootFileCallback.h +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2017 fortiss GmbH - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Jose Cabral - * - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#include - -#ifndef SRC_STDFBLIB_ITA_IBOOTFILECALLBACK_H_ -#define SRC_STDFBLIB_ITA_IBOOTFILECALLBACK_H_ - -class IBootFileCallback{ - public: - virtual bool executeCommand(const char *const paDest, char *paCommand) = 0; -}; - -#endif /* SRC_STDFBLIB_ITA_IBOOTFILECALLBACK_H_ */