diff --git a/tcdistribution/CFDPDistributor.cpp b/tcdistribution/CFDPDistributor.cpp new file mode 100644 index 00000000..9fe29499 --- /dev/null +++ b/tcdistribution/CFDPDistributor.cpp @@ -0,0 +1,138 @@ +#include "CCSDSDistributorIF.h" +#include "CFDPDistributor.h" + +#include "../serviceinterface/ServiceInterface.h" + +#define CFDP_DISTRIBUTOR_DEBUGGING 0 + +CFDPDistributor::CFDPDistributor(uint16_t setApid, object_id_t setObjectId, + object_id_t setPacketSource) : + TcDistributor(setObjectId), checker(setApid), verifyChannel(), + tcStatus(RETURN_FAILED), packetSource(setPacketSource) {} + +CFDPDistributor::~CFDPDistributor() {} + +CFDPDistributor::TcMqMapIter CFDPDistributor::selectDestination() { +#if FSFW_CPP_OSTREAM_ENABLED == 1 && CFDP_DISTRIBUTOR_DEBUGGING == 1 + store_address_t storeId = this->currentMessage.getStorageId()); + sif:: debug << "CFDPDistributor::handlePacket received: " << storeId.poolIndex << ", " << + storeId.packetIndex << std::endl; +#endif + TcMqMapIter queueMapIt = this->queueMap.end(); + if(this->currentPacket == nullptr) { + return queueMapIt; + } + this->currentPacket->setStoreAddress(this->currentMessage.getStorageId()); + if (currentPacket->getWholeData() != nullptr) { + tcStatus = checker.checkPacket(currentPacket); + if(tcStatus != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "CFDPDistributor::handlePacket: Packet format invalid, code " << + static_cast(tcStatus) << std::endl; +#else + sif::printDebug("CFDPDistributor::handlePacket: Packet format invalid, code %d\n", + static_cast(tcStatus)); +#endif +#endif + } + uint32_t queue_id = currentPacket->getService(); + queueMapIt = this->queueMap.find(queue_id); + } + else { + tcStatus = PACKET_LOST; + } + + if (queueMapIt == this->queueMap.end()) { + tcStatus = DESTINATION_NOT_FOUND; +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "CFDPDistributor::handlePacket: Destination not found" << std::endl; +#else + sif::printDebug("CFDPDistributor::handlePacket: Destination not found\n"); +#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif + } + + if (tcStatus != RETURN_OK) { + return this->queueMap.end(); + } + else { + return queueMapIt; + } + +} + + +ReturnValue_t CFDPDistributor::registerService(AcceptsTelecommandsIF* service) { + uint16_t serviceId = service->getIdentifier(); +#if PUS_DISTRIBUTOR_DEBUGGING == 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "Service ID: " << static_cast(serviceId) << std::endl; +#else + sif::printInfo("Service ID: %d\n", static_cast(serviceId)); +#endif +#endif + MessageQueueId_t queue = service->getRequestQueue(); + auto returnPair = queueMap.emplace(serviceId, queue); + if (not returnPair.second) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PUSDistributor::registerService: Service ID already" + " exists in map" << std::endl; +#else + sif::printError("PUSDistributor::registerService: Service ID already exists in map\n"); +#endif +#endif + return SERVICE_ID_ALREADY_EXISTS; + } + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t CFDPDistributor::getRequestQueue() { + return tcQueue->getId(); +} + +ReturnValue_t CFDPDistributor::callbackAfterSending(ReturnValue_t queueStatus) { + if (queueStatus != RETURN_OK) { + tcStatus = queueStatus; + } + if (tcStatus != RETURN_OK) { + this->verifyChannel.sendFailureReport(tc_verification::ACCEPTANCE_FAILURE, + currentPacket, tcStatus); + // A failed packet is deleted immediately after reporting, + // otherwise it will block memory. + currentPacket->deletePacket(); + return RETURN_FAILED; + } else { + this->verifyChannel.sendSuccessReport(tc_verification::ACCEPTANCE_SUCCESS, + currentPacket); + return RETURN_OK; + } +} + +uint16_t CFDPDistributor::getIdentifier() { + return checker.getApid(); +} + +ReturnValue_t CFDPDistributor::initialize() { + currentPacket = new TcPacketStored(); + if(currentPacket == nullptr) { + // Should not happen, memory allocation failed! + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + CCSDSDistributorIF* ccsdsDistributor = + objectManager->get(packetSource); + if (ccsdsDistributor == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "CFDPDistributor::initialize: Packet source invalid" << std::endl; + sif::error << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl; +#else + sif::printError("CFDPDistributor::initialize: Packet source invalid\n"); + sif::printError("Make sure it exists and implements CCSDSDistributorIF\n"); +#endif + return RETURN_FAILED; + } + return ccsdsDistributor->registerApplication(this); +} diff --git a/tcdistribution/CFDPDistributor.h b/tcdistribution/CFDPDistributor.h new file mode 100644 index 00000000..1a5865ed --- /dev/null +++ b/tcdistribution/CFDPDistributor.h @@ -0,0 +1,78 @@ +#ifndef FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ +#define FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ + +#include "CFDPDistributorIF.h" +#include "TcDistributor.h" +#include "TcPacketCheck.h" + +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../tmtcservices/VerificationReporter.h" + +/** + * This class accepts CFDP Telecommands and forwards them to Application + * services. + * @ingroup tc_distribution + */ +class CFDPDistributor: public TcDistributor, + public CFDPDistributorIF, + public AcceptsTelecommandsIF { +public: + /** + * The ctor passes @c set_apid to the checker class and calls the + * TcDistribution ctor with a certain object id. + * @param setApid The APID of this receiving Application. + * @param setObjectId Object ID of the distributor itself + * @param setPacketSource Object ID of the source of TC packets. + * Must implement CCSDSDistributorIF. + */ + CFDPDistributor(uint16_t setApid, object_id_t setObjectId, + object_id_t setPacketSource); + /** + * The destructor is empty. + */ + virtual ~CFDPDistributor(); + ReturnValue_t registerService(AcceptsTelecommandsIF* service) override; + MessageQueueId_t getRequestQueue() override; + ReturnValue_t initialize() override; + uint16_t getIdentifier() override; + +protected: + /** + * This attribute contains the class, that performs a formal packet check. + */ + TcPacketCheck checker; + /** + * With this class, verification messages are sent to the + * TC Verification service. + */ + VerificationReporter verifyChannel; + /** + * The currently handled packet is stored here. + */ + TcPacketStored* currentPacket = nullptr; + /** + * With this variable, the current check status is stored to generate + * acceptance messages later. + */ + ReturnValue_t tcStatus; + + const object_id_t packetSource; + + /** + * This method reads the packet service, checks if such a service is + * registered and forwards the packet to the destination. + * It also initiates the formal packet check and sending of verification + * messages. + * @return Iterator to map entry of found service id + * or iterator to @c map.end(). + */ + TcMqMapIter selectDestination() override; + /** + * The callback here handles the generation of acceptance + * success/failure messages. + */ + ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override; +}; + +#endif /* FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ */ diff --git a/tcdistribution/CFDPDistributorIF.h b/tcdistribution/CFDPDistributorIF.h new file mode 100644 index 00000000..dd017c97 --- /dev/null +++ b/tcdistribution/CFDPDistributorIF.h @@ -0,0 +1,27 @@ +#ifndef FSFW_TCDISTRIBUTION_CFDPDISTRIBUTORIF_H_ +#define FSFW_TCDISTRIBUTION_CFDPDISTRIBUTORIF_H_ + +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../ipc/MessageQueueSenderIF.h" + +/** + * This interface allows CFDP Services to register themselves at a CFDP Distributor. + * @ingroup tc_distribution + */ +class CFDPDistributorIF { +public: + /** + * The empty virtual destructor. + */ + virtual ~CFDPDistributorIF() { + } +/** + * With this method, Services can register themselves at the PUS Distributor. + * @param service A pointer to the registering Service. + * @return - @c RETURN_OK on success, + * - @c RETURN_FAILED on failure. + */ + virtual ReturnValue_t registerService( AcceptsTelecommandsIF* service ) = 0; +}; + +#endif /* FSFW_TCDISTRIBUTION_CFDPDISTRIBUTORIF_H_ */ diff --git a/tcdistribution/CMakeLists.txt b/tcdistribution/CMakeLists.txt index 17dc186c..e89792ed 100644 --- a/tcdistribution/CMakeLists.txt +++ b/tcdistribution/CMakeLists.txt @@ -2,6 +2,7 @@ target_sources(${LIB_FSFW_NAME} PRIVATE CCSDSDistributor.cpp PUSDistributor.cpp + CFDPDistributor.cpp TcDistributor.cpp TcPacketCheck.cpp )