diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp index 2936e1f2ffb4d7c5f7f41e281cde943c9936969a..ea4e826676da2b4cae96846c754e79b4607ebf01 100644 --- a/inc/ErrorHandler.hpp +++ b/inc/ErrorHandler.hpp @@ -200,6 +200,31 @@ public: * Attempt to add new statistic definition but the maximum number is already reached (ST[04]) */ MaxStatisticDefinitionsReached = 21, + /** + * Attempt to add a new report type, when the addition of all report types is already enabled in the + * Application Process configuration (ST[14]) + */ + AdditionOfAllReportTypesAlreadyEnabled = 22, + /** + * Attempt to add a new service type, when the addition of all service types is already enabled in the + * Application Process configuration (ST[14]) + */ + AdditionOfAllServiceTypesAlreadyEnabled = 23, + /** + * Attempt to add a new report type, when the max number of reports types allowed per service type + * definition in the Application Process configuration is already reached (ST[14]) + */ + MaxReportTypeDefinitionsReached = 24, + /** + * Attempt to add a new service type, when the max number of service types allowed per application process + * definition in the Application Process configuration is already reached (ST[14]) + */ + MaxServiceTypesReached = 25, + /** + * Attempt to add a report/event definition/housekeeping report type, when the specified application process + * ID is not controlled by the Service (ST[14]) + */ + ApplicationNotControlled = 26, }; /** diff --git a/inc/Helpers/ForwardControlConfiguration.hpp b/inc/Helpers/ForwardControlConfiguration.hpp index 2c2f1f3a8dbda25e4af795f8446046139c1843ad..aad43f1899734447bfd13f73fdbfbb5ad0426066 100644 --- a/inc/Helpers/ForwardControlConfiguration.hpp +++ b/inc/Helpers/ForwardControlConfiguration.hpp @@ -22,6 +22,18 @@ namespace ForwardControlConfiguration */ class ApplicationProcess { public: + /** + * Empty report type vector, can both mean that we haven't added report types yet, and added all report types. To + * be able to distinguish what the current 'empty' state means, we need this indicator. + */ + bool notEmptyReports = false; + + /** + * Empty service type vector, can both mean that we haven't added service types yet, and added all service types. To + * be able to distinguish what the current 'empty' state means, we need this indicator. + */ + bool notEmptyServices = false; + /** * Vector containing the Report Type definitions. Each definition has its unique name of type uint8. For * example, a Report Type definition could be 'ReportHousekeepingStructures'. @@ -39,7 +51,9 @@ public: * Map containing the Application Process definitions. Each application has its own ID. The ID is used as a * key to provide access to the list of Service Type definitions, included by the application. */ - typedef etl::map<uint8_t, serviceTypeDefinitions, ECSSMaxControlledApplications> applicationProcessDefinitions; + etl::map<uint8_t, serviceTypeDefinitions, ECSSMaxControlledApplications> definitions; + + ApplicationProcess() = default; }; /** @@ -62,7 +76,7 @@ public: * Map containing the Housekeeping definitions (application processes). Each application has its own ID. The ID is * used as a key to provide access to the list of the Housekeeping structure IDs. */ - typedef etl::map<uint8_t, housekeepingStructureIds, ECSSMaxControlledApplications> housekeepingDefinitions; + typedef etl::map<uint8_t, housekeepingStructureIds, ECSSMaxControlledApplications> definitions; }; /** @@ -85,7 +99,7 @@ public: * Map containing the Event Report Blocking definitions (applications). Each application has its own ID. The ID is * used as a key to provide access to the list of the Event Definitions. */ - typedef etl::map<uint8_t, eventDefinitionIds, ECSSMaxControlledApplications> eventReportBlockingDefinitions; + typedef etl::map<uint8_t, eventDefinitionIds, ECSSMaxControlledApplications> definitions; }; } // namespace ForwardControlConfiguration diff --git a/inc/Services/RealTimeForwardingControlService.hpp b/inc/Services/RealTimeForwardingControlService.hpp index 03e992a6e91de1d43d85a571902f48182a33e4ea..2f522cc04f28573198f2a39a516c3da855f5abe5 100644 --- a/inc/Services/RealTimeForwardingControlService.hpp +++ b/inc/Services/RealTimeForwardingControlService.hpp @@ -42,13 +42,48 @@ private: */ etl::vector<uint8_t, ECSSMaxControlledApplications> controlledApplications; + ForwardControlConfiguration::ApplicationProcess applicationProcessConfiguration; + ForwardControlConfiguration::HousekeepingParameterReport housekeepingConfiguration; + ForwardControlConfiguration::EventReportBlocking eventReportBlockingConfiguration; + + /** + * Performs the necessary error checking/logging for a specific application process ID. Also, skips the necessary + * bytes from the request message, in case of an invalid request. + */ + bool checkApplication1(Message& request, uint8_t applicationID, uint8_t numOfServices); + /** * Checks if the specified application process is controlled by the Service and returns true if it does. */ - bool appIsControlled(uint8_t applicationId); + bool appIsControlled(Message& request, uint8_t applicationId); - ForwardControlConfiguration::ApplicationProcess applicationProcessConfiguration; - ForwardControlConfiguration::HousekeepingParameterReport housekeepingConfiguration; + /** + * Checks if all service types are allowed already, i.e. if the application process contains no service type + * definitions. + */ + bool allServiceTypesAllowed(Message& request, uint8_t applicationID); + + /** + * Checks if the maximum number of service type definitions per application process is reached. + */ + bool maxServiceTypesReached(Message& request, uint8_t applicationID); + + /** + * Performs the necessary error checking/logging for a specific service type. Also, skips the necessary bytes + * from the request message, in case of an invalid request. + */ + bool checkService1(Message& request, uint8_t applicationID, uint8_t serviceType, uint8_t numOfMessages); + + /** + * Checks if all report types are allowed already, i.e. if the service type definition contains no report type + * definitions. + */ + bool allReportTypesAllowed(Message& request, uint8_t applicationID, uint8_t serviceType); + + /** + * Checks if the maximum number of report type definitions per service type definition is reached. + */ + bool maxReportTypesReached(Message& request, uint8_t applicationID, uint8_t serviceType); public: /** diff --git a/src/Services/RealTimeForwardingControlService.cpp b/src/Services/RealTimeForwardingControlService.cpp index 1f3c8d15d219f2447e7dcd11a3c5a7e3a1ba5626..329f1f7356e4dc41fafa0f6c4ce12f9b511cf7c1 100644 --- a/src/Services/RealTimeForwardingControlService.cpp +++ b/src/Services/RealTimeForwardingControlService.cpp @@ -1,8 +1,114 @@ #include "Services/RealTimeForwardingControlService.hpp" -bool RealTimeForwardingControlService::appIsControlled(uint8_t applicationId) { - return std::find(controlledApplications.begin(), controlledApplications.end(), applicationId) != - controlledApplications.end(); +bool RealTimeForwardingControlService::appIsControlled(Message& request, uint8_t applicationId) { + if (std::find(controlledApplications.begin(), controlledApplications.end(), applicationId) == + controlledApplications.end()) { + ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::ApplicationNotControlled); + return false; + } + return true; +} + +bool RealTimeForwardingControlService::checkApplication1(Message& request, uint8_t applicationID, + uint8_t numOfServices) { + if (not appIsControlled(request, applicationID) or allServiceTypesAllowed(request, applicationID) or + maxServiceTypesReached(request, applicationID)) { + for (uint8_t l = 0; l < numOfServices; l++) { + request.skipBytes(1); + uint8_t numOfMessages = request.readUint8(); + request.skipBytes(numOfMessages); + } + return false; + } + return true; +} + +bool RealTimeForwardingControlService::allServiceTypesAllowed(Message& request, uint8_t applicationID) { + if (applicationProcessConfiguration.definitions[applicationID].empty() and + applicationProcessConfiguration.notEmptyServices) { + ErrorHandler::reportError(request, + ErrorHandler::ExecutionStartErrorType::AdditionOfAllServiceTypesAlreadyEnabled); + return true; + } + return false; +} + +bool RealTimeForwardingControlService::maxServiceTypesReached(Message& request, uint8_t applicationID) { + if (applicationProcessConfiguration.definitions[applicationID].size() >= ECSSMaxServiceTypeDefinitions) { + ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached); + return true; + } + return false; +} + +bool RealTimeForwardingControlService::checkService1(Message& request, uint8_t applicationID, uint8_t serviceType, + uint8_t numOfMessages) { + if (allReportTypesAllowed(request, applicationID, serviceType) or + maxReportTypesReached(request, applicationID, serviceType)) { + request.skipBytes(numOfMessages); + return false; + } + return true; +} + +bool RealTimeForwardingControlService::allReportTypesAllowed(Message& request, uint8_t applicationID, + uint8_t serviceType) { + if (applicationProcessConfiguration.definitions[applicationID][serviceType].empty() and + applicationProcessConfiguration.notEmptyReports) { + ErrorHandler::reportError(request, + ErrorHandler::ExecutionStartErrorType::AdditionOfAllReportTypesAlreadyEnabled); + return true; + } + return false; +} + +bool RealTimeForwardingControlService::maxReportTypesReached(Message& request, uint8_t applicationID, + uint8_t serviceType) { + if (applicationProcessConfiguration.definitions[applicationID][serviceType].size() >= + ECSSMaxReportTypeDefinitions) { + ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxReportTypeDefinitionsReached); + return true; + } + return false; +} + +void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(Message& request) { + request.assertTC(ServiceType, MessageType::AddReportTypesToAppProcessConfiguration); + uint8_t numOfApplications = request.readUint16(); + + for (uint8_t i = 0; i < numOfApplications; i++) { + uint8_t applicationID = request.readUint8(); + uint8_t numOfServices = request.readUint8(); + + if (not checkApplication1(request, applicationID, numOfServices)) { + continue; + } + + // if (numOfServices == 0) { + // // todo: add all report types of the application process to the configuration. + // continue; + // } + + for (uint8_t j = 0; j < numOfServices; j++) { + uint8_t serviceType = request.readUint8(); + // todo: check if service type is valid. + uint8_t numOfMessages = request.readUint8(); + + if (not checkService1(request, applicationID, serviceType, numOfMessages)) { + continue; + } + + // if (numOfMessages == 0) { + // // todo: add all report types of the service type to the configuration. + // continue; + // } + + for (uint8_t k = 0; k < numOfMessages; k++) { + uint8_t messageType = request.readUint8(); + // todo: check if message type is valid. + } + } + } } void RealTimeForwardingControlService::execute(Message& message) {