From 134d5a1411dcdf3394dbdb85228d08f10e5066df Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 5 Sep 2022 10:26:35 +0200 Subject: [PATCH] basic impl which allows naked no closure file transfer --- src/fsfw/cfdp/definitions.h | 2 +- src/fsfw/cfdp/handler/DestHandler.cpp | 71 +++++++++++++++++++++- src/fsfw/cfdp/handler/DestHandler.h | 23 ++++++- src/fsfw/cfdp/handler/UserBase.h | 8 +-- src/fsfw/cfdp/handler/mib.h | 2 +- src/fsfw/cfdp/pdu/MetadataInfo.cpp | 6 +- src/fsfw/cfdp/pdu/MetadataInfo.h | 8 +-- src/fsfw/cfdp/pdu/MetadataPduReader.cpp | 2 +- unittests/cfdp/handler/testDistributor.cpp | 2 +- unittests/cfdp/pdu/testMetadataPdu.cpp | 10 +-- 10 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/fsfw/cfdp/definitions.h b/src/fsfw/cfdp/definitions.h index fc117581..635ead17 100644 --- a/src/fsfw/cfdp/definitions.h +++ b/src/fsfw/cfdp/definitions.h @@ -40,7 +40,7 @@ static constexpr ReturnValue_t FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE = //! Checksum types according to the SANA Checksum Types registry //! https://sanaregistry.org/r/checksum_identifiers/ -enum ChecksumType { +enum ChecksumTypes { // Modular legacy checksum MODULAR = 0, CRC_32_PROXIMITY_1 = 1, diff --git a/src/fsfw/cfdp/handler/DestHandler.cpp b/src/fsfw/cfdp/handler/DestHandler.cpp index 33947dcd..b6c42601 100644 --- a/src/fsfw/cfdp/handler/DestHandler.cpp +++ b/src/fsfw/cfdp/handler/DestHandler.cpp @@ -1,5 +1,7 @@ #include "DestHandler.h" +#include + #include #include "fsfw/FSFW.h" @@ -177,6 +179,8 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "File write error" << std::endl; #endif + } else { + tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE; } return result; } @@ -300,7 +304,18 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met cfdp::CfdpStates cfdp::DestHandler::getCfdpState() const { return cfdpState; } ReturnValue_t cfdp::DestHandler::handleTransferCompletion() { - // TODO: Checksum verification and notice of completion + ReturnValue_t result; + if (tp.checksumType != ChecksumTypes::NULL_CHECKSUM) { + result = checksumVerification(); + if (result != OK) { + // TODO: Warning / error handling? + } + } else { + tp.conditionCode = ConditionCode::NO_ERROR; + } + result = noticeOfCompletion(); + if (result != OK) { + } if (cfdpState == CfdpStates::BUSY_CLASS_1_NACKED) { if (tp.closureRequested) { step = TransactionStep::SENDING_FINISHED_PDU; @@ -310,8 +325,60 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() { } else if (cfdpState == CfdpStates::BUSY_CLASS_2_ACKED) { step = TransactionStep::SENDING_FINISHED_PDU; } + return OK; } void cfdp::DestHandler::finish() { - // TODO: Clear PDU list, reset state to be ready for next transfer + tp.reset(); + dp.packetListRef.clear(); + cfdpState = CfdpStates::IDLE; + step = TransactionStep::IDLE; +} + +ReturnValue_t cfdp::DestHandler::checksumVerification() { + std::array buf{}; + // TODO: Checksum verification and notice of completion + etl::crc32 crcCalc; + uint64_t currentOffset = 0; + FileOpParams params(tp.sourceName.data(), buf.size()); + while (currentOffset < tp.fileSize.value()) { + uint64_t readLen = 0; + if (currentOffset + buf.size() > tp.fileSize.value()) { + readLen = tp.fileSize.value() - currentOffset; + } else { + readLen = buf.size(); + } + if (readLen > 0) { + params.offset = currentOffset; + params.size = readLen; + auto result = dp.user.vfs.readFromFile(params, buf.data(), buf.size()); + if (result != OK) { + // TODO: Better error handling + return FAILED; + } + crcCalc.add(buf.begin(), buf.begin() + readLen); + } + currentOffset += readLen; + } + + uint32_t value = crcCalc.value(); + if (value == tp.crc) { + tp.conditionCode = ConditionCode::NO_ERROR; + tp.deliveryCode = FileDeliveryCode::DATA_COMPLETE; + } else { + // TODO: Proper error handling +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "CRC check for file " << tp.sourceName.data() << " failed" << std::endl; +#endif + tp.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE; + } + return OK; +} +ReturnValue_t cfdp::DestHandler::noticeOfCompletion() { + if (dp.cfg.indicCfg.transactionFinishedIndicRequired) { + TransactionFinishedParams params(tp.transactionId, tp.conditionCode, tp.deliveryCode, + tp.deliveryStatus); + dp.user.transactionFinishedIndication(params); + } + return OK; } diff --git a/src/fsfw/cfdp/handler/DestHandler.h b/src/fsfw/cfdp/handler/DestHandler.h index 9b607d65..289407c5 100644 --- a/src/fsfw/cfdp/handler/DestHandler.h +++ b/src/fsfw/cfdp/handler/DestHandler.h @@ -98,13 +98,32 @@ class DestHandler { explicit TransactionParams(size_t maxFileNameLen) : sourceName(maxFileNameLen), destName(maxFileNameLen) {} - ChecksumType checksumType = ChecksumType::NULL_CHECKSUM; + void reset() { + pduConf = PduConfig(); + transactionId = TransactionId(); + std::fill(sourceName.begin(), sourceName.end(), '\0'); + std::fill(destName.begin(), destName.end(), '\0'); + fileSize.setFileSize(0, false); + conditionCode = ConditionCode::NO_ERROR; + deliveryCode = FileDeliveryCode::DATA_INCOMPLETE; + deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY; + crc = 0; + progress = 0; + remoteCfg = nullptr; + closureRequested = false; + checksumType = ChecksumTypes::NULL_CHECKSUM; + } + + ChecksumTypes checksumType = ChecksumTypes::NULL_CHECKSUM; bool closureRequested = false; std::vector sourceName; std::vector destName; cfdp::FileSize fileSize; TransactionId transactionId; PduConfig pduConf; + ConditionCode conditionCode = ConditionCode::NO_ERROR; + FileDeliveryCode deliveryCode = FileDeliveryCode::DATA_INCOMPLETE; + FileDeliveryStatus deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY; uint32_t crc = 0; uint64_t progress = 0; RemoteEntityCfg* remoteCfg = nullptr; @@ -124,6 +143,8 @@ class DestHandler { ReturnValue_t handleEofPdu(const PacketInfo& info); ReturnValue_t handleMetadataParseError(const uint8_t* rawData, size_t maxSize); ReturnValue_t handleTransferCompletion(); + ReturnValue_t noticeOfCompletion(); + ReturnValue_t checksumVerification(); void finish(); }; diff --git a/src/fsfw/cfdp/handler/UserBase.h b/src/fsfw/cfdp/handler/UserBase.h index f9db4f49..e367b4a8 100644 --- a/src/fsfw/cfdp/handler/UserBase.h +++ b/src/fsfw/cfdp/handler/UserBase.h @@ -14,11 +14,11 @@ namespace cfdp { struct TransactionFinishedParams { - TransactionFinishedParams(TransactionId id, ConditionCode code, FileDeliveryStatus status, - FileDeliveryCode delivCode) - : id(std::move(id)), condCode(code), status(status), deliveryCode(delivCode) {} + TransactionFinishedParams(const TransactionId& id, ConditionCode code, FileDeliveryCode delivCode, + FileDeliveryStatus status) + : id(id), condCode(code), status(status), deliveryCode(delivCode) {} - TransactionId id; + const TransactionId& id; ConditionCode condCode; FileDeliveryStatus status; FileDeliveryCode deliveryCode; diff --git a/src/fsfw/cfdp/handler/mib.h b/src/fsfw/cfdp/handler/mib.h index 11f403dd..3b4c95e4 100644 --- a/src/fsfw/cfdp/handler/mib.h +++ b/src/fsfw/cfdp/handler/mib.h @@ -32,7 +32,7 @@ struct RemoteEntityCfg { bool closureRequested = false; bool crcOnTransmission = false; TransmissionModes defaultTransmissionMode = TransmissionModes::UNACKNOWLEDGED; - ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM; + ChecksumTypes defaultChecksum = ChecksumTypes::NULL_CHECKSUM; const uint8_t version = CFDP_VERSION_2; }; diff --git a/src/fsfw/cfdp/pdu/MetadataInfo.cpp b/src/fsfw/cfdp/pdu/MetadataInfo.cpp index d88bdd87..e1eb3ad8 100644 --- a/src/fsfw/cfdp/pdu/MetadataInfo.cpp +++ b/src/fsfw/cfdp/pdu/MetadataInfo.cpp @@ -1,6 +1,6 @@ #include "MetadataInfo.h" -MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, +MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumTypes checksumType, cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName, cfdp::StringLv& destFileName) : MetadataInfo(fileSize, sourceFileName, destFileName) { @@ -23,9 +23,9 @@ void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray_, std::optional optionsLen, std::optional maxOptionsLen); - [[nodiscard]] cfdp::ChecksumType getChecksumType() const; - void setChecksumType(cfdp::ChecksumType checksumType); + [[nodiscard]] cfdp::ChecksumTypes getChecksumType() const; + void setChecksumType(cfdp::ChecksumTypes checksumType); [[nodiscard]] bool isClosureRequested() const; void setClosureRequested(bool closureRequested = false); @@ -42,7 +42,7 @@ class MetadataInfo { private: bool closureRequested = false; - cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM; + cfdp::ChecksumTypes checksumType = cfdp::ChecksumTypes::NULL_CHECKSUM; cfdp::FileSize& fileSize; cfdp::StringLv& sourceFileName; cfdp::StringLv& destFileName; diff --git a/src/fsfw/cfdp/pdu/MetadataPduReader.cpp b/src/fsfw/cfdp/pdu/MetadataPduReader.cpp index 66025140..caf8287b 100644 --- a/src/fsfw/cfdp/pdu/MetadataPduReader.cpp +++ b/src/fsfw/cfdp/pdu/MetadataPduReader.cpp @@ -15,7 +15,7 @@ ReturnValue_t MetadataPduReader::parseData() { return SerializeIF::STREAM_TOO_SHORT; } info.setClosureRequested((*buf >> 6) & 0x01); - info.setChecksumType(static_cast(*buf & 0x0f)); + info.setChecksumType(static_cast(*buf & 0x0f)); remSize -= 1; buf += 1; auto endianness = getEndianness(); diff --git a/unittests/cfdp/handler/testDistributor.cpp b/unittests/cfdp/handler/testDistributor.cpp index 368ca9c0..f33e1115 100644 --- a/unittests/cfdp/handler/testDistributor.cpp +++ b/unittests/cfdp/handler/testDistributor.cpp @@ -30,7 +30,7 @@ TEST_CASE("CFDP Distributor", "[cfdp][distributor]") { cfdp::StringLv sourceFileName(sourceFileString); std::string destFileString = "hello2.txt"; cfdp::StringLv destFileName(destFileString); - MetadataInfo metadataInfo(false, cfdp::ChecksumType::CRC_32, fileSize, sourceFileName, + MetadataInfo metadataInfo(false, cfdp::ChecksumTypes::CRC_32, fileSize, sourceFileName, destFileName); MetadataPduCreator creator(pduConf, metadataInfo); uint8_t* dataPtr = nullptr; diff --git a/unittests/cfdp/pdu/testMetadataPdu.cpp b/unittests/cfdp/pdu/testMetadataPdu.cpp index 49f1deb4..18b60409 100644 --- a/unittests/cfdp/pdu/testMetadataPdu.cpp +++ b/unittests/cfdp/pdu/testMetadataPdu.cpp @@ -23,7 +23,7 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") { cfdp::StringLv sourceFileName(firstFileName); cfdp::StringLv destFileName; FileSize fileSize(35); - MetadataInfo info(false, ChecksumType::MODULAR, fileSize, sourceFileName, destFileName); + MetadataInfo info(false, ChecksumTypes::MODULAR, fileSize, sourceFileName, destFileName); FilestoreResponseTlv response(FilestoreActionCode::CREATE_DIRECTORY, FSR_CREATE_NOT_ALLOWED, sourceFileName, nullptr); @@ -74,7 +74,7 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") { REQUIRE(info.getMaxOptionsLen() == 2); info.setMaxOptionsLen(3); REQUIRE(info.getMaxOptionsLen() == 3); - info.setChecksumType(cfdp::ChecksumType::CRC_32C); + info.setChecksumType(cfdp::ChecksumTypes::CRC_32C); info.setClosureRequested(true); uint8_t* buffer = mdBuffer.data(); size_t sz = 0; @@ -83,8 +83,8 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") { result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK); REQUIRE(result == returnvalue::OK); REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 37); - auto checksumType = static_cast(mdBuffer[11] & 0x0f); - REQUIRE(checksumType == cfdp::ChecksumType::CRC_32C); + auto checksumType = static_cast(mdBuffer[11] & 0x0f); + REQUIRE(checksumType == cfdp::ChecksumTypes::CRC_32C); bool closureRequested = mdBuffer[11] >> 6 & 0x01; REQUIRE(closureRequested == true); // The size of the two options is 19. Summing up: @@ -130,7 +130,7 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") { size_t maxSize = 4; info.setOptionsArray(options.data(), sizeOfOptions, maxSize); REQUIRE(info.getOptionsLen() == 2); - info.setChecksumType(cfdp::ChecksumType::CRC_32C); + info.setChecksumType(cfdp::ChecksumTypes::CRC_32C); info.setClosureRequested(true); uint8_t* buffer = mdBuffer.data(); size_t sz = 0;