#include "DestHandler.h" #include #include "fsfw/cfdp/pdu/HeaderReader.h" #include "fsfw/cfdp/pdu/MetadataPduReader.h" #include "fsfw/objectmanager.h" #include "fsfw/serviceinterface.h" using namespace returnvalue; cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwParams fsfwParams) : dp(std::move(params)), fp(fsfwParams), tlvVec(params.maxTlvsInOnePdu) {} ReturnValue_t cfdp::DestHandler::performStateMachine() { switch (step) { case TransactionStep::IDLE: { ReturnValue_t status = returnvalue::OK; ReturnValue_t result; for (const auto& info : dp.packetListRef) { if (info.pduType == PduType::FILE_DIRECTIVE and info.directiveType == FileDirectives::METADATA) { result = handleMetadataPdu(info); if (result != OK) { status = result; } } } return status; } case TransactionStep::TRANSACTION_START: break; case TransactionStep::RECEIVING_FILE_DATA_PDUS: break; case TransactionStep::SENDING_ACK_PDU: break; case TransactionStep::TRANSFER_COMPLETION: break; case TransactionStep::SENDING_FINISHED_PDU: break; } return returnvalue::OK; } ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) { if (dp.packetListRef.full()) { return returnvalue::FAILED; } dp.packetListRef.push_back(packet); return returnvalue::OK; } ReturnValue_t cfdp::DestHandler::initialize() { if (fp.tmStore == nullptr) { fp.tmStore = ObjectManager::instance()->get(objects::TM_STORE); if (fp.tmStore == nullptr) { return returnvalue::FAILED; } } if (fp.tcStore == nullptr) { fp.tcStore = ObjectManager::instance()->get(objects::TC_STORE); if (fp.tcStore == nullptr) { return returnvalue::FAILED; } } return returnvalue::OK; } ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) { // Process metadata PDU auto constAccessorPair = fp.tcStore->getData(info.storeId); if (constAccessorPair.first != OK) { // TODO: This is not a CFDP error. Event and/or warning? return constAccessorPair.first; } cfdp::FileSize fileSize; cfdp::StringLv sourceFileName; cfdp::StringLv destFileName; MetadataInfo metadataInfo(fileSize, sourceFileName, destFileName); cfdp::Tlv* tlvArrayAsPtr = tlvVec.data(); metadataInfo.setOptionsArray(&tlvArrayAsPtr, std::nullopt, tlvVec.size()); MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), metadataInfo); ReturnValue_t result = reader.parseData(); // TODO: The standard does not really specify what happens if this kind of error happens // I think it might be a good idea to cache some sort of error code, which // is translated into a warning and/or event by an upper layer if (result != OK) { return handleMetadataParseError(constAccessorPair.second.data(), constAccessorPair.second.size()); } return result; } ReturnValue_t cfdp::DestHandler::handleMetadataParseError(const uint8_t* rawData, size_t maxSize) { // TODO: try to extract destination ID for error // TODO: Invalid metadata PDU. #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Parsing Metadata PDU failed with code " << result << std::endl; #else #endif HeaderReader headerReader(rawData, maxSize); ReturnValue_t result = headerReader.parseData(); if (result != OK) { // TODO: Now this really should not happen. Warning or error, // yield or cache appropriate returnvalue #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Parsing Header failed" << std::endl; #else #endif // TODO: Trigger appropriate event return result; } cfdp::EntityId destId; headerReader.getDestId(destId); RemoteEntityCfg* remoteCfg; if (not dp.remoteCfgTable.getRemoteCfg(destId, &remoteCfg)) { // TODO: No remote config for dest ID. I consider this a configuration error. // Warning or error, yield or cache appropriate returnvalue #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "No remote config exists for destination ID" << std::endl; #else #endif // TODO: Trigger appropriate event } // TODO: Appropriate returnvalue? return returnvalue::FAILED; }