diff --git a/.gitmodules b/.gitmodules
index c30fec28aea7f8a5584f89122ff9fc8a58a6863a..ebb319f25194b99f4bf61ba4c2415525d7a86ec0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,12 +1,12 @@
 [submodule "lib/Catch2"]
-	path = lib/Catch2
-	url = https://github.com/catchorg/Catch2.git
+    path = lib/Catch2
+    url = https://github.com/catchorg/Catch2.git
 [submodule "lib/etl"]
-	path = lib/etl
-	url = https://github.com/ETLCPP/etl.git
+    path = lib/etl
+    url = https://github.com/ETLCPP/etl.git
 [submodule "ci/page_style/doxygen_dark_theme"]
-	path = ci/page_style/doxygen_dark_theme
-	url = https://github.com/MaJerle/doxygen_dark_theme.git
+    path = ci/page_style/doxygen_dark_theme
+    url = https://github.com/MaJerle/doxygen_dark_theme.git
 [submodule "lib/logger"]
-	path = lib/logger
-	url = https://gitlab.com/acubesat/obc/logger.git
+    path = lib/logger
+    url = https://gitlab.com/acubesat/obc/logger.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3e5c2dee5446dfbb812365dd96086ae1574fbfd2..24ae6a8fd012616ff86b4a546faef0c52dd084a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,7 +45,9 @@ add_library(common OBJECT
         src/Services/ParameterStatisticsService.cpp
         src/Services/OnBoardMonitoringService.cpp
         src/Helpers/Statistic.cpp
+        src/Services/RealTimeForwardingControlService.cpp
         src/Helpers/PMONBase.cpp
+        src/Helpers/AllMessageTypes.cpp
         )
 
 # Specify the .cpp files for the executables
diff --git a/inc/ECSS_Definitions.hpp b/inc/ECSS_Definitions.hpp
index 01fc74b1db03fab7a40ea7d22c3a58d5c46a4429..24c490d77bb42b615960788e50d9c0ad8f4d22c8 100644
--- a/inc/ECSS_Definitions.hpp
+++ b/inc/ECSS_Definitions.hpp
@@ -183,6 +183,42 @@ inline const uint16_t ECSSPacketStoreIdSize = 15;
  */
 inline const uint8_t ECSSMaxHousekeepingStructures = 10;
 
+/**
+ * The max number of controlled application processes
+ * @see RealTimeForwardingControlService
+ */
+inline const uint8_t ECSSMaxControlledApplicationProcesses = 5;
+
+/**
+ * The max number of report type blocking definitions per service type definition in the application process
+ * configuration
+ * @see RealTimeForwardingControlService
+ * todo: must change when a service with more report types is implemented.
+ */
+inline const uint8_t ECSSMaxReportTypeDefinitions = 20;
+
+/**
+ * The max number of service type definitions per application process type definition in the application process
+ * configuration
+ * @see RealTimeForwardingControlService
+ * todo: must change when all 15 services are implemented.
+ */
+inline const uint8_t ECSSMaxServiceTypeDefinitions = 10;
+
+/**
+ * The number of possible combinations between application processes and service types, i.e. the number of all
+ * possible (applicationID, serviceType) pairs.
+ */
+inline const uint8_t ECSSMaxApplicationsServicesCombinations = ECSSMaxControlledApplicationProcesses *
+                                                               ECSSMaxServiceTypeDefinitions;
+
+/**
+ * The max number of event definition IDs per event report blocking type definition in the event report blocking
+ * configuration
+ * @see RealTimeForwardingControlService
+ */
+inline const uint8_t ECSSMaxEventDefinitionIDs = 15;
+
 /**
  * Limits noting the minimum and maximum valid Virtual Channels used by the Storage and Retrieval subservice
  */
@@ -196,6 +232,5 @@ inline struct {
  */
 inline const uint8_t ECSSMaxMonitoringDefinitions = 4;
 
-
 /** @} */
 #endif // ECSS_SERVICES_ECSS_DEFINITIONS_H
diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp
index bffa26ddb99f9bfc607acf557c2f111329a00a5f..351a75caba2833cef379c3d5af9549de4022572c 100644
--- a/inc/ErrorHandler.hpp
+++ b/inc/ErrorHandler.hpp
@@ -1,8 +1,8 @@
 #ifndef PROJECT_ERRORHANDLER_HPP
 #define PROJECT_ERRORHANDLER_HPP
 
-#include <type_traits>
 #include <stdint.h> // for the uint_8t stepID
+#include <type_traits>
 
 // Forward declaration of the class, since its header file depends on the ErrorHandler
 class Message;
@@ -323,7 +323,27 @@ public:
 		/**
 		 * Request to report a non existent parameter monitoring definition.
 		 */
-		ReportParameterNotInTheParameterMonitoringList = 46
+		ReportParameterNotInTheParameterMonitoringList = 46,
+		/**
+		 * Attempt to add a new service type, when the addition of all service types is already enabled in the
+		 * Application Process configuration (ST[14])
+		 */
+		AllServiceTypesAlreadyAllowed = 47,
+		/**
+		 * 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])
+		 */
+		MaxReportTypesReached = 48,
+		/**
+		 * 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 = 49,
+		/**
+		 * Attempt to add a report/event definition/housekeeping report type, when the specified application process
+		 * ID is not controlled by the Service (ST[14])
+		 */
+		NotControlledApplication = 50,
 	};
 
 	/**
diff --git a/inc/Helpers/AllMessageTypes.hpp b/inc/Helpers/AllMessageTypes.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb5c2c488647f0b54fa783dd09c72eff28801092
--- /dev/null
+++ b/inc/Helpers/AllMessageTypes.hpp
@@ -0,0 +1,20 @@
+#ifndef ECSS_SERVICES_ALLMESSAGETYPES_HPP
+#define ECSS_SERVICES_ALLMESSAGETYPES_HPP
+
+#include "ECSS_Definitions.hpp"
+#include <etl/map.h>
+#include <etl/vector.h>
+
+/**
+ * Namespace containing all the message types for every service type.
+ */
+namespace AllMessageTypes {
+	/**
+	 * Map containing all the message types, per service. The key is the ServiceType and the value,
+	 * an etl vector containing the message types.
+	 */
+	extern etl::map<uint8_t, etl::vector<uint8_t, ECSSMaxReportTypeDefinitions>, ECSSMaxServiceTypeDefinitions> messagesOfService;
+
+} // namespace AllMessageTypes
+
+#endif
diff --git a/inc/Helpers/ForwardControlConfiguration.hpp b/inc/Helpers/ForwardControlConfiguration.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..da573dd1ff4979caaa4ed8953fb88874ee3a1e35
--- /dev/null
+++ b/inc/Helpers/ForwardControlConfiguration.hpp
@@ -0,0 +1,47 @@
+#ifndef ECSS_SERVICES_FORWARDCONTROLCONFIGURATION_HPP
+#define ECSS_SERVICES_FORWARDCONTROLCONFIGURATION_HPP
+
+#include "ECSS_Definitions.hpp"
+#include "ErrorHandler.hpp"
+#include "Helpers/Parameter.hpp"
+#include "etl/map.h"
+#include "etl/vector.h"
+
+/**
+ * The Application Process configuration. It's basically a map, storing a vector of report type definitions for each
+ * pair of (applicationID, serviceType). It contains definitions, which indicate whether a telemetry message, produced
+ * by a service, inside an application process (subsystem), should be forwarded to the ground station.
+ */
+class ApplicationProcessConfiguration {
+public:
+	/**
+	 * Vector containing the Report Type definitions. Each definition has its unique name of type uint8. For
+	 * example, a Report Type definition could be 'ReportHousekeepingStructures'.
+	 */
+	typedef etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> ReportTypeDefinitions;
+
+	/**
+	 * This is the key for the application process configuration map. It contains a pair with the applicationID and
+	 * the serviceType.
+	 */
+	typedef std::pair<uint8_t, uint8_t> AppServiceKey;
+
+	/**
+	 * Map containing the report type definitions. Each application process has its own ID. The combination of the
+	 * application ID and the service type is used as a key to provide access to the list of report type definitions.
+	 *
+	 * @note
+	 * The report type definitions are basically the message types of each service. For example a message type for the
+	 * 'ParameterStatisticsService' (ST04) is 'ParameterStatisticsService::MessageType::ParameterStatisticsReport'. The
+	 * Real Time Forwarding Control Service (ST14) uses this map as a lookup table, to identify whether a requested
+	 * triplet (app->service->message type) is allowed to be forwarded to the ground station via the corresponding virtual
+	 * channel. The requested message type is only forwarded, if the requested application process ID and service type
+	 * already exist in the map, and the requested report type is located in the vector of report types, which corresponds
+	 * to the appID and service type.
+	 */
+	etl::map<AppServiceKey, ReportTypeDefinitions, ECSSMaxApplicationsServicesCombinations> definitions;
+
+	ApplicationProcessConfiguration() = default;
+};
+
+#endif
diff --git a/inc/Platform/x86/ECSS_Configuration.hpp b/inc/Platform/x86/ECSS_Configuration.hpp
index 3b27fecf53cd2ad67e162144c2f9f1c5d6bd3774..6dbedb3a135a1eba0f72b7d4f6c2e30c0569506f 100644
--- a/inc/Platform/x86/ECSS_Configuration.hpp
+++ b/inc/Platform/x86/ECSS_Configuration.hpp
@@ -18,24 +18,22 @@
  * @{
  */
 
-#define SERVICE_ALL ///< Enables compilation of all the ECSS services
-
-#ifdef SERVICE_ALL
-#define SERVICE_EVENTACTION ///<  Compile ST[19] event-action
-#define SERVICE_EVENTREPORT ///<  Compile ST[05] event reporting
-#define SERVICE_FUNCTION ///<  Compile ST[08] function management
-#define SERVICE_HOUSEKEEPING ///<  Compile ST[03] housekeeping
-#define SERVICE_LARGEPACKET ///<  Compile ST[13] large packet transfer
-#define SERVICE_MEMORY ///<  Compile ST[06] memory management
-#define SERVICE_ONBOARDMONITORING ///<  Compile ST[12] on-board monitoring
-#define SERVICE_PARAMETER ///<  Compile ST[20] parameter management
-#define SERVICE_PARAMETERSTATISTICS ///<  Compile ST[04] parameter statistics
-#define SERVICE_REQUESTVERIFICATION ///<  Compile ST[01] request verification
-#define SERVICE_STORAGEANDRETRIEVAL ///<  Compile ST[15] storage-and-retrieval of tm packets
-#define SERVICE_TEST                ///<  Compile ST[17] test
-#define SERVICE_TIME                ///<  Compile ST[09] time management
-#define SERVICE_TIMESCHEDULING      ///<  Compile ST[11] time-based scheduling
-#endif
+#define SERVICE_ALL                       ///< Enables compilation of all the ECSS services
+#define SERVICE_EVENTACTION               ///<  Compile ST[19] event-action
+#define SERVICE_EVENTREPORT               ///<  Compile ST[05] event reporting
+#define SERVICE_FUNCTION                  ///<  Compile ST[08] function management
+#define SERVICE_HOUSEKEEPING              ///<  Compile ST[03] housekeeping
+#define SERVICE_LARGEPACKET               ///<  Compile ST[13] large packet transfer
+#define SERVICE_MEMORY                    ///<  Compile ST[06] memory management
+#define SERVICE_ONBOARDMONITORING         ///<  Compile ST[12] on-board monitoring
+#define SERVICE_PARAMETER                 ///<  Compile ST[20] parameter management
+#define SERVICE_PARAMETERSTATISTICS       ///<  Compile ST[04] parameter statistics
+#define SERVICE_REALTIMEFORWARDINGCONTROL ///<  Compile ST[14] real time forwarding control
+#define SERVICE_REQUESTVERIFICATION       ///<  Compile ST[01] request verification
+#define SERVICE_STORAGEANDRETRIEVAL       ///<  Compile ST[15] storage-and-retrieval of tm packets
+#define SERVICE_TEST                      ///<  Compile ST[17] test
+#define SERVICE_TIME                      ///<  Compile ST[09] time management
+#define SERVICE_TIMESCHEDULING            ///<  Compile ST[11] time-based scheduling
 /** @} */
 
 #endif // ECSS_SERVICES_ECSS_CONFIGURATION_HPP
diff --git a/inc/Platform/x86/Parameters/PlatformParameters.hpp b/inc/Platform/x86/Parameters/PlatformParameters.hpp
index a1332949b970ef685be69101461a8f181afc7be6..3977b370ca020248a7216533768c747c8d9a4488 100644
--- a/inc/Platform/x86/Parameters/PlatformParameters.hpp
+++ b/inc/Platform/x86/Parameters/PlatformParameters.hpp
@@ -21,4 +21,4 @@ namespace PlatformParameters {
 	inline Parameter<uint32_t> parameter3(10);
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/inc/ServicePool.hpp b/inc/ServicePool.hpp
index 9dbb533a2640a1d96abed2543d33129edf5b5314..47ff8595a6c909500d7aa9491f304054845a6d63 100644
--- a/inc/ServicePool.hpp
+++ b/inc/ServicePool.hpp
@@ -14,6 +14,7 @@
 #include "Services/StorageAndRetrievalService.hpp"
 #include "Services/HousekeepingService.hpp"
 #include "Services/ParameterStatisticsService.hpp"
+#include "Services/RealTimeForwardingControlService.hpp"
 #include "Services/OnBoardMonitoringService.hpp"
 
 /**
@@ -70,6 +71,10 @@ public:
 	ParameterService parameterManagement;
 #endif
 
+#ifdef SERVICE_REALTIMEFORWARDINGCONTROL
+	RealTimeForwardingControlService realTimeForwarding;
+#endif
+
 #ifdef SERVICE_PARAMETERSTATISTICS
 	ParameterStatisticsService parameterStatistics;
 #endif
diff --git a/inc/Services/RealTimeForwardingControlService.hpp b/inc/Services/RealTimeForwardingControlService.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5e42edbeadf9da26029f9b8d5fb5bd357d135a65
--- /dev/null
+++ b/inc/Services/RealTimeForwardingControlService.hpp
@@ -0,0 +1,129 @@
+#ifndef ECSS_SERVICES_REALTIMEFORWARDINGCONTROLSERVICE_HPP
+#define ECSS_SERVICES_REALTIMEFORWARDINGCONTROLSERVICE_HPP
+
+#include "ECSS_Definitions.hpp"
+#include "ErrorHandler.hpp"
+#include "Helpers/AllMessageTypes.hpp"
+#include "Helpers/ForwardControlConfiguration.hpp"
+#include "Service.hpp"
+#include "etl/vector.h"
+
+/**
+ * Implementation of the ST[14] 'Real Time Forwarding Control Service' as defined in ECSS-E-ST-70-41C.
+ *
+ * The purpose of this Service is to control the forwarding of the telemetry to the ground station. It includes
+ * conditions for all the application processes that are controlled by the Service, which determine whether a message
+ * should be forwarded to the ground station, through the corresponding virtual channel.
+ *
+ * @author Konstantinos Petridis <petridkon@gmail.com>
+ */
+class RealTimeForwardingControlService {
+public:
+	inline static const uint8_t ServiceType = 14;
+
+	enum MessageType : uint8_t {
+		AddReportTypesToAppProcessConfiguration = 1,
+	};
+
+	RealTimeForwardingControlService() = default;
+
+	/**
+	 * Contains the Application IDs, controlled by the Service.
+	 */
+	etl::vector<uint8_t, ECSSMaxControlledApplicationProcesses> controlledApplications;
+
+	/**
+	 * The Application Process configuration, containing all the application process, service type and message type
+	 * definitions.
+	 */
+	ApplicationProcessConfiguration applicationProcessConfiguration;
+
+private:
+	/**
+	 * Adds all report types of the specified application process definition, to the application process configuration.
+	 */
+	void addAllReportsOfApplication(uint8_t applicationID);
+
+	/**
+	 * Adds all report types of the specified service type, to the application process configuration.
+	 */
+	void addAllReportsOfService(uint8_t applicationID, uint8_t serviceType);
+
+	/**
+	 * Counts the number of service types, stored for the specified application process.
+	 */
+	uint8_t countServicesOfApplication(uint8_t applicationID);
+
+	/**
+	 * Counts the number of report types, stored for the specified service type.
+	 */
+	uint8_t countReportsOfService(uint8_t applicationID, uint8_t serviceType);
+
+	/**
+	 * Checks whether the specified message type already exists in the specified application process and service
+	 * type definition.
+	 */
+	bool reportExistsInAppProcessConfiguration(uint8_t applicationID, uint8_t serviceType, uint8_t messageType);
+
+	/**
+	 * 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.
+	 *
+	 * @return True: if the application is valid and passes all the necessary error checking.
+	 */
+	bool checkApplicationOfAppProcessConfig(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 checkAppControlled(Message& request, uint8_t applicationId);
+
+	/**
+	 * 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.
+	 *
+	 * @return True: if the service type is valid and passes all the necessary error checking.
+	 */
+	bool checkService(Message& request, uint8_t applicationID, uint8_t numOfMessages);
+
+	/**
+	 * 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);
+
+	/**
+	 * Checks if the maximum number of message types that can be contained inside a service type definition, is
+	 * already reached.
+	 *
+	 * @return True: if the message type is valid and passes all the necessary error checking.
+	 */
+	bool checkMessage(Message& request, uint8_t applicationID, uint8_t serviceType, uint8_t messageType);
+
+public:
+	/**
+	 * TC[14,1] 'Add report types to the application process forward control configuration'.
+	 */
+	void addReportTypesToAppProcessConfiguration(Message& request);
+
+	/**
+	 * It is responsible to call the suitable function that executes a TC packet. The source of that packet
+	 * is the ground station.
+	 *
+	 * @note This function is called from the main execute() that is defined in the file MessageParser.hpp
+	 * @param message Contains the necessary parameters to call the suitable subservice.
+	 */
+	void execute(Message& message);
+};
+
+#endif
diff --git a/src/Helpers/AllMessageTypes.cpp b/src/Helpers/AllMessageTypes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c67e09b31d3ebf98fd7a477d051b23beb7949a62
--- /dev/null
+++ b/src/Helpers/AllMessageTypes.cpp
@@ -0,0 +1,72 @@
+#include "Helpers/AllMessageTypes.hpp"
+#include "Services/EventActionService.hpp"
+#include "Services/EventReportService.hpp"
+#include "Services/HousekeepingService.hpp"
+#include "Services/LargePacketTransferService.hpp"
+#include "Services/MemoryManagementService.hpp"
+#include "Services/ParameterService.hpp"
+#include "Services/ParameterStatisticsService.hpp"
+#include "Services/RealTimeForwardingControlService.hpp"
+#include "Services/RequestVerificationService.hpp"
+#include "Services/TestService.hpp"
+#include "Services/TimeBasedSchedulingService.hpp"
+
+namespace AllMessageTypes {
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st01Messages = {RequestVerificationService::MessageType::FailedAcceptanceReport,
+	                                                                   RequestVerificationService::MessageType::FailedCompletionOfExecution,
+	                                                                   RequestVerificationService::MessageType::FailedProgressOfExecution,
+	                                                                   RequestVerificationService::MessageType::FailedRoutingReport,
+	                                                                   RequestVerificationService::MessageType::FailedStartOfExecution,
+	                                                                   RequestVerificationService::MessageType::SuccessfulAcceptanceReport,
+	                                                                   RequestVerificationService::MessageType::SuccessfulCompletionOfExecution,
+	                                                                   RequestVerificationService::MessageType::SuccessfulProgressOfExecution,
+	                                                                   RequestVerificationService::MessageType::SuccessfulStartOfExecution};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st03Messages = {
+	    HousekeepingService::MessageType::DisablePeriodicHousekeepingParametersReport,
+	    HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport,
+	    HousekeepingService::MessageType::GenerateOneShotHousekeepingReport,
+	    HousekeepingService::MessageType::HousekeepingParametersReport,
+	    HousekeepingService::MessageType::HousekeepingPeriodicPropertiesReport,
+	    HousekeepingService::MessageType::HousekeepingStructuresReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st04Messages = {
+	    ParameterStatisticsService::MessageType::ParameterStatisticsDefinitionsReport,
+	    ParameterStatisticsService::MessageType::ParameterStatisticsReport,
+	};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st05Messages = {EventReportService::MessageType::HighSeverityAnomalyReport,
+	                                                                   EventReportService::MessageType::DisabledListEventReport,
+	                                                                   EventReportService::MessageType::InformativeEventReport,
+	                                                                   EventReportService::MessageType::LowSeverityAnomalyReport,
+	                                                                   EventReportService::MessageType::MediumSeverityAnomalyReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st06Messages = {MemoryManagementService::MessageType::CheckRawMemoryDataReport,
+	                                                                   MemoryManagementService::MessageType::DumpRawMemoryDataReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st11Messages = {TimeBasedSchedulingService::MessageType::TimeBasedScheduledSummaryReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st13Messages = {LargePacketTransferService::MessageType::FirstDownlinkPartReport,
+	                                                                   LargePacketTransferService::MessageType::InternalDownlinkPartReport,
+	                                                                   LargePacketTransferService::MessageType::LastDownlinkPartReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st17Messages = {TestService::MessageType::AreYouAliveTestReport,
+	                                                                   TestService::MessageType::OnBoardConnectionTestReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st19Messages = {EventActionService::MessageType::EventActionStatusReport};
+
+	etl::vector<uint8_t, ECSSMaxReportTypeDefinitions> st20Messages = {ParameterService::MessageType::ParameterValuesReport};
+
+	etl::map<uint8_t, etl::vector<uint8_t, ECSSMaxReportTypeDefinitions>, ECSSMaxServiceTypeDefinitions> messagesOfService = {
+	    {RequestVerificationService::ServiceType, st01Messages},
+	    {HousekeepingService::ServiceType, st03Messages},
+	    {ParameterStatisticsService::ServiceType, st04Messages},
+	    {EventReportService::ServiceType, st05Messages},
+	    {MemoryManagementService::ServiceType, st06Messages},
+	    {TimeBasedSchedulingService::ServiceType, st11Messages},
+	    {LargePacketTransferService::ServiceType, st13Messages},
+	    {TestService::ServiceType, st17Messages},
+	    {EventActionService::ServiceType, st19Messages},
+	    {ParameterService::ServiceType, st20Messages}};
+
+} // namespace AllMessageTypes
diff --git a/src/MessageParser.cpp b/src/MessageParser.cpp
index d756549295a1750a7a45cc0c3d628a50af055a97..7ce06c23b64058b079a73eb0bf449462cd471b82 100644
--- a/src/MessageParser.cpp
+++ b/src/MessageParser.cpp
@@ -74,6 +74,12 @@ void MessageParser::execute(Message& message) {
 			break;
 #endif
 
+#ifdef SERVICE_REALTIMEFORWARDINGCONTROL
+		case RealTimeForwardingControlService::ServiceType:
+			Services.realTimeForwarding.execute(message);
+			break;
+#endif
+
 		default:
 			ErrorHandler::reportInternalError(ErrorHandler::OtherMessageType);
 	}
diff --git a/src/Services/RealTimeForwardingControlService.cpp b/src/Services/RealTimeForwardingControlService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..315bfbe3e4dd11b979f95a240e90e8c75a813841
--- /dev/null
+++ b/src/Services/RealTimeForwardingControlService.cpp
@@ -0,0 +1,157 @@
+#include "Services/RealTimeForwardingControlService.hpp"
+#include <iostream>
+
+void RealTimeForwardingControlService::addAllReportsOfApplication(uint8_t applicationID) {
+	for (auto& service: AllMessageTypes::messagesOfService) {
+		uint8_t serviceType = service.first;
+		addAllReportsOfService(applicationID, serviceType);
+	}
+}
+
+void RealTimeForwardingControlService::addAllReportsOfService(uint8_t applicationID, uint8_t serviceType) {
+	for (auto& messageType: AllMessageTypes::messagesOfService[serviceType]) {
+		auto appServicePair = std::make_pair(applicationID, serviceType);
+		applicationProcessConfiguration.definitions[appServicePair].push_back(messageType);
+	}
+}
+
+uint8_t RealTimeForwardingControlService::countServicesOfApplication(uint8_t applicationID) {
+	uint8_t serviceCounter = 0;
+	for (auto& definition: applicationProcessConfiguration.definitions) {
+		auto& pair = definition.first;
+		if (pair.first == applicationID) {
+			serviceCounter++;
+		}
+	}
+	return serviceCounter;
+}
+
+uint8_t RealTimeForwardingControlService::countReportsOfService(uint8_t applicationID, uint8_t serviceType) {
+	auto appServicePair = std::make_pair(applicationID, serviceType);
+	return applicationProcessConfiguration.definitions[appServicePair].size();
+}
+
+bool RealTimeForwardingControlService::checkAppControlled(Message& request, uint8_t applicationId) {
+	if (std::find(controlledApplications.begin(), controlledApplications.end(), applicationId) ==
+	    controlledApplications.end()) {
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::NotControlledApplication);
+		return false;
+	}
+	return true;
+}
+
+bool RealTimeForwardingControlService::checkApplicationOfAppProcessConfig(Message& request, uint8_t applicationID,
+                                                                          uint8_t numOfServices) {
+	if (not checkAppControlled(request, applicationID) or allServiceTypesAllowed(request, applicationID)) {
+		for (uint8_t i = 0; i < numOfServices; i++) {
+			request.skipBytes(1);
+			uint8_t numOfMessages = request.readUint8();
+			request.skipBytes(numOfMessages);
+		}
+		return false;
+	}
+	return true;
+}
+
+bool RealTimeForwardingControlService::allServiceTypesAllowed(Message& request, uint8_t applicationID) {
+	if (countServicesOfApplication(applicationID) >= ECSSMaxServiceTypeDefinitions) {
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AllServiceTypesAlreadyAllowed);
+		return true;
+	}
+	return false;
+}
+
+bool RealTimeForwardingControlService::maxServiceTypesReached(Message& request, uint8_t applicationID) {
+	if (countServicesOfApplication(applicationID) >= ECSSMaxServiceTypeDefinitions) {
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached);
+		return true;
+	}
+	return false;
+}
+
+bool RealTimeForwardingControlService::checkService(Message& request, uint8_t applicationID, uint8_t numOfMessages) {
+	if (maxServiceTypesReached(request, applicationID)) {
+		request.skipBytes(numOfMessages);
+		return false;
+	}
+	return true;
+}
+
+bool RealTimeForwardingControlService::maxReportTypesReached(Message& request, uint8_t applicationID,
+                                                             uint8_t serviceType) {
+	if (countReportsOfService(applicationID, serviceType) >= AllMessageTypes::messagesOfService[serviceType].size()) {
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached);
+		return true;
+	}
+	return false;
+}
+
+bool RealTimeForwardingControlService::checkMessage(Message& request, uint8_t applicationID, uint8_t serviceType,
+                                                    uint8_t messageType) {
+	if (maxReportTypesReached(request, applicationID, serviceType) or
+	    reportExistsInAppProcessConfiguration(applicationID, serviceType, messageType)) {
+		return false;
+	}
+	return true;
+}
+
+bool RealTimeForwardingControlService::reportExistsInAppProcessConfiguration(uint8_t applicationID, uint8_t serviceType,
+                                                                             uint8_t messageType) {
+	auto key = std::make_pair(applicationID, serviceType);
+	auto& messages = applicationProcessConfiguration.definitions[key];
+	return std::find(messages.begin(), messages.end(), messageType) != messages.end();
+}
+
+void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(Message& request) {
+	request.assertTC(ServiceType, MessageType::AddReportTypesToAppProcessConfiguration);
+	uint8_t numOfApplications = request.readUint8();
+
+	for (uint8_t i = 0; i < numOfApplications; i++) {
+		uint8_t applicationID = request.readUint8();
+		uint8_t numOfServices = request.readUint8();
+
+		if (not checkApplicationOfAppProcessConfig(request, applicationID, numOfServices)) {
+			continue;
+		}
+
+		if (numOfServices == 0) {
+			addAllReportsOfApplication(applicationID);
+			continue;
+		}
+
+		for (uint8_t j = 0; j < numOfServices; j++) {
+			uint8_t serviceType = request.readUint8();
+			uint8_t numOfMessages = request.readUint8();
+
+			if (not checkService(request, applicationID, numOfMessages)) {
+				continue;
+			}
+
+			if (numOfMessages == 0) {
+				addAllReportsOfService(applicationID, serviceType);
+				continue;
+			}
+
+			for (uint8_t k = 0; k < numOfMessages; k++) {
+				uint8_t messageType = request.readUint8();
+
+				if (not checkMessage(request, applicationID, serviceType, messageType)) {
+					continue;
+				}
+				auto key = std::make_pair(applicationID, serviceType);
+				applicationProcessConfiguration.definitions[key].push_back(
+				    messageType);
+			}
+		}
+	}
+}
+
+void RealTimeForwardingControlService::execute(Message& message) {
+	switch (message.messageType) {
+		case AddReportTypesToAppProcessConfiguration:
+			addReportTypesToAppProcessConfiguration(message);
+			break;
+		default:
+			ErrorHandler::reportInternalError(ErrorHandler::OtherMessageType);
+	}
+}
diff --git a/test/Services/HousekeepingService.cpp b/test/Services/HousekeepingService.cpp
index 459ec7528c0c502c1e7124a242ac2b0e9cedaa2b..c4fec918d3564e717b230f50fe7679b97280f655 100644
--- a/test/Services/HousekeepingService.cpp
+++ b/test/Services/HousekeepingService.cpp
@@ -1,8 +1,8 @@
+#include "Services/HousekeepingService.hpp"
 #include <iostream>
-#include "catch2/catch.hpp"
 #include "Message.hpp"
 #include "ServiceTests.hpp"
-#include "Services/HousekeepingService.hpp"
+#include "catch2/catch.hpp"
 #include "etl/algorithm.h"
 
 HousekeepingService& housekeepingService = Services.housekeeping;
@@ -18,7 +18,7 @@ void buildRequest(Message& request, uint8_t idToCreate) {
 	request.appendUint8(idToCreate);
 	request.appendUint32(interval);
 	request.appendUint16(numOfSimplyCommutatedParams);
-	for (auto& id : simplyCommutatedIds) {
+	for (auto& id: simplyCommutatedIds) {
 		request.appendUint16(id);
 	}
 }
@@ -39,11 +39,11 @@ void initializeHousekeepingStructures() {
 
 	HousekeepingStructure structures[3];
 	int i = 0;
-	for (auto& newStructure : structures) {
+	for (auto& newStructure: structures) {
 		newStructure.structureId = ids[i];
 		newStructure.collectionInterval = interval;
 		newStructure.periodicGenerationActionStatus = false;
-		for (uint16_t parameterId : simplyCommutatedIds) {
+		for (uint16_t parameterId: simplyCommutatedIds) {
 			newStructure.simplyCommutatedParameterIds.push_back(parameterId);
 		}
 		housekeepingService.housekeepingStructures.insert({ids[i], newStructure});
@@ -60,9 +60,6 @@ void initializeHousekeepingStructures() {
  * Helper function that stores samples into simply commutated parameters of different data type each.
  */
 void storeSamplesToParameters(uint16_t id1, uint16_t id2, uint16_t id3) {
-	Message samples(HousekeepingService::ServiceType,
-	                HousekeepingService::MessageType::ReportHousekeepingPeriodicProperties, Message::TM, 1);
-
 	static_cast<Parameter<uint16_t>&>(Services.parameterManagement.getParameter(id1)->get()).setValue(33);
 	static_cast<Parameter<uint8_t>&>(Services.parameterManagement.getParameter(id2)->get()).setValue(77);
 	static_cast<Parameter<uint32_t>&>(Services.parameterManagement.getParameter(id3)->get()).setValue(99);
@@ -77,7 +74,7 @@ void appendNewParameters(Message& request, uint8_t idToAppend) {
 
 	request.appendUint8(idToAppend);
 	request.appendUint16(numOfSimplyCommutatedParams);
-	for (auto& id : simplyCommutatedIds) {
+	for (auto& id: simplyCommutatedIds) {
 		request.appendUint16(id);
 	}
 }
@@ -94,7 +91,7 @@ TEST_CASE("Create housekeeping structure") {
 		request.appendUint8(idToCreate);
 		request.appendUint32(interval);
 		request.appendUint16(numOfSimplyCommutatedParams);
-		for (auto& id : simplyCommutatedIds) {
+		for (auto& id: simplyCommutatedIds) {
 			request.appendUint16(id);
 		}
 
@@ -146,11 +143,11 @@ TEST_CASE("Create housekeeping structure") {
 
 		REQUIRE(housekeepingService.housekeepingStructures.size() == 0);
 
-		for (auto& structId : idsToCreate) {
+		for (auto& structId: idsToCreate) {
 			request.appendUint8(structId);
 			request.appendUint32(interval);
 			request.appendUint16(numOfSimplyCommutatedParams);
-			for (auto& parameterId : simplyCommutatedIds) {
+			for (auto& parameterId: simplyCommutatedIds) {
 				request.appendUint16(parameterId);
 			}
 			MessageParser::execute(request);
@@ -176,7 +173,7 @@ TEST_CASE("Create housekeeping structure") {
 		request.appendUint8(idToCreate);
 		request.appendUint32(interval);
 		request.appendUint16(numOfSimplyCommutatedParams);
-		for (auto& id : simplyCommutatedIds) {
+		for (auto& id: simplyCommutatedIds) {
 			request.appendUint16(id);
 		}
 
@@ -188,7 +185,7 @@ TEST_CASE("Create housekeeping structure") {
 
 		REQUIRE(newStruct.simplyCommutatedParameterIds.size() == 4);
 		uint16_t existingParameterIds[4] = {8, 4, 5, 11};
-		for (auto parameterId : newStruct.simplyCommutatedParameterIds) {
+		for (auto parameterId: newStruct.simplyCommutatedParameterIds) {
 			CHECK(std::find(std::begin(existingParameterIds), std::end(existingParameterIds), parameterId) !=
 			      std::end(existingParameterIds));
 		}
@@ -214,7 +211,7 @@ TEST_CASE("Delete housekeeping structure") {
 		uint8_t numOfStructs = 5;
 		uint8_t ids[5] = {2, 3, 4, 7, 8};
 		request.appendUint8(numOfStructs);
-		for (auto& id : ids) {
+		for (auto& id: ids) {
 			request.appendUint8(id);
 		}
 
@@ -260,7 +257,7 @@ TEST_CASE("Enable the periodic generation of housekeeping structures") {
 		uint8_t numOfStructs = 5;
 		uint8_t idsToEnable[5] = {1, 3, 4, 6, 7};
 		request2.appendUint8(numOfStructs);
-		for (auto& id : idsToEnable) {
+		for (auto& id: idsToEnable) {
 			request2.appendUint8(id);
 		}
 		REQUIRE(not housekeepingService.housekeepingStructures[0].periodicGenerationActionStatus);
@@ -288,7 +285,7 @@ TEST_CASE("Disable the periodic generation of housekeeping structures") {
 		uint8_t numOfStructs = 4;
 		uint8_t idsToDisable[4] = {0, 1, 4, 6};
 		request2.appendUint8(numOfStructs);
-		for (auto& id : idsToDisable) {
+		for (auto& id: idsToDisable) {
 			request2.appendUint8(id);
 		}
 		housekeepingService.housekeepingStructures[0].periodicGenerationActionStatus = true;
@@ -317,7 +314,7 @@ TEST_CASE("Reporting of housekeeping structures") {
 		uint8_t numOfStructs = 3;
 		uint8_t idsToReport[3] = {9, 4, 2};
 		request2.appendUint8(numOfStructs);
-		for (auto& id : idsToReport) {
+		for (auto& id: idsToReport) {
 			request2.appendUint8(id);
 		}
 		MessageParser::execute(request2);
@@ -431,7 +428,7 @@ TEST_CASE("One-shot housekeeping parameter report generation") {
 		uint8_t numOfStructs = 5;
 		uint8_t structIds[5] = {0, 4, 7, 8, 11};
 		request2.appendUint8(numOfStructs);
-		for (auto& id : structIds) {
+		for (auto& id: structIds) {
 			request2.appendUint8(id);
 		}
 		MessageParser::execute(request2);
@@ -520,7 +517,7 @@ TEST_CASE("Append parameters in housekeeping report structure") {
 		uint16_t currentlyExistingParameters[] = {8, 4, 5, 9, 10, 11};
 		HousekeepingStructure structToCheck = housekeepingService.housekeepingStructures[structId];
 		REQUIRE(structToCheck.simplyCommutatedParameterIds.size() == 6);
-		for (auto& existingParameter : currentlyExistingParameters) {
+		for (auto& existingParameter: currentlyExistingParameters) {
 			CHECK(std::find(std::begin(structToCheck.simplyCommutatedParameterIds),
 			                std::end(structToCheck.simplyCommutatedParameterIds),
 			                existingParameter) != std::end(structToCheck.simplyCommutatedParameterIds));
@@ -540,7 +537,7 @@ TEST_CASE("Append parameters in housekeeping report structure") {
 
 		request.appendUint8(structId);
 		request.appendUint16(numOfSimplyCommutatedParams);
-		for (auto& id : simplyCommutatedIds) {
+		for (auto& id: simplyCommutatedIds) {
 			request.appendUint16(id);
 		}
 		REQUIRE(housekeepingService.housekeepingStructures.find(structId) !=
@@ -570,7 +567,7 @@ TEST_CASE("Modification of housekeeping structures' interval") {
 		uint32_t intervals[4] = {12, 21, 32, 17};
 		request.appendUint8(numOfStructs);
 		int i = 0;
-		for (auto& id : structIds) {
+		for (auto& id: structIds) {
 			request.appendUint8(id);
 			request.appendUint32(intervals[i++]);
 		}
@@ -595,7 +592,7 @@ TEST_CASE("Reporting of housekeeping structure periodic properties") {
 		uint8_t numOfStructs = 6;
 		uint8_t structIds[6] = {0, 4, 1, 6, 9, 10};
 		request.appendUint8(numOfStructs);
-		for (auto& id : structIds) {
+		for (auto& id: structIds) {
 			request.appendUint8(id);
 		}
 		housekeepingService.housekeepingStructures[0].periodicGenerationActionStatus = true;
@@ -609,16 +606,16 @@ TEST_CASE("Reporting of housekeeping structure periodic properties") {
 		      3);
 
 		Message report = ServiceTests::get(3);
-		CHECK(report.readUint8() == 3); // Number of valid ids
-		CHECK(report.readUint8() == 0); // Id
-		CHECK(report.readBoolean() == true); // Periodic status
-		CHECK(report.readUint32() == 7); // Interval
-		CHECK(report.readUint8() == 4); // Id
+		CHECK(report.readUint8() == 3);       // Number of valid ids
+		CHECK(report.readUint8() == 0);       // Id
+		CHECK(report.readBoolean() == true);  // Periodic status
+		CHECK(report.readUint32() == 7);      // Interval
+		CHECK(report.readUint8() == 4);       // Id
 		CHECK(report.readBoolean() == false); // Periodic status
-		CHECK(report.readUint32() == 24); // Interval
-		CHECK(report.readUint8() == 6); // Id
+		CHECK(report.readUint32() == 24);     // Interval
+		CHECK(report.readUint8() == 6);       // Id
 		CHECK(report.readBoolean() == false); // Periodic status
-		CHECK(report.readUint32() == 13); // Interval
+		CHECK(report.readUint32() == 13);     // Interval
 
 		ServiceTests::reset();
 		Services.reset();
diff --git a/test/Services/RealTimeForwardingControl.cpp b/test/Services/RealTimeForwardingControl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3553697dff0d3748aa67c78e75631653435972b0
--- /dev/null
+++ b/test/Services/RealTimeForwardingControl.cpp
@@ -0,0 +1,553 @@
+#include <iostream>
+#include "ECSS_Definitions.hpp"
+#include "Message.hpp"
+#include "ServiceTests.hpp"
+#include "Services/RealTimeForwardingControlService.hpp"
+#include "catch2/catch.hpp"
+
+RealTimeForwardingControlService& realTimeForwarding = Services.realTimeForwarding;
+
+uint8_t applications[] = {1};
+uint8_t services[] = {3, 5};
+uint8_t allServices[] = {1, 3, 4, 5, 6, 11, 13, 17, 19, 20};
+uint8_t redundantServices[] = {1, 3, 4, 5, 6, 11, 13, 17, 19, 20, 1, 3};
+uint8_t messages1[] = {HousekeepingService::MessageType::HousekeepingPeriodicPropertiesReport,
+                       HousekeepingService::MessageType::DisablePeriodicHousekeepingParametersReport};
+
+uint8_t messages2[] = {EventReportService::MessageType::InformativeEventReport,
+                       EventReportService::MessageType::DisabledListEventReport};
+
+void validReportTypes(Message& request) {
+	uint8_t numOfApplications = 1;
+	uint8_t numOfServicesPerApp = 2;
+	uint8_t numOfMessagesPerService = 2;
+
+	request.appendUint8(numOfApplications);
+
+	for (auto appID: applications) {
+		request.appendUint8(appID);
+		request.appendUint8(numOfServicesPerApp);
+
+		for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+			uint8_t serviceType = services[j];
+			request.appendUint8(serviceType);
+			request.appendUint8(numOfMessagesPerService);
+			uint8_t* messages = (j == 0) ? messages1 : messages2;
+
+			for (uint8_t k = 0; k < numOfMessagesPerService; k++) {
+				request.appendUint8(messages[k]);
+			}
+		}
+	}
+}
+
+void duplicateReportTypes(Message& request) {
+	uint8_t numOfApplications = 1;
+	uint8_t numOfServicesPerApp = 2;
+	uint8_t numOfMessagesPerService = 2;
+
+	request.appendUint8(numOfApplications);
+
+	for (auto appID: applications) {
+		request.appendUint8(appID);
+		request.appendUint8(numOfServicesPerApp);
+
+		for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+			uint8_t serviceType = services[j];
+			request.appendUint8(serviceType);
+			request.appendUint8(numOfMessagesPerService);
+
+			for (uint8_t k = 0; k < numOfMessagesPerService; k++) {
+				request.appendUint8(messages1[0]);
+			}
+		}
+	}
+}
+
+void validInvalidReportTypes(Message& request) {
+	uint8_t numOfApplications = 3;
+	uint8_t numOfMessagesPerService = 2;
+
+	uint8_t applications2[] = {1, 2, 3};
+	request.appendUint8(numOfApplications);
+
+	for (uint8_t i = 0; i < numOfApplications; i++) {
+		request.appendUint8(applications2[i]);
+		uint8_t numOfServicesPerApp = (i == 0) ? 12 : 2;
+		uint8_t* servicesToPick = (i == 0) ? redundantServices : services;
+		request.appendUint8(numOfServicesPerApp);
+
+		for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+			uint8_t serviceType = servicesToPick[j];
+			request.appendUint8(serviceType);
+			request.appendUint8(numOfMessagesPerService);
+			uint8_t* messages = (j == 0) ? messages1 : messages2;
+
+			for (uint8_t k = 0; k < numOfMessagesPerService; k++) {
+				request.appendUint8(messages[k]);
+			}
+		}
+	}
+}
+
+void validAllReportsOfService(Message& request) {
+	uint8_t numOfApplications = 1;
+	uint8_t numOfServicesPerApp = 2;
+	uint8_t numOfMessagesPerService = 0;
+
+	request.appendUint8(numOfApplications);
+
+	for (auto appID: applications) {
+		request.appendUint8(appID);
+		request.appendUint8(numOfServicesPerApp);
+
+		for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+			uint8_t serviceType = services[j];
+			request.appendUint8(serviceType);
+			request.appendUint8(numOfMessagesPerService);
+		}
+	}
+}
+
+void validInvalidAllReportsOfService(Message& request) {
+	uint8_t numOfApplications = 3;
+	uint8_t numOfMessagesPerService = 2;
+
+	uint8_t applications2[] = {1, 2, 3};
+	request.appendUint8(numOfApplications);
+
+	for (uint8_t i = 0; i < numOfApplications; i++) {
+		request.appendUint8(applications2[i]);
+		uint8_t numOfServicesPerApp = (i == 0) ? 12 : 2;
+		uint8_t* servicesToPick = (i == 0) ? redundantServices : services;
+		request.appendUint8(numOfServicesPerApp);
+
+		for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+			uint8_t serviceType = servicesToPick[j];
+			request.appendUint8(serviceType);
+			uint8_t numOfMessages = (i < 2) ? 0 : numOfMessagesPerService;
+			request.appendUint8(numOfMessages);
+			if (i >= 2) {
+				uint8_t* messages = (j == 0) ? messages1 : messages2;
+
+				for (uint8_t k = 0; k < numOfMessagesPerService; k++) {
+					request.appendUint8(messages[k]);
+				}
+			}
+		}
+	}
+}
+
+void validAllReportsOfApp(Message& request) {
+	uint8_t numOfApplications = 1;
+	uint8_t numOfServicesPerApp = 0;
+
+	request.appendUint8(numOfApplications);
+
+	for (auto appID: applications) {
+		request.appendUint8(appID);
+		request.appendUint8(numOfServicesPerApp);
+	}
+}
+
+void validInvalidAllReportsOfApp(Message& request) {
+	uint8_t numOfApplications = 3;
+	uint8_t numOfMessagesPerService = 2;
+
+	uint8_t applications2[] = {1, 2, 3};
+	request.appendUint8(numOfApplications);
+
+	for (uint8_t i = 0; i < numOfApplications; i++) {
+		request.appendUint8(applications2[i]);
+		uint8_t numOfServicesPerApp = (i == 0 or i == 1) ? 0 : 2;
+		uint8_t* servicesToPick = (i == 0) ? redundantServices : services;
+		request.appendUint8(numOfServicesPerApp);
+
+		if (i >= 2) {
+			for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+				uint8_t serviceType = servicesToPick[j];
+				request.appendUint8(serviceType);
+				uint8_t numOfMessages = (i == 0 or i == 1) ? 0 : numOfMessagesPerService;
+				request.appendUint8(numOfMessages);
+
+				uint8_t* messages = (j == 0) ? messages1 : messages2;
+
+				for (uint8_t k = 0; k < numOfMessagesPerService; k++) {
+					request.appendUint8(messages[k]);
+				}
+			}
+		}
+	}
+}
+
+void resetAppProcessConfiguration() {
+	realTimeForwarding.applicationProcessConfiguration.definitions.clear();
+	REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions.empty());
+}
+
+TEST_CASE("Add report types to the Application Process Configuration") {
+	SECTION("Successful addition of report types to the Application Process Configuration") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		validReportTypes(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 0);
+		auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions;
+		REQUIRE(applicationProcesses.size() == 2);
+
+		for (auto appID: applications) {
+			for (uint8_t j = 0; j < 2; j++) {
+				uint8_t serviceType = services[j];
+				auto appServicePair = std::make_pair(appID, serviceType);
+				REQUIRE(applicationProcesses.find(appServicePair) != applicationProcesses.end());
+				REQUIRE(applicationProcesses[appServicePair].size() == 2);
+				uint8_t* messages = (j == 0) ? messages1 : messages2;
+
+				for (uint8_t k = 0; k < 2; k++) {
+					REQUIRE(std::find(applicationProcesses[appServicePair].begin(),
+					                  applicationProcesses[appServicePair].end(),
+					                  messages[k]) != applicationProcesses[appServicePair].end());
+				}
+			}
+		}
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Requested Application Process is not controlled by the service") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		validReportTypes(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NotControlledApplication) == 1);
+		REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions.empty());
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("All service types already allowed") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		validReportTypes(request);
+
+		for (uint8_t i = 1; i < ECSSMaxServiceTypeDefinitions + 1; i++) {
+			realTimeForwarding.applicationProcessConfiguration.definitions[std::make_pair(applicationID, i)];
+		}
+		CHECK(realTimeForwarding.applicationProcessConfiguration.definitions.size() == ECSSMaxServiceTypeDefinitions);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AllServiceTypesAlreadyAllowed) ==
+		      1);
+		REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions.size() == ECSSMaxServiceTypeDefinitions);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Max service types already reached") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		uint8_t serviceType1 = services[0]; // st03
+		uint8_t serviceType2 = services[1]; // st05
+
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		validReportTypes(request);
+
+		auto& applicationProcessConfig = realTimeForwarding.applicationProcessConfiguration.definitions;
+
+		for (uint8_t i = 100; i < ECSSMaxServiceTypeDefinitions + 99; i++) {
+			applicationProcessConfig[std::make_pair(applicationID, i)];
+		}
+		CHECK(applicationProcessConfig.size() == ECSSMaxServiceTypeDefinitions - 1);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached) == 1);
+		REQUIRE(applicationProcessConfig.size() == ECSSMaxServiceTypeDefinitions);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("All report types already allowed") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		uint8_t serviceType = services[0]; // st03
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		validReportTypes(request);
+
+		for (auto message: AllMessageTypes::messagesOfService[serviceType]) {
+			realTimeForwarding.applicationProcessConfiguration.definitions[std::make_pair(applicationID, serviceType)]
+			    .push_back(message);
+		}
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 2);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached) ==
+		      2);
+		REQUIRE(
+		    realTimeForwarding.applicationProcessConfiguration.definitions[std::make_pair(applicationID, serviceType)]
+		        .size() == AllMessageTypes::messagesOfService[serviceType].size());
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Max report types already reached") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		uint8_t serviceType1 = services[0]; // st03
+		uint8_t serviceType2 = services[1]; // st05
+
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		validReportTypes(request);
+
+		auto& applicationProcessConfig = realTimeForwarding.applicationProcessConfiguration;
+
+		auto appServicePair1 = std::make_pair(applicationID, serviceType1);
+		auto appServicePair2 = std::make_pair(applicationID, serviceType2);
+		REQUIRE(applicationProcessConfig.definitions[appServicePair1].empty());
+		REQUIRE(applicationProcessConfig.definitions[appServicePair2].empty());
+
+		auto numOfMessages1 = AllMessageTypes::messagesOfService[serviceType1].size();
+		auto numOfMessages2 = AllMessageTypes::messagesOfService[serviceType2].size();
+
+		for (uint8_t i = 0; i < numOfMessages1 - 1; i++) {
+			applicationProcessConfig.definitions[appServicePair1].push_back(i);
+		}
+		for (uint8_t i = 16; i < numOfMessages2 + 15; i++) {
+			applicationProcessConfig.definitions[appServicePair2].push_back(i);
+		}
+		REQUIRE(applicationProcessConfig.definitions[appServicePair1].size() == numOfMessages1 - 1);
+		REQUIRE(applicationProcessConfig.definitions[appServicePair2].size() == numOfMessages2 - 1);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 2);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached) == 2);
+		REQUIRE(applicationProcessConfig.definitions.size() == 2);
+		REQUIRE(applicationProcessConfig.definitions[appServicePair1].size() == numOfMessages1);
+		REQUIRE(applicationProcessConfig.definitions[appServicePair2].size() == numOfMessages2);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Requested addition of duplicate report type definitions") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		duplicateReportTypes(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 0);
+		auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions;
+		REQUIRE(applicationProcesses.size() == 2);
+
+		for (auto appID: applications) {
+			for (auto& serviceType: services) {
+				auto appServicePair = std::make_pair(appID, serviceType);
+				REQUIRE(applicationProcesses.find(appServicePair) != applicationProcesses.end());
+				REQUIRE(applicationProcesses[appServicePair].size() == 1);
+				REQUIRE(std::find(applicationProcesses[appServicePair].begin(),
+				                  applicationProcesses[appServicePair].end(),
+				                  messages1[0]) != applicationProcesses[appServicePair].end());
+			}
+		}
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Valid and invalid application-related requests combined") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+		uint8_t applicationID1 = 1;
+		uint8_t applicationID2 = 2;
+		uint8_t applicationID3 = 3;
+		realTimeForwarding.controlledApplications.push_back(applicationID1);
+		realTimeForwarding.controlledApplications.push_back(applicationID3);
+		validInvalidReportTypes(request);
+
+		for (uint8_t i = 100; i < ECSSMaxServiceTypeDefinitions + 99; i++) {
+			realTimeForwarding.applicationProcessConfiguration.definitions[std::make_pair(applicationID3, i)];
+		}
+		CHECK(realTimeForwarding.applicationProcessConfiguration.definitions.size() ==
+		      ECSSMaxServiceTypeDefinitions - 1);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 7);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NotControlledApplication) == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached) == 3);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached) == 3);
+
+		auto& definitions = realTimeForwarding.applicationProcessConfiguration.definitions;
+		REQUIRE(definitions.size() == 20);
+		for (auto serviceType: allServices) {
+			REQUIRE(definitions.find(std::make_pair(applicationID1, serviceType)) != definitions.end());
+		}
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Valid addition of all report types of a specified service type") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+		uint8_t applicationID1 = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID1);
+		validAllReportsOfService(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 0);
+		auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions;
+		for (auto serviceType: services) {
+			REQUIRE(applicationProcesses[std::make_pair(applicationID1, serviceType)].size() ==
+			        AllMessageTypes::messagesOfService[serviceType].size());
+		}
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Addition of all report types of a service type, combined with invalid requests") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+		uint8_t applicationID1 = 1;
+		uint8_t applicationID2 = 2;
+		realTimeForwarding.controlledApplications.push_back(applicationID1);
+		realTimeForwarding.controlledApplications.push_back(applicationID2);
+		validInvalidAllReportsOfService(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 3);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NotControlledApplication) == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached) == 2);
+
+		auto& definitions = realTimeForwarding.applicationProcessConfiguration.definitions;
+		REQUIRE(definitions.size() == 12);
+
+		int cnt1 = 0;
+		int cnt2 = 0;
+		for (auto& pair: definitions) {
+			if (pair.first.first == applicationID1) {
+				cnt1++;
+			} else if (pair.first.first == applicationID2) {
+				cnt2++;
+			}
+		}
+		REQUIRE(cnt1 == 10);
+		REQUIRE(cnt2 == 2);
+
+		for (auto& serviceType: allServices) {
+			REQUIRE(definitions[std::make_pair(applicationID1, serviceType)].size() ==
+			        AllMessageTypes::messagesOfService[serviceType].size());
+		}
+		for (auto& serviceType: services) {
+			REQUIRE(definitions[std::make_pair(applicationID2, serviceType)].size() ==
+			        AllMessageTypes::messagesOfService[serviceType].size());
+		}
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Valid addition of all report types of an application process") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+		uint8_t applicationID1 = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID1);
+		validAllReportsOfApp(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 0);
+		auto& definitions = realTimeForwarding.applicationProcessConfiguration.definitions;
+		REQUIRE(definitions.size() == ECSSMaxServiceTypeDefinitions);
+
+		for (auto serviceType: allServices) {
+			REQUIRE(std::equal(definitions[std::make_pair(applicationID1, serviceType)].begin(),
+			                   definitions[std::make_pair(applicationID1, serviceType)].end(),
+			                   AllMessageTypes::messagesOfService[serviceType].begin()));
+		}
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Addition of all report types of an application process, combined with invalid request") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+		uint8_t applicationID1 = 1;
+		uint8_t applicationID2 = 2;
+		realTimeForwarding.controlledApplications.push_back(applicationID1);
+		realTimeForwarding.controlledApplications.push_back(applicationID2);
+		validInvalidAllReportsOfApp(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NotControlledApplication) == 1);
+		auto& definitions = realTimeForwarding.applicationProcessConfiguration.definitions;
+
+		REQUIRE(definitions.size() == 2 * ECSSMaxServiceTypeDefinitions);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+}