diff --git a/.gitignore b/.gitignore
index eb461072..a5a8d2ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
# PyCharm and CLion
-/.idea/*
+.idea/*
!/.idea/runConfigurations
!/.idea/cmake.xml
!/.idea/codeStyles
diff --git a/.idea/cmake.xml b/.idea/cmake.xml
index b0a4921a..8986ec94 100644
--- a/.idea/cmake.xml
+++ b/.idea/cmake.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/src/fsfw/CMakeLists.txt b/src/fsfw/CMakeLists.txt
index e645d34f..c8d4dc37 100644
--- a/src/fsfw/CMakeLists.txt
+++ b/src/fsfw/CMakeLists.txt
@@ -32,6 +32,7 @@ add_subdirectory(timemanager)
add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices)
add_subdirectory(filesystem)
+add_subdirectory(util)
# Optional
diff --git a/src/fsfw/cfdp/CfdpMessage.cpp b/src/fsfw/cfdp/CfdpMessage.cpp
index ea4e2c98..f5bff8fd 100644
--- a/src/fsfw/cfdp/CfdpMessage.cpp
+++ b/src/fsfw/cfdp/CfdpMessage.cpp
@@ -4,8 +4,9 @@ CfdpMessage::CfdpMessage() = default;
CfdpMessage::~CfdpMessage() = default;
-void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
- message->setParameter(cfdpPacket.raw);
+void CfdpMessage::setPutRequest(CommandMessage *message, store_address_t putRequest) {
+ message->setCommand(PUT_REQUEST);
+ message->setParameter(putRequest.raw);
}
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {
diff --git a/src/fsfw/cfdp/CfdpMessage.h b/src/fsfw/cfdp/CfdpMessage.h
index a3ee9421..b75902eb 100644
--- a/src/fsfw/cfdp/CfdpMessage.h
+++ b/src/fsfw/cfdp/CfdpMessage.h
@@ -11,9 +11,11 @@ class CfdpMessage {
public:
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
+ static const Command_t PUT_REQUEST = MAKE_COMMAND_ID(1);
+ static const Command_t CANCEL_REQUEST = MAKE_COMMAND_ID(1);
virtual ~CfdpMessage();
- static void setCommand(CommandMessage* message, store_address_t cfdpPacket);
+ static void setPutRequest(CommandMessage* message, store_address_t putRequest);
static store_address_t getStoreId(const CommandMessage* message);
diff --git a/src/fsfw/cfdp/FileSize.h b/src/fsfw/cfdp/Fss.h
similarity index 91%
rename from src/fsfw/cfdp/FileSize.h
rename to src/fsfw/cfdp/Fss.h
index b0b48452..f7110122 100644
--- a/src/fsfw/cfdp/FileSize.h
+++ b/src/fsfw/cfdp/Fss.h
@@ -8,11 +8,14 @@
namespace cfdp {
-struct FileSize : public SerializeIF {
+/**
+ * Helper type for the CFDP File Size Sensitive (FSS) fields.
+ */
+struct Fss : public SerializeIF {
public:
- FileSize() = default;
+ Fss() = default;
- explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
+ explicit Fss(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
[[nodiscard]] uint64_t value() const { return fileSize; }
diff --git a/src/fsfw/cfdp/VarLenFields.cpp b/src/fsfw/cfdp/VarLenFields.cpp
index b9e0b3a8..d0582467 100644
--- a/src/fsfw/cfdp/VarLenFields.cpp
+++ b/src/fsfw/cfdp/VarLenFields.cpp
@@ -3,8 +3,8 @@
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h"
-cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() {
- ReturnValue_t result = this->setValue(width, value);
+cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
+ ReturnValue_t result = this->setValueAndWidth(width, value);
if (result != returnvalue::OK) {
#if FSFW_DISABLE_PRINTOUT == 0
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -20,8 +20,8 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
-ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) {
- switch (widthInBytes) {
+ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) {
+ switch (width_) {
case (cfdp::WidthInBytes::ONE_BYTE): {
if (value_ > UINT8_MAX) {
return returnvalue::FAILED;
@@ -43,15 +43,18 @@ ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_
this->value.fourBytes = value_;
break;
}
+ case (cfdp::WidthInBytes::EIGHT_BYTES): {
+ this->value.eightBytes = value_;
+ }
default: {
break;
}
}
- this->width = widthInBytes;
+ this->width = width_;
return returnvalue::OK;
}
-size_t cfdp::VarLenField::getValue() const {
+uint64_t cfdp::VarLenField::getValue() const {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
return value.oneByte;
@@ -62,6 +65,9 @@ size_t cfdp::VarLenField::getValue() const {
case (cfdp::WidthInBytes::FOUR_BYTES): {
return value.fourBytes;
}
+ case (cfdp::WidthInBytes::EIGHT_BYTES): {
+ return value.eightBytes;
+ }
}
return 0;
}
@@ -84,6 +90,10 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
case (cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
}
+ case (cfdp::WidthInBytes::EIGHT_BYTES): {
+ return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize,
+ streamEndianness);
+ }
default: {
return returnvalue::FAILED;
}
@@ -98,11 +108,16 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui
return deSerialize(buffer, size, streamEndianness);
}
+ReturnValue_t cfdp::VarLenField::setValue(uint64_t value_) {
+ return setValueAndWidth(getWidth(), value_);
+}
+
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
value.oneByte = **buffer;
+ *buffer += 1;
*size += 1;
return returnvalue::OK;
}
@@ -112,6 +127,9 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
case (cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
}
+ case (cfdp::WidthInBytes::EIGHT_BYTES): {
+ return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness);
+ }
default: {
return returnvalue::FAILED;
}
@@ -135,3 +153,5 @@ bool cfdp::VarLenField::operator==(const cfdp::VarLenField &other) const {
bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const {
return not(*this == other);
}
+
+void cfdp::VarLenField::setWidth(cfdp::WidthInBytes width_) { this->width = width_; }
diff --git a/src/fsfw/cfdp/VarLenFields.h b/src/fsfw/cfdp/VarLenFields.h
index 2758dc67..8ee15bb1 100644
--- a/src/fsfw/cfdp/VarLenFields.h
+++ b/src/fsfw/cfdp/VarLenFields.h
@@ -25,13 +25,15 @@ class VarLenField : public SerializeIF {
template
explicit VarLenField(UnsignedByteField byteField);
- VarLenField(cfdp::WidthInBytes width, size_t value);
+ VarLenField(cfdp::WidthInBytes width, uint64_t value);
bool operator==(const VarLenField &other) const;
bool operator!=(const VarLenField &other) const;
bool operator<(const VarLenField &other) const;
- ReturnValue_t setValue(cfdp::WidthInBytes, size_t value);
+ ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value);
+ void setWidth(cfdp::WidthInBytes width);
+ ReturnValue_t setValue(uint64_t value);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
@@ -42,7 +44,7 @@ class VarLenField : public SerializeIF {
Endianness streamEndianness);
[[nodiscard]] cfdp::WidthInBytes getWidth() const;
- [[nodiscard]] size_t getValue() const;
+ [[nodiscard]] uint64_t getValue() const;
#if FSFW_CPP_OSTREAM_ENABLED == 1
friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) {
@@ -65,7 +67,7 @@ template
cfdp::VarLenField::VarLenField(UnsignedByteField byteField)
: width(static_cast(sizeof(T))) {
static_assert((sizeof(T) % 2) == 0);
- setValue(width, byteField.getValue());
+ setValueAndWidth(width, byteField.getValue());
}
struct EntityId : public VarLenField {
@@ -74,6 +76,32 @@ struct EntityId : public VarLenField {
template
explicit EntityId(UnsignedByteField byteField) : VarLenField(byteField) {}
EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {}
+
+ ReturnValue_t serializeAsLv(uint8_t **buffer, size_t *size, size_t maxSize) const {
+ if (buffer == nullptr or size == nullptr) {
+ return returnvalue::FAILED;
+ }
+ if (*size + 1 + getWidth() > maxSize) {
+ return SerializeIF::BUFFER_TOO_SHORT;
+ }
+ **buffer = getWidth();
+ *buffer += 1;
+ *size += 1;
+ return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK);
+ }
+
+ ReturnValue_t deSerializeFromLv(const uint8_t **buffer, size_t *deserLen) {
+ if (buffer == nullptr or deserLen == nullptr) {
+ return returnvalue::FAILED;
+ }
+ if (*deserLen < 2) {
+ return SerializeIF::STREAM_TOO_SHORT;
+ }
+ auto width = static_cast(**buffer);
+ *buffer += 1;
+ *deserLen -= 1;
+ return VarLenField::deSerialize(width, buffer, deserLen, SerializeIF::Endianness::NETWORK);
+ }
};
struct TransactionSeqNum : public VarLenField {
diff --git a/src/fsfw/cfdp/definitions.h b/src/fsfw/cfdp/definitions.h
index 2d7a37fc..d19d8532 100644
--- a/src/fsfw/cfdp/definitions.h
+++ b/src/fsfw/cfdp/definitions.h
@@ -17,7 +17,7 @@ static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
static constexpr uint8_t CFDP_VERSION_2 = 0b001;
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
-static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP;
+static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP_BASE;
static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1);
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
@@ -68,6 +68,7 @@ enum WidthInBytes : uint8_t {
ONE_BYTE = 1,
TWO_BYTES = 2,
FOUR_BYTES = 4,
+ EIGHT_BYTES = 8
};
enum FileDirective : uint8_t {
@@ -142,6 +143,20 @@ enum RecordContinuationState {
CONTAINS_START_AND_END = 0b11
};
+enum class ProxyOpMessageType : uint8_t {
+ PUT_REQUEST = 0x00,
+ MSG_TO_USR = 0x01,
+ FS_REQUEST = 0x02,
+ FAULT_HANDLER_OVERRIDE = 0x03,
+ TRANSMISSION_MODE = 0x04,
+ FLOW_LABEL = 0x05,
+ SEG_CTRL = 0x06,
+ PUT_RESPONSE = 0x07,
+ FS_RESPONSE = 0x08,
+ PUT_CANCEL = 0x09,
+ CLOSURE = 0x0b
+};
+
} // namespace cfdp
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */
diff --git a/src/fsfw/cfdp/handler/CMakeLists.txt b/src/fsfw/cfdp/handler/CMakeLists.txt
index 7ad995c0..8ba2fec8 100644
--- a/src/fsfw/cfdp/handler/CMakeLists.txt
+++ b/src/fsfw/cfdp/handler/CMakeLists.txt
@@ -1,2 +1,4 @@
-target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
- FaultHandlerBase.cpp UserBase.cpp)
+target_sources(
+ ${LIB_FSFW_NAME}
+ PRIVATE SourceHandler.cpp DestHandler.cpp PutRequest.cpp
+ ReservedMessageParser.cpp FaultHandlerBase.cpp UserBase.cpp)
diff --git a/src/fsfw/cfdp/handler/DestHandler.cpp b/src/fsfw/cfdp/handler/DestHandler.cpp
index 364897ee..d9c8793d 100644
--- a/src/fsfw/cfdp/handler/DestHandler.cpp
+++ b/src/fsfw/cfdp/handler/DestHandler.cpp
@@ -16,25 +16,26 @@ using namespace returnvalue;
cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwParams fsfwParams)
: tlvVec(params.maxTlvsInOnePdu),
- userTlvVec(params.maxTlvsInOnePdu),
- dp(std::move(params)),
- fp(fsfwParams),
- tp(params.maxFilenameLen) {
- tp.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
+ msgToUserVec(params.maxTlvsInOnePdu),
+ transactionParams(params.maxFilenameLen),
+ destParams(std::move(params)),
+ fsfwParams(fsfwParams) {
+ transactionParams.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
}
-const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
+const cfdp::DestHandler::FsmResult& cfdp::DestHandler::stateMachine() {
ReturnValue_t result;
uint8_t errorIdx = 0;
fsmRes.resetOfIteration();
if (fsmRes.step == TransactionStep::IDLE) {
- for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
+ for (auto infoIter = destParams.packetListRef.begin();
+ infoIter != destParams.packetListRef.end();) {
if (infoIter->pduType == PduType::FILE_DIRECTIVE and
infoIter->directiveType == FileDirective::METADATA) {
result = handleMetadataPdu(*infoIter);
checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used
- dp.packetListRef.erase(infoIter++);
+ destParams.packetListRef.erase(infoIter++);
} else {
infoIter++;
}
@@ -42,11 +43,12 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
if (fsmRes.step == TransactionStep::IDLE) {
// To decrease the already high complexity of the software, all packets arriving before
// a metadata PDU are deleted.
- for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
- fp.tcStore->deleteData(infoIter->storeId);
+ for (auto infoIter = destParams.packetListRef.begin();
+ infoIter != destParams.packetListRef.end();) {
+ fsfwParams.tcStore->deleteData(infoIter->storeId);
infoIter++;
}
- dp.packetListRef.clear();
+ destParams.packetListRef.clear();
}
if (fsmRes.step != TransactionStep::IDLE) {
@@ -54,21 +56,22 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
}
return updateFsmRes(errorIdx);
}
- if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
+ if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
- for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
+ for (auto infoIter = destParams.packetListRef.begin();
+ infoIter != destParams.packetListRef.end();) {
if (infoIter->pduType == PduType::FILE_DATA) {
result = handleFileDataPdu(*infoIter);
checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used
- dp.packetListRef.erase(infoIter++);
+ destParams.packetListRef.erase(infoIter++);
} else if (infoIter->pduType == PduType::FILE_DIRECTIVE and
infoIter->directiveType == FileDirective::EOF_DIRECTIVE) {
// TODO: Support for check timer missing
result = handleEofPdu(*infoIter);
checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used
- dp.packetListRef.erase(infoIter++);
+ destParams.packetListRef.erase(infoIter++);
} else {
infoIter++;
}
@@ -85,7 +88,7 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
}
return updateFsmRes(errorIdx);
}
- if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
+ if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
// TODO: Will be implemented at a later stage
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CFDP state machine for acknowledged mode not implemented yet" << std::endl;
@@ -95,29 +98,29 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
}
ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) {
- if (dp.packetListRef.full()) {
+ if (destParams.packetListRef.full()) {
return FAILED;
}
- dp.packetListRef.push_back(packet);
+ destParams.packetListRef.push_back(packet);
return OK;
}
ReturnValue_t cfdp::DestHandler::initialize() {
- if (fp.tmStore == nullptr) {
- fp.tmStore = ObjectManager::instance()->get(objects::TM_STORE);
- if (fp.tmStore == nullptr) {
+ if (fsfwParams.tmStore == nullptr) {
+ fsfwParams.tmStore = ObjectManager::instance()->get(objects::TM_STORE);
+ if (fsfwParams.tmStore == nullptr) {
return FAILED;
}
}
- if (fp.tcStore == nullptr) {
- fp.tcStore = ObjectManager::instance()->get(objects::TC_STORE);
- if (fp.tcStore == nullptr) {
+ if (fsfwParams.tcStore == nullptr) {
+ fsfwParams.tcStore = ObjectManager::instance()->get(objects::TC_STORE);
+ if (fsfwParams.tcStore == nullptr) {
return FAILED;
}
}
- if (fp.msgQueue == nullptr) {
+ if (fsfwParams.msgQueue == nullptr) {
return FAILED;
}
return OK;
@@ -125,18 +128,16 @@ ReturnValue_t cfdp::DestHandler::initialize() {
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
// Process metadata PDU
- auto constAccessorPair = fp.tcStore->getData(info.storeId);
+ auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
cfdp::StringLv sourceFileName;
cfdp::StringLv destFileName;
- MetadataInfo metadataInfo(tp.fileSize, sourceFileName, destFileName);
- cfdp::Tlv* tlvArrayAsPtr = tlvVec.data();
- metadataInfo.setOptionsArray(&tlvArrayAsPtr, std::nullopt, tlvVec.size());
+ MetadataGenericInfo metadataInfo(transactionParams.fileSize);
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
- metadataInfo);
+ metadataInfo, tlvVec.data(), tlvVec.size());
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
@@ -145,18 +146,17 @@ ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
return handleMetadataParseError(result, constAccessorPair.second.data(),
constAccessorPair.second.size());
}
- return startTransaction(reader, metadataInfo);
+ return startTransaction(reader);
}
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
// Process file data PDU
- auto constAccessorPair = fp.tcStore->getData(info.storeId);
+ auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
- cfdp::FileSize offset;
- FileDataInfo fdInfo(offset);
+ FileDataInfo fdInfo;
FileDataReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), fdInfo);
ReturnValue_t result = reader.parseData();
if (result != OK) {
@@ -164,46 +164,46 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info)
}
size_t fileSegmentLen = 0;
const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen);
- FileOpParams fileOpParams(tp.destName.data(), fileSegmentLen);
- fileOpParams.offset = offset.value();
- if (dp.cfg.indicCfg.fileSegmentRecvIndicRequired) {
+ FileOpParams fileOpParams(transactionParams.destName.data(), fileSegmentLen);
+ fileOpParams.offset = fdInfo.getOffset().value();
+ if (destParams.cfg.indicCfg.fileSegmentRecvIndicRequired) {
FileSegmentRecvdParams segParams;
- segParams.offset = offset.value();
- segParams.id = tp.transactionId;
+ segParams.offset = fdInfo.getOffset().value();
+ segParams.id = transactionParams.transactionId;
segParams.length = fileSegmentLen;
segParams.recContState = fdInfo.getRecordContinuationState();
size_t segmentMetadatLen = 0;
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
segParams.segmentMetadata = {segMetadata, segmentMetadatLen};
- dp.user.fileSegmentRecvdIndication(segParams);
+ destParams.user.fileSegmentRecvdIndication(segParams);
}
- result = dp.user.vfs.writeToFile(fileOpParams, fileData);
+ result = destParams.user.vfs.writeToFile(fileOpParams, fileData);
if (result != returnvalue::OK) {
// TODO: Proper Error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
<< result << std::endl;
#endif
- tp.vfsErrorCount++;
- if (tp.vfsErrorCount < 3) {
+ transactionParams.vfsErrorCount++;
+ if (transactionParams.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter
- fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast(fsmRes.step),
- result);
+ fsfwParams.eventReporter->forwardEvent(events::FILESTORE_ERROR,
+ static_cast(fsmRes.step), result);
}
return result;
} else {
- tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
- tp.vfsErrorCount = 0;
+ transactionParams.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
+ transactionParams.vfsErrorCount = 0;
}
- if (offset.value() + fileSegmentLen > tp.progress) {
- tp.progress = offset.value() + fileSegmentLen;
+ if (fdInfo.getOffset().value() + fileSegmentLen > transactionParams.progress) {
+ transactionParams.progress = fdInfo.getOffset().value() + fileSegmentLen;
}
return result;
}
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
// Process EOF PDU
- auto constAccessorPair = fp.tcStore->getData(info.storeId);
+ auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
@@ -216,21 +216,21 @@ ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
}
// TODO: Error handling
if (eofInfo.getConditionCode() == ConditionCode::NO_ERROR) {
- tp.crc = eofInfo.getChecksum();
+ transactionParams.crc = eofInfo.getChecksum();
uint64_t fileSizeFromEof = eofInfo.getFileSize().value();
// CFDP 4.6.1.2.9: Declare file size error if progress exceeds file size
- if (fileSizeFromEof > tp.progress) {
+ if (fileSizeFromEof > transactionParams.progress) {
// TODO: File size error
}
- tp.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
+ transactionParams.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
}
- if (dp.cfg.indicCfg.eofRecvIndicRequired) {
- dp.user.eofRecvIndication(getTransactionId());
+ if (destParams.cfg.indicCfg.eofRecvIndicRequired) {
+ destParams.user.eofRecvIndication(getTransactionId());
}
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
- if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
+ if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
- } else if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
+ } else if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
fsmRes.step = TransactionStep::SENDING_ACK_PDU;
}
}
@@ -260,7 +260,7 @@ ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
cfdp::EntityId destId;
headerReader.getDestId(destId);
RemoteEntityCfg* remoteCfg;
- if (not dp.remoteCfgTable.getRemoteCfg(destId, &remoteCfg)) {
+ if (not destParams.remoteCfgTable.getRemoteCfg(destId, &remoteCfg)) {
// TODO: No remote config for dest ID. I consider this a configuration error, which is not
// covered by the standard.
// Warning or error, yield or cache appropriate returnvalue
@@ -274,51 +274,57 @@ ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
return returnvalue::FAILED;
}
-ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, MetadataInfo& info) {
- if (fsmRes.state != CfdpStates::IDLE) {
+ReturnValue_t cfdp::DestHandler::startTransaction(const MetadataPduReader& reader) {
+ if (fsmRes.state != CfdpState::IDLE) {
// According to standard, discard metadata PDU if we are busy
return OK;
}
ReturnValue_t result = OK;
size_t sourceNameSize = 0;
- const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
- if (sourceNameSize + 1 > tp.sourceName.size()) {
- fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
- return FAILED;
+ if (not reader.getSourceFileName().isEmpty()) {
+ const uint8_t* sourceNamePtr = reader.getSourceFileName().getValue(&sourceNameSize);
+ if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
+ fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
+ return FAILED;
+ }
+ std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
+ transactionParams.sourceName[sourceNameSize] = '\0';
}
- std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
- tp.sourceName[sourceNameSize] = '\0';
size_t destNameSize = 0;
- const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
- if (destNameSize + 1 > tp.destName.size()) {
- fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
- return FAILED;
+ if (not reader.getDestFileName().isEmpty()) {
+ const uint8_t* destNamePtr = reader.getDestFileName().getValue(&destNameSize);
+ if (destNameSize + 1 > transactionParams.destName.size()) {
+ fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
+ return FAILED;
+ }
+ std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
+ transactionParams.destName[destNameSize] = '\0';
}
- std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
- tp.destName[destNameSize] = '\0';
+ transactionParams.metadataOnly = true;
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
// so there is no need to create a file or truncate an existing file
if (destNameSize > 0 and sourceNameSize > 0) {
- FilesystemParams fparams(tp.destName.data());
+ transactionParams.metadataOnly = false;
+ FilesystemParams fparams(transactionParams.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
- if (dp.user.vfs.isDirectory(tp.destName.data())) {
+ if (destParams.user.vfs.isDirectory(transactionParams.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
- if (dp.user.vfs.fileExists(fparams)) {
- result = dp.user.vfs.truncateFile(fparams);
+ if (destParams.user.vfs.fileExists(fparams)) {
+ result = destParams.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
} else {
- result = dp.user.vfs.createFile(fparams);
+ result = destParams.user.vfs.createFile(fparams);
if (result != OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
return FAILED;
@@ -328,122 +334,135 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
}
EntityId sourceId;
reader.getSourceId(sourceId);
- if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) {
+ if (not destParams.remoteCfgTable.getRemoteCfg(sourceId, &transactionParams.remoteCfg)) {
// TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__
<< ": No remote configuration found for destination ID "
- << tp.pduConf.sourceId.getValue() << std::endl;
+ << transactionParams.pduConf.sourceId.getValue() << std::endl;
#endif
return FAILED;
}
- fsmRes.step = TransactionStep::TRANSACTION_START;
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
- fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
+ fsmRes.state = CfdpState::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
- fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
+ fsmRes.state = CfdpState::BUSY_CLASS_2_ACKED;
}
- tp.checksumType = info.getChecksumType();
- tp.closureRequested = info.isClosureRequested();
- reader.fillConfig(tp.pduConf);
- tp.pduConf.direction = Direction::TOWARDS_SENDER;
- tp.transactionId.entityId = tp.pduConf.sourceId;
- tp.transactionId.seqNum = tp.pduConf.seqNum;
- fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
- MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
- params.fileSize = tp.fileSize.getSize();
- params.destFileName = tp.destName.data();
- params.sourceFileName = tp.sourceName.data();
- params.msgsToUserArray = dynamic_cast(userTlvVec.data());
- params.msgsToUserLen = info.getOptionsLen();
- dp.user.metadataRecvdIndication(params);
+ if (transactionParams.metadataOnly) {
+ fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
+ } else {
+ // Kind of ugly, make FSM working on packet per packet basis..
+ fsmRes.step = TransactionStep::TRANSACTION_START;
+ fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
+ }
+ auto& info = reader.getGenericInfo();
+ transactionParams.checksumType = info.getChecksumType();
+ transactionParams.closureRequested = info.isClosureRequested();
+ reader.fillConfig(transactionParams.pduConf);
+ transactionParams.pduConf.direction = Direction::TOWARDS_SENDER;
+ transactionParams.transactionId.entityId = transactionParams.pduConf.sourceId;
+ transactionParams.transactionId.seqNum = transactionParams.pduConf.seqNum;
+ transactionParams.fileSize = info.getFileSize();
+ MetadataRecvdParams params(transactionParams.transactionId, transactionParams.pduConf.sourceId,
+ transactionParams.fileSize);
+ params.destFileName = transactionParams.destName.data();
+ params.sourceFileName = transactionParams.sourceName.data();
+ params.numberOfMsgsToUser = 0;
+ for (const auto& opt : tlvVec) {
+ if (opt.getType() == TlvType::MSG_TO_USER) {
+ msgToUserVec[params.numberOfMsgsToUser] =
+ MessageToUserTlv(opt.getValue(), opt.getLengthField());
+ params.numberOfMsgsToUser++;
+ }
+ }
+ params.msgsToUserArray = msgToUserVec.data();
+ destParams.user.metadataRecvdIndication(params);
return result;
}
-cfdp::CfdpStates cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
+cfdp::CfdpState cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
ReturnValue_t result;
- if (tp.checksumType != ChecksumType::NULL_CHECKSUM) {
+ if (transactionParams.checksumType != ChecksumType::NULL_CHECKSUM) {
result = checksumVerification();
if (result != OK) {
// TODO: Warning / error handling?
}
} else {
- tp.conditionCode = ConditionCode::NO_ERROR;
+ transactionParams.conditionCode = ConditionCode::NO_ERROR;
}
result = noticeOfCompletion();
if (result != OK) {
}
- if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
- if (tp.closureRequested) {
+ if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
+ if (transactionParams.closureRequested) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
} else {
finish();
}
- } else if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
+ } else if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
- // Maximum allowed path size is 255 characters, so this should be enough to hold the full
- // base name in any case.
- char baseNameBuf[524]{};
- FilesystemParams fparamsSrc(tp.sourceName.data());
+ // A path may only have a maximum of 256 characters in CFDP, so this buffer should be sufficient
+ // for all use-cases.
+ char baseNameBuf[512]{};
+ FilesystemParams fparamsSrc(transactionParams.sourceName.data());
size_t baseNameLen = 0;
- ReturnValue_t result =
- dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen);
+ ReturnValue_t result = destParams.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf,
+ sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED;
}
// Destination name + slash + base name + null termination
- if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) {
+ if (destNameSize + 1 + baseNameLen + 1 > transactionParams.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
- tp.destName[destNameSize++] = '/';
- std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen);
+ transactionParams.destName[destNameSize++] = '/';
+ std::memcpy(transactionParams.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
- tp.destName[destNameSize++] = '\0';
+ transactionParams.destName[destNameSize++] = '\0';
return OK;
}
-void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
- fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
- static_cast(fsmRes.step), result);
+void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result,
+ const char* info) const {
+ fsfwParams.eventReporter->forwardEvent(event, static_cast(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif
}
void cfdp::DestHandler::finish() {
- tp.reset();
- dp.packetListRef.clear();
- fsmRes.state = CfdpStates::IDLE;
+ transactionParams.reset();
+ destParams.packetListRef.clear();
+ fsmRes.state = CfdpState::IDLE;
fsmRes.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.destName.data(), tp.fileSize.value());
- while (currentOffset < tp.fileSize.value()) {
+ FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
+ while (currentOffset < transactionParams.fileSize.value()) {
uint64_t readLen;
- if (currentOffset + buf.size() > tp.fileSize.value()) {
- readLen = tp.fileSize.value() - currentOffset;
+ if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
+ readLen = transactionParams.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());
+ auto result = destParams.user.vfs.readFromFile(params, buf.data(), buf.size());
if (result != OK) {
// TODO: I think this is a case for a filestore rejection, but it might sense to print
// a warning or trigger an event because this should generally not happen
@@ -455,40 +474,43 @@ ReturnValue_t cfdp::DestHandler::checksumVerification() {
}
uint32_t value = crcCalc.value();
- if (value == tp.crc) {
- tp.conditionCode = ConditionCode::NO_ERROR;
- tp.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
+ if (value == transactionParams.crc) {
+ transactionParams.conditionCode = ConditionCode::NO_ERROR;
+ transactionParams.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
} else {
// TODO: Proper error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
- sif::warning << "CRC check for file " << tp.destName.data() << " failed" << std::endl;
+ sif::warning << "CRC check for file " << transactionParams.destName.data() << " failed"
+ << std::endl;
#endif
- tp.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
+ transactionParams.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);
+ if (destParams.cfg.indicCfg.transactionFinishedIndicRequired) {
+ TransactionFinishedParams params(
+ transactionParams.transactionId, transactionParams.conditionCode,
+ transactionParams.deliveryCode, transactionParams.deliveryStatus);
+ destParams.user.transactionFinishedIndication(params);
}
return OK;
}
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
- FinishedInfo info(tp.conditionCode, tp.deliveryCode, tp.deliveryStatus);
- FinishPduCreator finishedPdu(tp.pduConf, info);
+ FinishedInfo info(transactionParams.conditionCode, transactionParams.deliveryCode,
+ transactionParams.deliveryStatus);
+ FinishPduCreator finishedPdu(transactionParams.pduConf, info);
store_address_t storeId;
uint8_t* dataPtr = nullptr;
ReturnValue_t result =
- fp.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
+ fsfwParams.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler:sendFinishedPdu: Getting store slot failed" << std::endl;
#endif
- fp.eventReporter->forwardEvent(events::STORE_ERROR, result, 0);
+ fsfwParams.eventReporter->forwardEvent(events::STORE_ERROR, result, 0);
return result;
}
size_t serLen = 0;
@@ -498,16 +520,16 @@ ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Serializing Finished PDU failed"
<< std::endl;
#endif
- fp.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
+ fsfwParams.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
return result;
}
TmTcMessage msg(storeId);
- result = fp.msgQueue->sendMessage(fp.packetDest.getReportReceptionQueue(), &msg);
+ result = fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &msg);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
#endif
- fp.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0);
+ fsfwParams.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0);
return result;
}
fsmRes.packetsSent++;
@@ -527,7 +549,9 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::updateFsmRes(uint8_t erro
return fsmRes;
}
-const cfdp::TransactionId& cfdp::DestHandler::getTransactionId() const { return tp.transactionId; }
+const cfdp::TransactionId& cfdp::DestHandler::getTransactionId() const {
+ return transactionParams.transactionId;
+}
void cfdp::DestHandler::checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx) {
if (result != OK and errorIdx < 3) {
@@ -536,13 +560,15 @@ void cfdp::DestHandler::checkAndHandleError(ReturnValue_t result, uint8_t& error
}
}
-void cfdp::DestHandler::setMsgQueue(MessageQueueIF& queue) { fp.msgQueue = &queue; }
+void cfdp::DestHandler::setMsgQueue(MessageQueueIF& queue) { fsfwParams.msgQueue = &queue; }
void cfdp::DestHandler::setEventReporter(EventReportingProxyIF& reporter) {
- fp.eventReporter = &reporter;
+ fsfwParams.eventReporter = &reporter;
}
-const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const { return dp; }
+const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const {
+ return destParams;
+}
-StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fp.tmStore; }
-StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fp.tcStore; }
+StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fsfwParams.tmStore; }
+StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fsfwParams.tcStore; }
diff --git a/src/fsfw/cfdp/handler/DestHandler.h b/src/fsfw/cfdp/handler/DestHandler.h
index 1896c9a2..0eb7b5e8 100644
--- a/src/fsfw/cfdp/handler/DestHandler.h
+++ b/src/fsfw/cfdp/handler/DestHandler.h
@@ -14,6 +14,7 @@
#include "fsfw/cfdp/handler/mib.h"
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
#include "fsfw/cfdp/pdu/PduConfig.h"
+#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/container/DynamicFIFO.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/storagemanager/storeAddress.h"
@@ -21,23 +22,9 @@
namespace cfdp {
-struct PacketInfo {
- PacketInfo(PduType type, store_address_t storeId,
- std::optional directive = std::nullopt)
- : pduType(type), directiveType(directive), storeId(storeId) {}
-
- PduType pduType = PduType::FILE_DATA;
- std::optional directiveType = FileDirective::INVALID_DIRECTIVE;
- store_address_t storeId = store_address_t::invalid();
- PacketInfo() = default;
-};
-
template
using LostSegmentsList = etl::set, SIZE>;
-template
-using PacketInfoList = etl::list;
using LostSegmentsListBase = etl::iset>;
-using PacketInfoListBase = etl::ilist;
struct DestHandlerParams {
DestHandlerParams(LocalEntityCfg cfg, UserBase& user, RemoteConfigTableIF& remoteCfgTable,
@@ -45,6 +32,9 @@ struct DestHandlerParams {
// TODO: This container can potentially take tons of space. For a better
// memory efficient implementation, an additional abstraction could be
// be used so users can use uint32_t as the pair type
+ // TODO: Actually, we can provide a better abstraction via interface, which
+ // allows using something like a bounded map. This simplifies
+ // the implementation significantly.
LostSegmentsListBase& lostSegmentsContainer)
: cfg(std::move(cfg)),
user(user),
@@ -58,31 +48,10 @@ struct DestHandlerParams {
PacketInfoListBase& packetListRef;
LostSegmentsListBase& lostSegmentsContainer;
- uint8_t maxTlvsInOnePdu = 10;
+ uint8_t maxTlvsInOnePdu = 20;
size_t maxFilenameLen = 255;
};
-struct FsfwParams {
- FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
- EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore,
- StorageManagerIF& tmStore)
- : FsfwParams(packetDest, msgQueue, eventReporter) {
- this->tcStore = &tcStore;
- this->tmStore = &tmStore;
- }
-
- FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
- EventReportingProxyIF* eventReporter)
- : packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {}
- AcceptsTelemetryIF& packetDest;
- MessageQueueIF* msgQueue;
- EventReportingProxyIF* eventReporter = nullptr;
- StorageManagerIF* tcStore = nullptr;
- StorageManagerIF* tmStore = nullptr;
-};
-
-enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
-
class DestHandler {
public:
enum class TransactionStep : uint8_t {
@@ -99,7 +68,7 @@ class DestHandler {
ReturnValue_t result = returnvalue::OK;
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
TransactionStep step = TransactionStep::IDLE;
- CfdpStates state = CfdpStates::IDLE;
+ CfdpState state = CfdpState::IDLE;
uint32_t packetsSent = 0;
uint8_t errors = 0;
std::array errorCodes = {};
@@ -124,7 +93,7 @@ class DestHandler {
* - @c returnvalue::OK State machine OK for this execution cycle
* - @c CALL_FSM_AGAIN State machine should be called again.
*/
- const FsmResult& performStateMachine();
+ const FsmResult& stateMachine();
void setMsgQueue(MessageQueueIF& queue);
void setEventReporter(EventReportingProxyIF& reporter);
@@ -132,7 +101,7 @@ class DestHandler {
ReturnValue_t initialize();
- [[nodiscard]] CfdpStates getCfdpState() const;
+ [[nodiscard]] CfdpState getCfdpState() const;
[[nodiscard]] TransactionStep getTransactionStep() const;
[[nodiscard]] const TransactionId& getTransactionId() const;
[[nodiscard]] const DestHandlerParams& getDestHandlerParams() const;
@@ -157,17 +126,19 @@ class DestHandler {
crc = 0;
progress = 0;
remoteCfg = nullptr;
+ metadataOnly = false;
closureRequested = false;
vfsErrorCount = 0;
checksumType = ChecksumType::NULL_CHECKSUM;
}
+ bool metadataOnly = false;
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
bool closureRequested = false;
uint16_t vfsErrorCount = 0;
std::vector sourceName;
std::vector destName;
- cfdp::FileSize fileSize;
+ cfdp::Fss fileSize;
TransactionId transactionId;
PduConfig pduConf;
ConditionCode conditionCode = ConditionCode::NO_ERROR;
@@ -179,13 +150,13 @@ class DestHandler {
};
std::vector tlvVec;
- std::vector userTlvVec;
- DestHandlerParams dp;
- FsfwParams fp;
- TransactionParams tp;
+ std::vector msgToUserVec;
+ TransactionParams transactionParams;
+ DestHandlerParams destParams;
+ cfdp::FsfwParams fsfwParams;
FsmResult fsmRes;
- ReturnValue_t startTransaction(MetadataPduReader& reader, MetadataInfo& info);
+ ReturnValue_t startTransaction(const MetadataPduReader& reader);
ReturnValue_t handleMetadataPdu(const PacketInfo& info);
ReturnValue_t handleFileDataPdu(const PacketInfo& info);
ReturnValue_t handleEofPdu(const PacketInfo& info);
@@ -196,7 +167,7 @@ class DestHandler {
ReturnValue_t sendFinishedPdu();
ReturnValue_t noticeOfCompletion();
ReturnValue_t checksumVerification();
- void fileErrorHandler(Event event, ReturnValue_t result, const char* info);
+ void fileErrorHandler(Event event, ReturnValue_t result, const char* info) const;
const FsmResult& updateFsmRes(uint8_t errors);
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
void finish();
diff --git a/src/fsfw/cfdp/handler/PutRequest.cpp b/src/fsfw/cfdp/handler/PutRequest.cpp
new file mode 100644
index 00000000..a1abcc14
--- /dev/null
+++ b/src/fsfw/cfdp/handler/PutRequest.cpp
@@ -0,0 +1,201 @@
+#include "PutRequest.h"
+
+using namespace returnvalue;
+
+cfdp::PutRequest::PutRequest(cfdp::EntityId destId, const uint8_t *msgsToUser,
+ size_t msgsToUserTotalSize, const uint8_t *fsRequests,
+ size_t fsRequestsSize)
+ : destId(std::move(destId)),
+ metadataOnly(true),
+ msgsToUsersTotalSize(msgsToUserTotalSize),
+ msgsToUserStartPtr(msgsToUser),
+ fsRequestsTotalSize(fsRequestsSize),
+ fsRequestStartPtr(fsRequests) {}
+
+cfdp::PutRequest::PutRequest(cfdp::EntityId destId, cfdp::StringLv &sourceName,
+ cfdp::StringLv &destName)
+ : destId(std::move(destId)), sourceName(std::move(sourceName)), destName(std::move(destName)) {}
+
+[[nodiscard]] bool cfdp::PutRequest::isMetadataOnly() const { return metadataOnly; }
+
+ReturnValue_t cfdp::PutRequest::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
+ SerializeIF::Endianness streamEndianness) const {
+ if (buffer == nullptr or size == nullptr) {
+ return FAILED;
+ }
+ if (*size + getSerializedSize() > maxSize) {
+ return SerializeIF::BUFFER_TOO_SHORT;
+ }
+ ReturnValue_t result = destId.serializeAsLv(buffer, size, maxSize);
+ if (result != OK) {
+ return result;
+ }
+ result = SerializeAdapter::serialize(&metadataOnly, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ if (!metadataOnly) {
+ result = sourceName.serialize(buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result = destName.serialize(buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result =
+ SerializeAdapter::serialize(&hasTransmissionMode, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result =
+ SerializeAdapter::serialize(&transmissionMode, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result =
+ SerializeAdapter::serialize(&hasClosureRequested, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result =
+ SerializeAdapter::serialize(&closureRequested, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ }
+ result =
+ SerializeAdapter::serialize(&msgsToUsersTotalSize, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ std::memcpy(*buffer, msgsToUserStartPtr, msgsToUsersTotalSize);
+ *buffer += msgsToUsersTotalSize;
+ *size += msgsToUsersTotalSize;
+
+ result =
+ SerializeAdapter::serialize(&fsRequestsTotalSize, buffer, size, maxSize, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ std::memcpy(*buffer, fsRequestStartPtr, fsRequestsTotalSize);
+ *buffer += fsRequestsTotalSize;
+ *size += fsRequestsTotalSize;
+ return OK;
+}
+
+ReturnValue_t cfdp::PutRequest::deSerialize(const uint8_t **buffer, size_t *size,
+ SerializeIF::Endianness streamEndianness) {
+ if (buffer == nullptr or size == nullptr) {
+ return FAILED;
+ }
+ ReturnValue_t result = destId.deSerializeFromLv(buffer, size);
+ if (result != OK) {
+ return result;
+ }
+ result = SerializeAdapter::deSerialize(&metadataOnly, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ if (!metadataOnly) {
+ result = sourceName.deSerialize(buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result = destName.deSerialize(buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result = SerializeAdapter::deSerialize(&hasTransmissionMode, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result = SerializeAdapter::deSerialize(&transmissionMode, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result = SerializeAdapter::deSerialize(&hasClosureRequested, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ result = SerializeAdapter::deSerialize(&closureRequested, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ }
+ result = SerializeAdapter::deSerialize(&msgsToUsersTotalSize, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ msgsToUserStartPtr = *buffer;
+ *buffer += msgsToUsersTotalSize;
+ *size += msgsToUsersTotalSize;
+
+ result = SerializeAdapter::deSerialize(&fsRequestsTotalSize, buffer, size, streamEndianness);
+ if (result != OK) {
+ return result;
+ }
+ fsRequestStartPtr = *buffer;
+ *buffer += fsRequestsTotalSize;
+ *size += fsRequestsTotalSize;
+ return OK;
+}
+
+size_t cfdp::PutRequest::getSerializedSize() const {
+ // Entity ID LV (1 leading size byte) and the metadata only flag.
+ size_t baseSize = 1 + destId.getSerializedSize() + 1;
+ if (!metadataOnly) {
+ baseSize += sourceName.getSerializedSize() + destName.getSerializedSize() + 4;
+ }
+ baseSize += sizeof(msgsToUsersTotalSize) + msgsToUsersTotalSize + sizeof(fsRequestsTotalSize) +
+ fsRequestsTotalSize;
+ return baseSize;
+}
+
+void cfdp::PutRequest::setSourceAndDestName(cfdp::StringLv &sourceName_,
+ cfdp::StringLv &destName_) {
+ metadataOnly = false;
+ this->sourceName = std::move(sourceName_);
+ this->destName = std::move(destName_);
+}
+
+const cfdp::StringLv &cfdp::PutRequest::getSourceName() const { return sourceName; }
+
+const cfdp::StringLv &cfdp::PutRequest::getDestName() const { return destName; }
+
+const cfdp::EntityId &cfdp::PutRequest::getDestId() const { return destId; }
+
+void cfdp::PutRequest::setDestId(cfdp::EntityId id) { destId = std::move(id); }
+
+void cfdp::PutRequest::setTransmissionMode(cfdp::TransmissionMode transmissionMode_) {
+ this->transmissionMode = transmissionMode_;
+ hasTransmissionMode = true;
+}
+
+void cfdp::PutRequest::clearTransmissionMode() { hasTransmissionMode = false; }
+
+void cfdp::PutRequest::clearClosureRequest() { hasClosureRequested = false; }
+
+void cfdp::PutRequest::setClosureRequest(bool closureRequested_) {
+ this->closureRequested = closureRequested_;
+ hasClosureRequested = true;
+}
+
+const uint8_t *cfdp::PutRequest::getMessagesToUser(size_t &totalSize) {
+ totalSize = this->msgsToUsersTotalSize;
+ return msgsToUserStartPtr;
+}
+
+bool cfdp::PutRequest::getClosureRequested(bool &closureRequested_) const {
+ if (hasClosureRequested) {
+ closureRequested_ = this->closureRequested;
+ }
+ return hasClosureRequested;
+}
+
+bool cfdp::PutRequest::getTransmissionMode(cfdp::TransmissionMode &mode) const {
+ if (hasTransmissionMode) {
+ mode = static_cast(this->transmissionMode);
+ }
+ return hasTransmissionMode;
+}
diff --git a/src/fsfw/cfdp/handler/PutRequest.h b/src/fsfw/cfdp/handler/PutRequest.h
new file mode 100644
index 00000000..6bf46c60
--- /dev/null
+++ b/src/fsfw/cfdp/handler/PutRequest.h
@@ -0,0 +1,82 @@
+#pragma once
+
+#include
+#include
+
+#include "fsfw/cfdp/VarLenFields.h"
+#include "fsfw/cfdp/tlv/FilestoreRequestTlv.h"
+#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
+
+namespace cfdp {
+
+class PutRequest : public SerializeIF {
+ public:
+ /**
+ * Metadata only constructor.
+ * @param destId
+ * @param msgsToUser
+ * @param msgsToUserTotalSize
+ * @param fsRequests
+ * @param fsRequestsSize
+ */
+ PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
+ const uint8_t* fsRequests, size_t fsRequestsSize);
+ /**
+ * Put request to initiate file transfers. By default, the transmission mode and closure requested
+ * parameter are not present, thereby being derived from the remote configuration for a
+ * particular destination ID.
+ * @param destId
+ * @param sourceName
+ * @param destName
+ */
+ PutRequest(EntityId destId, cfdp::StringLv& sourceName, cfdp::StringLv& destName);
+
+ /**
+ * Default constructor for deserialization.
+ */
+ PutRequest() = default;
+
+ [[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
+ Endianness streamEndianness) const override;
+ ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
+ Endianness streamEndianness) override;
+ [[nodiscard]] size_t getSerializedSize() const override;
+ void setSourceAndDestName(cfdp::StringLv& sourceName, cfdp::StringLv& destName);
+
+ [[nodiscard]] const cfdp::StringLv& getSourceName() const;
+ [[nodiscard]] const cfdp::StringLv& getDestName() const;
+
+ void setTransmissionMode(cfdp::TransmissionMode transmissionMode);
+ void clearTransmissionMode();
+ void setClosureRequest(bool closureRequested);
+ void clearClosureRequest();
+
+ const uint8_t* getMessagesToUser(size_t& msgSize);
+
+ [[nodiscard]] bool isMetadataOnly() const;
+
+ bool getTransmissionMode(TransmissionMode& mode) const;
+ bool getClosureRequested(bool& closureRequested) const;
+
+ [[nodiscard]] const EntityId& getDestId() const;
+ void setDestId(EntityId id);
+
+ private:
+ EntityId destId;
+ uint8_t metadataOnly = true;
+ // Transaction parameters. Omitted if the put request is metadata only.
+ cfdp::StringLv sourceName;
+
+ cfdp::StringLv destName;
+ bool hasTransmissionMode = false;
+ uint8_t transmissionMode = TransmissionMode::UNACKNOWLEDGED;
+ bool hasClosureRequested = false;
+ uint8_t closureRequested = false;
+ // Metadata
+ size_t msgsToUsersTotalSize = 0;
+ const uint8_t* msgsToUserStartPtr = nullptr;
+ size_t fsRequestsTotalSize = 0;
+ const uint8_t* fsRequestStartPtr = nullptr;
+};
+
+} // namespace cfdp
diff --git a/src/fsfw/cfdp/handler/RemoteConfigTableIF.h b/src/fsfw/cfdp/handler/RemoteConfigTableIF.h
index d0e6121d..1c1603c9 100644
--- a/src/fsfw/cfdp/handler/RemoteConfigTableIF.h
+++ b/src/fsfw/cfdp/handler/RemoteConfigTableIF.h
@@ -16,7 +16,7 @@ class RemoteConfigTableIF {
*/
class OneRemoteConfigProvider : public RemoteConfigTableIF {
public:
- explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
+ explicit OneRemoteConfigProvider(RemoteEntityCfg& cfg) : cfg(cfg) {}
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
if (remoteId != cfg.remoteId) {
@@ -27,7 +27,7 @@ class OneRemoteConfigProvider : public RemoteConfigTableIF {
}
private:
- RemoteEntityCfg cfg;
+ RemoteEntityCfg& cfg;
};
} // namespace cfdp
diff --git a/src/fsfw/cfdp/handler/ReservedMessageParser.cpp b/src/fsfw/cfdp/handler/ReservedMessageParser.cpp
new file mode 100644
index 00000000..ffd2fdc6
--- /dev/null
+++ b/src/fsfw/cfdp/handler/ReservedMessageParser.cpp
@@ -0,0 +1,74 @@
+#include "ReservedMessageParser.h"
+
+#include "fsfw/cfdp/CfdpMessage.h"
+#include "fsfw/cfdp/handler/PutRequest.h"
+#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
+#include "fsfw/ipc/CommandMessage.h"
+#include "fsfw/ipc/QueueFactory.h"
+
+using namespace returnvalue;
+
+cfdp::ReservedMessageParser::ReservedMessageParser(StorageManagerIF& ipcStore,
+ MessageQueueIF& msgQueue,
+ MessageQueueId_t userDestination)
+ : msgQueue(msgQueue), ipcStore(ipcStore), userDestination(userDestination) {}
+
+ReturnValue_t cfdp::ReservedMessageParser::parse(const MessageToUserTlv* msgsToUserArray,
+ size_t numMsgToUser) {
+ ReturnValue_t result = returnvalue::OK;
+ cfdp::StringLv sourceFileName;
+ cfdp::StringLv destFileName;
+ PutRequest putRequest;
+ const uint8_t* currentPtr = nullptr;
+ size_t deserSize = 0;
+ bool needToSendPutRequest = false;
+ for (size_t idx = 0; idx < numMsgToUser; idx++) {
+ if (&msgsToUserArray[idx] == nullptr) {
+ continue;
+ }
+ uint8_t messageType = 0;
+ if (msgsToUserArray[idx].isReservedCfdpMessage(messageType, ¤tPtr, deserSize)) {
+ if (messageType == static_cast(ProxyOpMessageType::PUT_REQUEST)) {
+ EntityId entityIdLv;
+ result = entityIdLv.deSerializeFromLv(¤tPtr, &deserSize);
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ putRequest.setDestId(entityIdLv);
+ result =
+ sourceFileName.deSerialize(¤tPtr, &deserSize, SerializeIF::Endianness::NETWORK);
+ if (result != OK) {
+ return result;
+ }
+ result =
+ destFileName.deSerialize(¤tPtr, &deserSize, SerializeIF::Endianness::NETWORK);
+ if (result != OK) {
+ return result;
+ }
+ putRequest.setSourceAndDestName(sourceFileName, destFileName);
+ needToSendPutRequest = true;
+ }
+ }
+ }
+ if (needToSendPutRequest) {
+ store_address_t storeId;
+ uint8_t* dataPtr;
+ result = ipcStore.getFreeElement(&storeId, putRequest.getSerializedSize(), &dataPtr);
+ if (result != OK) {
+ return result;
+ }
+ size_t serLen = 0;
+ result = putRequest.serialize(&dataPtr, &serLen, putRequest.getSerializedSize(),
+ SerializeIF::Endianness::MACHINE);
+ if (result != OK) {
+ return result;
+ }
+ CommandMessage msg;
+ CfdpMessage::setPutRequest(&msg, storeId);
+ result = msgQueue.sendMessage(userDestination, &msg);
+ if (result != OK) {
+ return result;
+ }
+ }
+ return OK;
+}
diff --git a/src/fsfw/cfdp/handler/ReservedMessageParser.h b/src/fsfw/cfdp/handler/ReservedMessageParser.h
new file mode 100644
index 00000000..2b5c89b2
--- /dev/null
+++ b/src/fsfw/cfdp/handler/ReservedMessageParser.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
+#include "fsfw/ipc/MessageQueueIF.h"
+#include "fsfw/storagemanager/StorageManagerIF.h"
+
+namespace cfdp {
+
+/**
+ * This class parses messages to user for special CFDP messages and converts them to appropriate
+ * CFDP requests sent via the IPC store where applicable. It also provides an API to retrieve
+ * custom messages which are not special CFDP messages from a provided bytestream.
+ */
+class ReservedMessageParser {
+ public:
+ ReservedMessageParser(StorageManagerIF& ipcStore, MessageQueueIF& msgQueue,
+ MessageQueueId_t userDestination);
+
+ ReturnValue_t parse(const MessageToUserTlv* msgsToUserArray, size_t numMsgsToUser);
+
+ private:
+ MessageQueueIF& msgQueue;
+ StorageManagerIF& ipcStore;
+ MessageQueueId_t userDestination;
+};
+
+} // namespace cfdp
diff --git a/src/fsfw/cfdp/handler/SourceHandler.cpp b/src/fsfw/cfdp/handler/SourceHandler.cpp
index 513b25f3..f0f89607 100644
--- a/src/fsfw/cfdp/handler/SourceHandler.cpp
+++ b/src/fsfw/cfdp/handler/SourceHandler.cpp
@@ -1 +1,376 @@
#include "SourceHandler.h"
+
+#include
+
+#include
+
+#include "fsfw/cfdp/pdu/EofPduCreator.h"
+#include "fsfw/cfdp/pdu/FileDataCreator.h"
+#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
+#include "fsfw/filesystem/HasFileSystemIF.h"
+#include "fsfw/globalfunctions/arrayprinter.h"
+#include "fsfw/objectmanager.h"
+#include "fsfw/serviceinterface.h"
+#include "fsfw/tasks/TaskFactory.h"
+#include "fsfw/tmtcservices/TmTcMessage.h"
+
+using namespace returnvalue;
+
+cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
+ : sourceParams(std::move(params)), fsfwParams(fsfwParams) {
+ // The entity ID portion of the transaction ID will always remain fixed.
+ transactionParams.id.entityId = sourceParams.cfg.localId;
+ transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
+ if (sourceParams.seqCountProvider.bitWidth() == 8) {
+ transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
+ } else if (sourceParams.seqCountProvider.bitWidth() == 16) {
+ transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::TWO_BYTES);
+ } else if (sourceParams.seqCountProvider.bitWidth() == 32) {
+ transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::FOUR_BYTES);
+ } else if (sourceParams.seqCountProvider.bitWidth() == 64) {
+ transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::EIGHT_BYTES);
+ } else {
+#if FSFW_CPP_OSTREAM_ENABLED == 1
+ sif::error << "cfdp::SourceHandler: Seq count provider bit width "
+ << sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl;
+#else
+ sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n",
+ sourceParams.seqCountProvider.bitWidth());
+#endif
+ // Yeah, what am I supposed to do here? Can't throw an exception in the FSFW..
+ transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
+ }
+ transactionParams.pduConf.seqNum.setValue(0);
+}
+
+cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
+ ReturnValue_t result;
+ if (step == TransactionStep::IDLE) {
+ step = TransactionStep::TRANSACTION_START;
+ }
+ if (step == TransactionStep::TRANSACTION_START) {
+ sourceParams.user.transactionIndication(transactionParams.id);
+ result = checksumGeneration();
+ if (result != OK) {
+ addError(result);
+ }
+ step = TransactionStep::SENDING_METADATA;
+ }
+ if (step == TransactionStep::SENDING_METADATA) {
+ result = prepareAndSendMetadataPdu();
+ if (result != OK) {
+ addError(result);
+ }
+ fsmResult.callStatus = CallStatus::CALL_AGAIN;
+ return fsmResult;
+ }
+ if (step == TransactionStep::SENDING_FILE_DATA) {
+ bool noFdPdu = false;
+ result = prepareAndSendNextFileDataPdu(noFdPdu);
+ if (result == OK and !noFdPdu) {
+ fsmResult.callStatus = CallStatus::CALL_AGAIN;
+ return fsmResult;
+ }
+ }
+ if (step == TransactionStep::SENDING_EOF) {
+ result = prepareAndSendEofPdu();
+ if (result != OK) {
+ addError(result);
+ }
+ if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
+ sourceParams.user.eofSentIndication(transactionParams.id);
+ }
+ if (transactionParams.closureRequested) {
+ step = TransactionStep::WAIT_FOR_FINISH;
+ fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
+ } else {
+ step = TransactionStep::NOTICE_OF_COMPLETION;
+ fsmResult.callStatus = CallStatus::CALL_AGAIN;
+ }
+ return fsmResult;
+ }
+ if (step == TransactionStep::WAIT_FOR_FINISH) {
+ // TODO: In case this is a request with closure, wait for finish.
+ // Done, issue notice of completion
+ step = TransactionStep::NOTICE_OF_COMPLETION;
+ }
+ if (step == TransactionStep::NOTICE_OF_COMPLETION) {
+ noticeOfCompletion();
+ reset();
+ }
+ return fsmResult;
+}
+
+const cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() {
+ fsmResult.packetsSent = 0;
+ fsmResult.errors = 0;
+ fsmResult.callStatus = CallStatus::DONE;
+ if (state == cfdp::CfdpState::IDLE) {
+ return fsmResult;
+ }
+ if (state == cfdp::CfdpState::BUSY_CLASS_1_NACKED) {
+ return fsmNacked();
+ }
+ return fsmResult;
+}
+
+ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
+ if (transactionParams.fileSize.value() == 0) {
+ // NULL checksum for empty file.
+ transactionParams.crc = 0;
+ return OK;
+ }
+ std::array buf{};
+ etl::crc32 crcCalc;
+ uint64_t currentOffset = 0;
+ FileOpParams params(transactionParams.sourceName.data(), transactionParams.fileSize.value());
+ while (currentOffset < transactionParams.fileSize.value()) {
+ uint64_t readLen;
+ if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
+ readLen = transactionParams.fileSize.value() - currentOffset;
+ } else {
+ readLen = buf.size();
+ }
+ if (readLen > 0) {
+ params.offset = currentOffset;
+ params.size = readLen;
+ auto result = sourceParams.user.vfs.readFromFile(params, buf.data(), buf.size());
+ if (result != OK) {
+ addError(result);
+ return FAILED;
+ }
+ crcCalc.add(buf.begin(), buf.begin() + readLen);
+ }
+ currentOffset += readLen;
+ }
+
+ transactionParams.crc = crcCalc.value();
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
+ if (state != CfdpState::IDLE) {
+ return SOURCE_TRANSACTION_PENDING;
+ }
+ if (cfg.remoteId != putRequest.getDestId()) {
+ return WRONG_REMOTE_CFG_ENTITY_ID;
+ }
+ if (putRequest.getSourceName().getValueLen() == 0) {
+ return SOURCE_NAME_EMPTY;
+ }
+ if (putRequest.getDestName().getValueLen() == 0) {
+ return DEST_NAME_EMPTY;
+ }
+ const char* srcNamePtr = putRequest.getSourceName().getCString(transactionParams.sourceNameSize);
+ const char* destNamePtr = putRequest.getDestName().getCString(transactionParams.destNameSize);
+ std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
+ std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
+ // Add 0 termination. The source and dest name size can not be larger than UINT8_MAX, so this
+ // operation is safe.
+ transactionParams.sourceName[transactionParams.sourceNameSize] = '\0';
+ transactionParams.destName[transactionParams.destNameSize] = '\0';
+ FilesystemParams params(transactionParams.sourceName.data());
+ if (!sourceParams.user.vfs.fileExists(params)) {
+ return FILE_DOES_NOT_EXIST;
+ }
+ if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
+ return FILE_SEGMENT_LEN_INVALID;
+ }
+ // If transmission mode is not set, use default transmission mode for the remote entity.
+ if (not putRequest.getTransmissionMode(transactionParams.pduConf.mode)) {
+ transactionParams.pduConf.mode = cfg.defaultTransmissionMode;
+ }
+ // If closure request field is not set, use default option for the remote entity.
+ if (not putRequest.getClosureRequested(transactionParams.closureRequested)) {
+ transactionParams.closureRequested = cfg.closureRequested;
+ }
+ const EntityId& destId = putRequest.getDestId();
+ // The width of the source and destination ID must be the same. Use the larger ID value to
+ // ensure the width is large enough for both IDs
+ if (destId.getWidth() > transactionParams.pduConf.sourceId.getWidth()) {
+ transactionParams.pduConf.destId = destId;
+ transactionParams.pduConf.sourceId.setWidth(destId.getWidth());
+ } else {
+ transactionParams.pduConf.destId.setValueAndWidth(transactionParams.pduConf.sourceId.getWidth(),
+ destId.getValue());
+ }
+ // Only used for PDU forwarding, file is sent to file receiver regularly here.
+ transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
+ transactionParams.pduConf.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement());
+ transactionParams.id.seqNum = transactionParams.pduConf.seqNum;
+
+ if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) {
+ state = cfdp::CfdpState::BUSY_CLASS_2_ACKED;
+ } else if (transactionParams.pduConf.mode == TransmissionMode::UNACKNOWLEDGED) {
+ state = cfdp::CfdpState::BUSY_CLASS_1_NACKED;
+ }
+ step = TransactionStep::IDLE;
+ uint64_t fileSize = 0;
+ sourceParams.user.vfs.getFileSize(params, fileSize);
+ transactionParams.pduConf.largeFile = false;
+ if (fileSize > UINT32_MAX) {
+ transactionParams.pduConf.largeFile = true;
+ }
+ if (fileSize == 0) {
+ transactionParams.checksumType = ChecksumType::NULL_CHECKSUM;
+ } else {
+ transactionParams.checksumType = ChecksumType::CRC_32;
+ }
+ transactionParams.fileSize.setFileSize(fileSize, transactionParams.pduConf.largeFile);
+ transactionParams.progress = 0;
+ transactionParams.remoteCfg = cfg;
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() {
+ cfdp::StringLv sourceName(transactionParams.sourceName.data(), transactionParams.sourceNameSize);
+ cfdp::StringLv destName(transactionParams.destName.data(), transactionParams.destNameSize);
+ auto metadataInfo =
+ MetadataGenericInfo(transactionParams.closureRequested, transactionParams.checksumType,
+ transactionParams.fileSize);
+ auto metadataPdu =
+ MetadataPduCreator(transactionParams.pduConf, metadataInfo, sourceName, destName, nullptr, 0);
+ ReturnValue_t result = sendGenericPdu(metadataPdu);
+ if (result != OK) {
+ return result;
+ }
+ // Advance FSM if everything works
+ step = TransactionStep::SENDING_FILE_DATA;
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu(bool& noFileDataPdu) {
+ cfdp::Fss offset(transactionParams.progress);
+ uint64_t readLen;
+ uint64_t fileSize = transactionParams.fileSize.value();
+ noFileDataPdu = false;
+ if (fileSize == 0) {
+ // We are done, no need to send file data PDUs for an empty file.
+ step = TransactionStep::SENDING_EOF;
+ noFileDataPdu = true;
+ return OK;
+ }
+ if (fileSize < transactionParams.remoteCfg.maxFileSegmentLen) {
+ readLen = transactionParams.fileSize.value();
+ } else {
+ if (transactionParams.progress + transactionParams.remoteCfg.maxFileSegmentLen > fileSize) {
+ readLen = fileSize - transactionParams.progress;
+ } else {
+ readLen = transactionParams.remoteCfg.maxFileSegmentLen;
+ }
+ }
+ FileOpParams fileParams(transactionParams.sourceName.data(), readLen);
+ fileParams.offset = transactionParams.progress;
+ ReturnValue_t result =
+ sourceParams.user.vfs.readFromFile(fileParams, fileBuf.data(), fileBuf.size());
+ if (result != returnvalue::OK) {
+ addError(result);
+ return result;
+ }
+ auto fileDataInfo = FileDataInfo(offset, fileBuf.data(), readLen);
+ auto fileDataPdu = FileDataCreator(transactionParams.pduConf, fileDataInfo);
+ result = sendGenericPdu(fileDataPdu);
+ if (result != OK) {
+ return result;
+ }
+ transactionParams.progress += readLen;
+ if (transactionParams.progress >= fileSize) {
+ // Advance FSM after all file data PDUs were sent.
+ step = TransactionStep::SENDING_EOF;
+ }
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
+ auto eofInfo =
+ EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize);
+ auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
+ ReturnValue_t result = sendGenericPdu(eofPdu);
+ if (result != OK) {
+ return result;
+ }
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::initialize() {
+ if (fsfwParams.tmStore == nullptr) {
+ fsfwParams.tmStore = ObjectManager::instance()->get(objects::TM_STORE);
+ if (fsfwParams.tmStore == nullptr) {
+ return FAILED;
+ }
+ }
+
+ if (fsfwParams.tcStore == nullptr) {
+ fsfwParams.tcStore = ObjectManager::instance()->get(objects::TC_STORE);
+ if (fsfwParams.tcStore == nullptr) {
+ return FAILED;
+ }
+ }
+
+ if (fsfwParams.msgQueue == nullptr) {
+ return FAILED;
+ }
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
+ uint8_t* dataPtr;
+ store_address_t storeId;
+ ReturnValue_t result =
+ fsfwParams.tmStore->getFreeElement(&storeId, pdu.getSerializedSize(), &dataPtr);
+ if (result != OK) {
+ addError(result);
+ fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
+ if (result == StorageManagerIF::DATA_STORAGE_FULL) {
+ return TM_STORE_FULL;
+ }
+ return result;
+ }
+ size_t serializedLen = 0;
+ result = pdu.serializeBe(dataPtr, serializedLen, pdu.getSerializedSize());
+ if (result != OK) {
+ addError(result);
+ return result;
+ }
+ TmTcMessage tmMsg(storeId);
+ result =
+ fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg);
+ if (result != OK) {
+ fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
+ }
+ if (result == MessageQueueIF::FULL) {
+ return TARGET_MSG_QUEUE_FULL;
+ } else if (result == OK) {
+ fsmResult.packetsSent += 1;
+ }
+ return result;
+}
+
+ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() {
+ if (sourceParams.cfg.indicCfg.transactionFinishedIndicRequired) {
+ cfdp::TransactionFinishedParams params(transactionParams.id, ConditionCode::NO_ERROR,
+ FileDeliveryCode::DATA_COMPLETE,
+ FileDeliveryStatus::RETAINED_IN_FILESTORE);
+ sourceParams.user.transactionFinishedIndication(params);
+ }
+ return OK;
+}
+
+ReturnValue_t cfdp::SourceHandler::reset() {
+ step = TransactionStep::IDLE;
+ state = cfdp::CfdpState::IDLE;
+ fsmResult.callStatus = CallStatus::DONE;
+ transactionParams.reset();
+ return OK;
+}
+cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
+
+cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }
+
+void cfdp::SourceHandler::addError(ReturnValue_t error) {
+ if (fsmResult.errors < fsmResult.errorCodes.size()) {
+ fsmResult.errorCodes[fsmResult.errors] = error;
+ fsmResult.errors++;
+ fsmResult.result = error;
+ }
+}
diff --git a/src/fsfw/cfdp/handler/SourceHandler.h b/src/fsfw/cfdp/handler/SourceHandler.h
index 319cf258..d1d3fab2 100644
--- a/src/fsfw/cfdp/handler/SourceHandler.h
+++ b/src/fsfw/cfdp/handler/SourceHandler.h
@@ -1,6 +1,110 @@
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
-class SourceHandler {};
+#include
+#include
+
+#include "UserBase.h"
+#include "defs.h"
+#include "fsfw/cfdp/Fss.h"
+#include "fsfw/cfdp/handler/PutRequest.h"
+#include "fsfw/cfdp/handler/mib.h"
+#include "fsfw/events/EventReportingProxyIF.h"
+#include "fsfw/storagemanager/StorageManagerIF.h"
+#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
+#include "fsfw/util/ProvidesSeqCountIF.h"
+
+namespace cfdp {
+
+struct SourceHandlerParams {
+ SourceHandlerParams(LocalEntityCfg cfg, UserBase& user, ProvidesSeqCountIF& seqCountProvider)
+ : cfg(std::move(cfg)), user(user), seqCountProvider(seqCountProvider) {}
+
+ LocalEntityCfg cfg;
+ UserBase& user;
+ ProvidesSeqCountIF& seqCountProvider;
+};
+
+class SourceHandler {
+ public:
+ enum class TransactionStep : uint8_t {
+ IDLE = 0,
+ TRANSACTION_START = 1,
+ SENDING_METADATA = 3,
+ SENDING_FILE_DATA = 4,
+ SENDING_EOF = 5,
+ WAIT_FOR_ACK = 6,
+ WAIT_FOR_FINISH = 7,
+ NOTICE_OF_COMPLETION = 8
+ };
+ struct FsmResult {
+ public:
+ ReturnValue_t result = returnvalue::OK;
+ CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
+ CfdpState state = CfdpState::IDLE;
+ uint32_t packetsSent = 0;
+ uint8_t errors = 0;
+ std::array errorCodes = {};
+ };
+
+ SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams);
+
+ [[nodiscard]] CfdpState getState() const;
+ [[nodiscard]] TransactionStep getStep() const;
+
+ /**
+ * Pass a put request to the source handler, which might initiate a CFDP transaction and start
+ * the state machine
+ * @return
+ */
+ ReturnValue_t transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg);
+ const FsmResult& stateMachine();
+
+ ReturnValue_t initialize();
+
+ private:
+ struct TransactionParams {
+ uint32_t crc{};
+ std::array sourceName{};
+ size_t sourceNameSize = 0;
+ std::array destName{};
+ size_t destNameSize = 0;
+ cfdp::Fss fileSize;
+ size_t progress = 0;
+ bool closureRequested = false;
+ ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
+ RemoteEntityCfg remoteCfg;
+ PduConfig pduConf;
+ cfdp::TransactionId id{};
+
+ void reset() {
+ sourceNameSize = 0;
+ destNameSize = 0;
+ fileSize.setFileSize(0, false);
+ progress = 0;
+ closureRequested = false;
+ }
+ } transactionParams;
+
+ cfdp::CfdpState state = cfdp::CfdpState::IDLE;
+ TransactionStep step = TransactionStep::IDLE;
+ std::array fileBuf{};
+ SourceHandlerParams sourceParams;
+ cfdp::FsfwParams fsfwParams;
+ FsmResult fsmResult;
+
+ FsmResult& fsmNacked();
+ ReturnValue_t checksumGeneration();
+ ReturnValue_t prepareAndSendMetadataPdu();
+ ReturnValue_t prepareAndSendNextFileDataPdu(bool& noFileDataPdu);
+ ReturnValue_t prepareAndSendEofPdu();
+ ReturnValue_t noticeOfCompletion();
+ ReturnValue_t reset();
+
+ [[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu);
+ void addError(ReturnValue_t error);
+};
+
+} // namespace cfdp
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H
diff --git a/src/fsfw/cfdp/handler/UserBase.h b/src/fsfw/cfdp/handler/UserBase.h
index e367b4a8..6141eea9 100644
--- a/src/fsfw/cfdp/handler/UserBase.h
+++ b/src/fsfw/cfdp/handler/UserBase.h
@@ -6,6 +6,7 @@
#include
#include "StatusReportIF.h"
+#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/VarLenFields.h"
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
@@ -27,14 +28,14 @@ struct TransactionFinishedParams {
};
struct MetadataRecvdParams {
- MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId)
- : id(id), sourceId(sourceId) {}
+ MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId, Fss fileSize)
+ : id(id), sourceId(sourceId), fileSize(std::move(fileSize)) {}
const TransactionId& id;
const EntityId& sourceId;
- uint64_t fileSize = 0;
+ Fss fileSize{};
const char* sourceFileName = "";
const char* destFileName = "";
- size_t msgsToUserLen = 0;
+ size_t numberOfMsgsToUser = 0;
const MessageToUserTlv* msgsToUserArray = nullptr;
};
@@ -65,6 +66,7 @@ struct FileSegmentRecvdParams {
*/
class UserBase {
friend class DestHandler;
+ friend class SourceHandler;
public:
explicit UserBase(HasFileSystemIF& vfs);
diff --git a/src/fsfw/cfdp/handler/defs.h b/src/fsfw/cfdp/handler/defs.h
index 5f17ca2d..4356835d 100644
--- a/src/fsfw/cfdp/handler/defs.h
+++ b/src/fsfw/cfdp/handler/defs.h
@@ -1,11 +1,54 @@
#ifndef FSFW_CFDP_HANDLER_DEFS_H
#define FSFW_CFDP_HANDLER_DEFS_H
+#include
+
+#include "fsfw/storagemanager/StorageManagerIF.h"
+#include "fsfw/storagemanager/storeAddress.h"
+#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
+
namespace cfdp {
-enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
+enum class CfdpState { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP;
+static constexpr uint8_t CID = CLASS_ID::CFDP_HANDLER;
+
+struct PacketInfo {
+ PacketInfo(PduType type, store_address_t storeId,
+ std::optional directive = std::nullopt)
+ : pduType(type), directiveType(directive), storeId(storeId) {}
+
+ PduType pduType = PduType::FILE_DATA;
+ std::optional directiveType = FileDirective::INVALID_DIRECTIVE;
+ store_address_t storeId = store_address_t::invalid();
+ PacketInfo() = default;
+};
+
+struct FsfwParams {
+ FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
+ EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore,
+ StorageManagerIF& tmStore)
+ : FsfwParams(packetDest, msgQueue, eventReporter) {
+ this->tcStore = &tcStore;
+ this->tmStore = &tmStore;
+ }
+
+ FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
+ EventReportingProxyIF* eventReporter)
+ : packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {}
+ AcceptsTelemetryIF& packetDest;
+ MessageQueueIF* msgQueue;
+ EventReportingProxyIF* eventReporter = nullptr;
+ StorageManagerIF* tcStore = nullptr;
+ StorageManagerIF* tmStore = nullptr;
+};
+
+template
+using PacketInfoList = etl::list;
+using PacketInfoListBase = etl::ilist;
+
+enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
namespace events {
@@ -15,8 +58,19 @@ static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity:
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
+//! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode.
+static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent(SSID, 5, severity::LOW);
} // namespace events
+static constexpr ReturnValue_t SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0);
+static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = returnvalue::makeCode(CID, 1);
+static constexpr ReturnValue_t FILE_SEGMENT_LEN_INVALID = returnvalue::makeCode(CID, 2);
+static constexpr ReturnValue_t SOURCE_NAME_EMPTY = returnvalue::makeCode(CID, 3);
+static constexpr ReturnValue_t DEST_NAME_EMPTY = returnvalue::makeCode(CID, 4);
+static constexpr ReturnValue_t WRONG_REMOTE_CFG_ENTITY_ID = returnvalue::makeCode(CID, 5);
+static constexpr ReturnValue_t TARGET_MSG_QUEUE_FULL = returnvalue::makeCode(CID, 6);
+static constexpr ReturnValue_t TM_STORE_FULL = returnvalue::makeCode(CID, 7);
+
} // namespace cfdp
#endif // FSFW_CFDP_HANDLER_DEFS_H
diff --git a/src/fsfw/cfdp/handler/mib.h b/src/fsfw/cfdp/handler/mib.h
index 553596a6..7e4454ef 100644
--- a/src/fsfw/cfdp/handler/mib.h
+++ b/src/fsfw/cfdp/handler/mib.h
@@ -27,14 +27,15 @@ struct LocalEntityCfg {
};
struct RemoteEntityCfg {
+ RemoteEntityCfg() = default;
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
EntityId remoteId;
- size_t maxFileSegmentLen = 2048;
+ size_t maxFileSegmentLen = 1024;
bool closureRequested = false;
bool crcOnTransmission = false;
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
- const uint8_t version = CFDP_VERSION_2;
+ uint8_t version = CFDP_VERSION_2;
};
} // namespace cfdp
diff --git a/src/fsfw/cfdp/pdu/CMakeLists.txt b/src/fsfw/cfdp/pdu/CMakeLists.txt
index c08a4b29..89de7b86 100644
--- a/src/fsfw/cfdp/pdu/CMakeLists.txt
+++ b/src/fsfw/cfdp/pdu/CMakeLists.txt
@@ -17,7 +17,7 @@ target_sources(
FinishedInfo.cpp
FinishedPduCreator.cpp
FinishedPduReader.cpp
- MetadataInfo.cpp
+ MetadataGenericInfo.cpp
MetadataPduCreator.cpp
MetadataPduReader.cpp
KeepAlivePduCreator.cpp
diff --git a/src/fsfw/cfdp/pdu/EofInfo.cpp b/src/fsfw/cfdp/pdu/EofInfo.cpp
index 98e79df7..b226fe7f 100644
--- a/src/fsfw/cfdp/pdu/EofInfo.cpp
+++ b/src/fsfw/cfdp/pdu/EofInfo.cpp
@@ -1,8 +1,13 @@
#include "EofInfo.h"
-EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
+#include
+
+EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
EntityIdTlv* faultLoc)
- : conditionCode(conditionCode), checksum(checksum), fileSize(fileSize), faultLoc(faultLoc) {}
+ : conditionCode(conditionCode),
+ checksum(checksum),
+ fileSize(std::move(fileSize)),
+ faultLoc(faultLoc) {}
EofInfo::EofInfo(EntityIdTlv* faultLoc)
: conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
@@ -16,15 +21,15 @@ cfdp::ConditionCode EofInfo::getConditionCode() const { return conditionCode; }
EntityIdTlv* EofInfo::getFaultLoc() const { return faultLoc; }
-cfdp::FileSize& EofInfo::getFileSize() { return fileSize; }
+cfdp::Fss& EofInfo::getFileSize() { return fileSize; }
-void EofInfo::setChecksum(uint32_t checksum) { this->checksum = checksum; }
+void EofInfo::setChecksum(uint32_t checksum_) { this->checksum = checksum_; }
-void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
- this->conditionCode = conditionCode;
+void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode_) {
+ this->conditionCode = conditionCode_;
}
-void EofInfo::setFaultLoc(EntityIdTlv* faultLoc) { this->faultLoc = faultLoc; }
+void EofInfo::setFaultLoc(EntityIdTlv* faultLoc_) { this->faultLoc = faultLoc_; }
size_t EofInfo::getSerializedSize(bool fssLarge) {
// Condition code + spare + 4 byte checksum
@@ -42,6 +47,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
return size;
}
-ReturnValue_t EofInfo::setFileSize(size_t fileSize, bool isLarge) {
- return this->fileSize.setFileSize(fileSize, isLarge);
+ReturnValue_t EofInfo::setFileSize(size_t fileSize_, bool isLarge) {
+ return this->fileSize.setFileSize(fileSize_, isLarge);
}
diff --git a/src/fsfw/cfdp/pdu/EofInfo.h b/src/fsfw/cfdp/pdu/EofInfo.h
index 4b4fb057..59bfed31 100644
--- a/src/fsfw/cfdp/pdu/EofInfo.h
+++ b/src/fsfw/cfdp/pdu/EofInfo.h
@@ -1,14 +1,14 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
-#include "../FileSize.h"
+#include "../Fss.h"
#include "../definitions.h"
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
struct EofInfo {
public:
explicit EofInfo(EntityIdTlv* faultLoc = nullptr);
- EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
+ EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
EntityIdTlv* faultLoc = nullptr);
size_t getSerializedSize(bool fssLarge = false);
@@ -17,7 +17,7 @@ struct EofInfo {
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
- cfdp::FileSize& getFileSize();
+ cfdp::Fss& getFileSize();
void setChecksum(uint32_t checksum);
void setConditionCode(cfdp::ConditionCode conditionCode);
void setFaultLoc(EntityIdTlv* faultLoc);
@@ -26,7 +26,7 @@ struct EofInfo {
private:
cfdp::ConditionCode conditionCode;
uint32_t checksum;
- cfdp::FileSize fileSize;
+ cfdp::Fss fileSize;
EntityIdTlv* faultLoc = nullptr;
};
diff --git a/src/fsfw/cfdp/pdu/FileDataCreator.cpp b/src/fsfw/cfdp/pdu/FileDataCreator.cpp
index 956752fb..70779a51 100644
--- a/src/fsfw/cfdp/pdu/FileDataCreator.cpp
+++ b/src/fsfw/cfdp/pdu/FileDataCreator.cpp
@@ -37,7 +37,7 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
*buffer += segmentMetadataLen;
*size += segmentMetadataLen;
}
- cfdp::FileSize& offset = info.getOffset();
+ cfdp::Fss& offset = info.getOffset();
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
diff --git a/src/fsfw/cfdp/pdu/FileDataInfo.cpp b/src/fsfw/cfdp/pdu/FileDataInfo.cpp
index 19fc00cd..8248a727 100644
--- a/src/fsfw/cfdp/pdu/FileDataInfo.cpp
+++ b/src/fsfw/cfdp/pdu/FileDataInfo.cpp
@@ -1,9 +1,9 @@
#include "FileDataInfo.h"
-FileDataInfo::FileDataInfo(cfdp::FileSize &offset, const uint8_t *fileData, size_t fileSize)
- : offset(offset), fileData(fileData), fileSize(fileSize) {}
+#include
-FileDataInfo::FileDataInfo(cfdp::FileSize &offset) : offset(offset) {}
+FileDataInfo::FileDataInfo(cfdp::Fss offset, const uint8_t *fileData, size_t fileSize)
+ : offset(std::move(offset)), fileData(fileData), fileSize(fileSize) {}
void FileDataInfo::setSegmentMetadataFlag(bool enable) {
if (enable) {
@@ -71,7 +71,7 @@ const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
return segmentMetadata;
}
-cfdp::FileSize &FileDataInfo::getOffset() { return offset; }
+cfdp::Fss &FileDataInfo::getOffset() { return offset; }
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
this->recContState = recContState;
diff --git a/src/fsfw/cfdp/pdu/FileDataInfo.h b/src/fsfw/cfdp/pdu/FileDataInfo.h
index 36908d8b..b2b975ad 100644
--- a/src/fsfw/cfdp/pdu/FileDataInfo.h
+++ b/src/fsfw/cfdp/pdu/FileDataInfo.h
@@ -1,17 +1,17 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
-#include
+#include
#include
class FileDataInfo {
public:
- explicit FileDataInfo(cfdp::FileSize& offset);
- FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
+ FileDataInfo() = default;
+ FileDataInfo(cfdp::Fss offset, const uint8_t* fileData, size_t fileSize);
[[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
- cfdp::FileSize& getOffset();
+ cfdp::Fss& getOffset();
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
void setFileData(const uint8_t* fileData, size_t fileSize);
@@ -33,7 +33,7 @@ class FileDataInfo {
private:
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
- cfdp::FileSize& offset;
+ cfdp::Fss offset;
const uint8_t* fileData = nullptr;
size_t fileSize = 0;
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;
diff --git a/src/fsfw/cfdp/pdu/HeaderReader.cpp b/src/fsfw/cfdp/pdu/HeaderReader.cpp
index de3d2906..4d853920 100644
--- a/src/fsfw/cfdp/pdu/HeaderReader.cpp
+++ b/src/fsfw/cfdp/pdu/HeaderReader.cpp
@@ -103,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons
}
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
- void *sourcePtr) const {
+ void *sourcePtr) {
switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): {
auto *fieldTyped = static_cast(sourcePtr);
- field->setValue(width, *fieldTyped);
+ field->setValueAndWidth(width, *fieldTyped);
break;
}
case (cfdp::WidthInBytes::TWO_BYTES): {
@@ -115,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
- field->setValue(width, fieldTyped);
+ field->setValueAndWidth(width, fieldTyped);
break;
}
case (cfdp::WidthInBytes::FOUR_BYTES): {
@@ -123,7 +123,15 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
- field->setValue(width, fieldTyped);
+ field->setValueAndWidth(width, fieldTyped);
+ break;
+ }
+ case (cfdp::WidthInBytes::EIGHT_BYTES): {
+ uint64_t fieldTyped = 0;
+ size_t deserSize = 0;
+ SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize,
+ SerializeIF::Endianness::NETWORK);
+ field->setValueAndWidth(width, fieldTyped);
break;
}
}
diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp
index 40747751..2afcd427 100644
--- a/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp
+++ b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp
@@ -1,6 +1,6 @@
#include "KeepAlivePduCreator.h"
-KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress)
+KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::Fss &progress)
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
updateDirectiveFieldLen();
}
diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h
index aa4bf0fd..97ce6095 100644
--- a/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h
+++ b/src/fsfw/cfdp/pdu/KeepAlivePduCreator.h
@@ -1,12 +1,12 @@
#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
-#include "fsfw/cfdp/FileSize.h"
+#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
class KeepAlivePduCreator : public FileDirectiveCreator {
public:
- KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress);
+ KeepAlivePduCreator(PduConfig& conf, cfdp::Fss& progress);
void updateDirectiveFieldLen();
@@ -16,7 +16,7 @@ class KeepAlivePduCreator : public FileDirectiveCreator {
Endianness streamEndianness) const override;
private:
- cfdp::FileSize& progress;
+ cfdp::Fss& progress;
};
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */
diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp b/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp
index d3362cf9..73ddc678 100644
--- a/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp
+++ b/src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp
@@ -1,7 +1,6 @@
#include "KeepAlivePduReader.h"
-KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize,
- cfdp::FileSize& progress)
+KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress)
: FileDirectiveReader(pduBuf, maxSize), progress(progress) {}
ReturnValue_t KeepAlivePduReader::parseData() {
@@ -15,4 +14,4 @@ ReturnValue_t KeepAlivePduReader::parseData() {
return progress.deSerialize(&buffer, &remLen, getEndianness());
}
-cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; }
+cfdp::Fss& KeepAlivePduReader::getProgress() { return progress; }
diff --git a/src/fsfw/cfdp/pdu/KeepAlivePduReader.h b/src/fsfw/cfdp/pdu/KeepAlivePduReader.h
index 38e061f1..553101c9 100644
--- a/src/fsfw/cfdp/pdu/KeepAlivePduReader.h
+++ b/src/fsfw/cfdp/pdu/KeepAlivePduReader.h
@@ -1,19 +1,19 @@
#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_
#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_
-#include "fsfw/cfdp/FileSize.h"
+#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
class KeepAlivePduReader : public FileDirectiveReader {
public:
- KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress);
+ KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress);
ReturnValue_t parseData() override;
- cfdp::FileSize& getProgress();
+ cfdp::Fss& getProgress();
private:
- cfdp::FileSize& progress;
+ cfdp::Fss& progress;
};
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */
diff --git a/src/fsfw/cfdp/pdu/MetadataGenericInfo.cpp b/src/fsfw/cfdp/pdu/MetadataGenericInfo.cpp
new file mode 100644
index 00000000..f3b1c751
--- /dev/null
+++ b/src/fsfw/cfdp/pdu/MetadataGenericInfo.cpp
@@ -0,0 +1,35 @@
+#include "MetadataGenericInfo.h"
+
+MetadataGenericInfo::MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType,
+ cfdp::Fss fileSize)
+ : MetadataGenericInfo(std::move(fileSize)) {
+ this->closureRequested = closureRequested;
+ this->checksumType = checksumType;
+}
+
+MetadataGenericInfo::MetadataGenericInfo(cfdp::Fss fileSize) : fileSize(std::move(fileSize)) {}
+
+cfdp::ChecksumType MetadataGenericInfo::getChecksumType() const { return checksumType; }
+
+void MetadataGenericInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
+ checksumType = checksumType_;
+}
+
+bool MetadataGenericInfo::isClosureRequested() const { return closureRequested; }
+
+void MetadataGenericInfo::setClosureRequested(bool closureRequested_) {
+ closureRequested = closureRequested_;
+}
+
+const cfdp::Fss& MetadataGenericInfo::getFileSize() const { return fileSize; }
+
+size_t MetadataGenericInfo::getSerializedSize(bool fssLarge) {
+ // 1 byte + minimal FSS 4 bytes
+ size_t size = 5;
+ if (fssLarge) {
+ size += 4;
+ }
+ return size;
+}
+
+cfdp::Fss& MetadataGenericInfo::getMutFileSize() { return fileSize; }
diff --git a/src/fsfw/cfdp/pdu/MetadataGenericInfo.h b/src/fsfw/cfdp/pdu/MetadataGenericInfo.h
new file mode 100644
index 00000000..73a54972
--- /dev/null
+++ b/src/fsfw/cfdp/pdu/MetadataGenericInfo.h
@@ -0,0 +1,35 @@
+#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
+#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
+
+#include
+
+#include "fsfw/cfdp/Fss.h"
+#include "fsfw/cfdp/definitions.h"
+#include "fsfw/cfdp/tlv/Lv.h"
+#include "fsfw/cfdp/tlv/StringLv.h"
+#include "fsfw/cfdp/tlv/Tlv.h"
+
+class MetadataGenericInfo {
+ public:
+ MetadataGenericInfo() = default;
+ explicit MetadataGenericInfo(cfdp::Fss fileSize);
+ MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::Fss fileSize);
+
+ static size_t getSerializedSize(bool fssLarge = false);
+
+ [[nodiscard]] cfdp::ChecksumType getChecksumType() const;
+ void setChecksumType(cfdp::ChecksumType checksumType);
+ [[nodiscard]] bool isClosureRequested() const;
+ void setClosureRequested(bool closureRequested = false);
+
+ [[nodiscard]] const cfdp::Fss& getFileSize() const;
+
+ cfdp::Fss& getMutFileSize();
+
+ private:
+ bool closureRequested = false;
+ cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
+ cfdp::Fss fileSize;
+};
+
+#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */
diff --git a/src/fsfw/cfdp/pdu/MetadataInfo.cpp b/src/fsfw/cfdp/pdu/MetadataInfo.cpp
deleted file mode 100644
index d88bdd87..00000000
--- a/src/fsfw/cfdp/pdu/MetadataInfo.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include "MetadataInfo.h"
-
-MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType,
- cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
- cfdp::StringLv& destFileName)
- : MetadataInfo(fileSize, sourceFileName, destFileName) {
- this->closureRequested = closureRequested;
- this->checksumType = checksumType;
-}
-
-MetadataInfo::MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
- cfdp::StringLv& destFileName)
- : fileSize(fileSize), sourceFileName(sourceFileName), destFileName(destFileName) {}
-
-void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray_, std::optional optionsLen_,
- std::optional maxOptionsLen_) {
- this->optionsArray = optionsArray_;
- if (maxOptionsLen_) {
- this->maxOptionsLen = maxOptionsLen_.value();
- }
- if (optionsLen_) {
- this->optionsLen = optionsLen_.value();
- }
-}
-
-cfdp::ChecksumType MetadataInfo::getChecksumType() const { return checksumType; }
-
-void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
- checksumType = checksumType_;
-}
-
-bool MetadataInfo::isClosureRequested() const { return closureRequested; }
-
-void MetadataInfo::setClosureRequested(bool closureRequested_) {
- closureRequested = closureRequested_;
-}
-
-cfdp::StringLv& MetadataInfo::getDestFileName() { return destFileName; }
-
-cfdp::FileSize& MetadataInfo::getFileSize() { return fileSize; }
-
-ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray_, size_t* optionsLen_,
- size_t* maxOptsLen) {
- if (optionsArray_ == nullptr or optionsArray == nullptr) {
- return returnvalue::FAILED;
- }
- *optionsArray_ = optionsArray;
- if (optionsLen_ != nullptr) {
- *optionsLen_ = this->optionsLen;
- }
- if (maxOptsLen != nullptr) {
- *maxOptsLen = this->maxOptionsLen;
- }
- return returnvalue::OK;
-}
-
-bool MetadataInfo::hasOptions() const {
- if (optionsArray != nullptr and optionsLen > 0) {
- return true;
- }
- return false;
-}
-
-bool MetadataInfo::canHoldOptions() const {
- if (optionsArray != nullptr and maxOptionsLen > 0) {
- return true;
- }
- return false;
-}
-
-size_t MetadataInfo::getSerializedSize(bool fssLarge) {
- // 1 byte + minimal FSS 4 bytes
- size_t size = 5;
- if (fssLarge) {
- size += 4;
- }
- size += sourceFileName.getSerializedSize();
- size += destFileName.getSerializedSize();
- if (hasOptions()) {
- for (size_t idx = 0; idx < optionsLen; idx++) {
- size += optionsArray[idx]->getSerializedSize();
- }
- }
- return size;
-}
-
-void MetadataInfo::setDestFileName(cfdp::StringLv& destFileName_) {
- this->destFileName = destFileName_;
-}
-
-void MetadataInfo::setSourceFileName(cfdp::StringLv& sourceFileName_) {
- this->sourceFileName = sourceFileName_;
-}
-
-size_t MetadataInfo::getMaxOptionsLen() const { return maxOptionsLen; }
-
-void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen_) { this->maxOptionsLen = maxOptionsLen_; }
-
-size_t MetadataInfo::getOptionsLen() const { return optionsLen; }
-
-void MetadataInfo::setOptionsLen(size_t optionsLen_) { this->optionsLen = optionsLen_; }
-
-cfdp::StringLv& MetadataInfo::getSourceFileName() { return sourceFileName; }
diff --git a/src/fsfw/cfdp/pdu/MetadataInfo.h b/src/fsfw/cfdp/pdu/MetadataInfo.h
deleted file mode 100644
index 95f4544a..00000000
--- a/src/fsfw/cfdp/pdu/MetadataInfo.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
-#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
-
-#include
-
-#include "fsfw/cfdp/FileSize.h"
-#include "fsfw/cfdp/definitions.h"
-#include "fsfw/cfdp/tlv/Lv.h"
-#include "fsfw/cfdp/tlv/StringLv.h"
-#include "fsfw/cfdp/tlv/Tlv.h"
-
-class MetadataInfo {
- public:
- MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
- cfdp::StringLv& destFileName);
- MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::FileSize& fileSize,
- cfdp::StringLv& sourceFileName, cfdp::StringLv& destFileName);
-
- size_t getSerializedSize(bool fssLarge = false);
-
- void setOptionsArray(cfdp::Tlv** optionsArray, std::optional optionsLen,
- std::optional maxOptionsLen);
- [[nodiscard]] cfdp::ChecksumType getChecksumType() const;
- void setChecksumType(cfdp::ChecksumType checksumType);
- [[nodiscard]] bool isClosureRequested() const;
- void setClosureRequested(bool closureRequested = false);
-
- void setDestFileName(cfdp::StringLv& destFileName);
- void setSourceFileName(cfdp::StringLv& sourceFileName);
-
- cfdp::StringLv& getDestFileName();
- cfdp::StringLv& getSourceFileName();
- cfdp::FileSize& getFileSize();
-
- [[nodiscard]] bool hasOptions() const;
- [[nodiscard]] bool canHoldOptions() const;
- ReturnValue_t getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, size_t* maxOptsLen);
- void setOptionsLen(size_t optionsLen);
- [[nodiscard]] size_t getOptionsLen() const;
- void setMaxOptionsLen(size_t maxOptionsLen);
- [[nodiscard]] size_t getMaxOptionsLen() const;
-
- private:
- bool closureRequested = false;
- cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
- cfdp::FileSize& fileSize;
- cfdp::StringLv& sourceFileName;
- cfdp::StringLv& destFileName;
-
- cfdp::Tlv** optionsArray = nullptr;
- size_t optionsLen = 0;
- size_t maxOptionsLen = 0;
-};
-
-#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */
diff --git a/src/fsfw/cfdp/pdu/MetadataPduCreator.cpp b/src/fsfw/cfdp/pdu/MetadataPduCreator.cpp
index 536a48f4..9f8633cb 100644
--- a/src/fsfw/cfdp/pdu/MetadataPduCreator.cpp
+++ b/src/fsfw/cfdp/pdu/MetadataPduCreator.cpp
@@ -1,12 +1,26 @@
#include "MetadataPduCreator.h"
-MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info)
- : FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) {
+MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataGenericInfo &info,
+ cfdp::StringLv &srcFileName, cfdp::StringLv &destFileName,
+ cfdp::Tlv **optionsArray, size_t optionsLen)
+ : FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5),
+ info(info),
+ srcFileName(srcFileName),
+ destFileName(destFileName),
+ optionsArray(optionsArray),
+ optionsLen(optionsLen) {
updateDirectiveFieldLen();
}
void MetadataPduCreator::updateDirectiveFieldLen() {
- setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
+ size_t dirFieldLen = MetadataGenericInfo::getSerializedSize(HeaderCreator::getLargeFileFlag()) +
+ srcFileName.getSerializedSize() + destFileName.getSerializedSize();
+ if (optionsLen > 0 and optionsArray != nullptr) {
+ for (size_t idx = 0; idx < optionsLen; idx++) {
+ dirFieldLen += optionsArray[idx]->getSerializedSize();
+ }
+ }
+ setDirectiveDataFieldLen(dirFieldLen);
}
size_t MetadataPduCreator::getSerializedSize() const {
@@ -29,21 +43,18 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
if (result != returnvalue::OK) {
return result;
}
- result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness);
+ result = srcFileName.serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
- result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness);
+ result = destFileName.serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
- if (info.hasOptions()) {
- cfdp::Tlv **optsArray = nullptr;
- size_t optsLen = 0;
- info.getOptions(&optsArray, &optsLen, nullptr);
- for (size_t idx = 0; idx < optsLen; idx++) {
- result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
+ if (optionsLen > 0 and optionsArray != nullptr) {
+ for (size_t idx = 0; idx < optionsLen; idx++) {
+ result = optionsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
@@ -51,3 +62,5 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
}
return result;
}
+const cfdp::StringLv &MetadataPduCreator::getSourceFileName() const { return srcFileName; }
+const cfdp::StringLv &MetadataPduCreator::getDestFileName() const { return destFileName; }
diff --git a/src/fsfw/cfdp/pdu/MetadataPduCreator.h b/src/fsfw/cfdp/pdu/MetadataPduCreator.h
index 4486a79c..e1c931e5 100644
--- a/src/fsfw/cfdp/pdu/MetadataPduCreator.h
+++ b/src/fsfw/cfdp/pdu/MetadataPduCreator.h
@@ -2,22 +2,30 @@
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
-#include "fsfw/cfdp/pdu/MetadataInfo.h"
+#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
class MetadataPduCreator : public FileDirectiveCreator {
public:
- MetadataPduCreator(PduConfig& conf, MetadataInfo& info);
+ MetadataPduCreator(PduConfig& conf, MetadataGenericInfo& info, cfdp::StringLv& srcFileName,
+ cfdp::StringLv& destFileName, cfdp::Tlv** optionsArray, size_t optionsLen);
void updateDirectiveFieldLen();
[[nodiscard]] size_t getSerializedSize() const override;
+ const cfdp::StringLv& getSourceFileName() const;
+ const cfdp::StringLv& getDestFileName() const;
+
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
using FileDirectiveCreator::serialize;
private:
- MetadataInfo& info;
+ MetadataGenericInfo& info;
+ cfdp::StringLv& srcFileName;
+ cfdp::StringLv& destFileName;
+ cfdp::Tlv** optionsArray;
+ size_t optionsLen;
};
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */
diff --git a/src/fsfw/cfdp/pdu/MetadataPduReader.cpp b/src/fsfw/cfdp/pdu/MetadataPduReader.cpp
index 66025140..e6160ce8 100644
--- a/src/fsfw/cfdp/pdu/MetadataPduReader.cpp
+++ b/src/fsfw/cfdp/pdu/MetadataPduReader.cpp
@@ -1,9 +1,15 @@
#include "MetadataPduReader.h"
-MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info)
- : FileDirectiveReader(pduBuf, maxSize), info(info) {}
+MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize,
+ MetadataGenericInfo& info, cfdp::Tlv* optionsArray,
+ size_t optArrayMaxSize)
+ : FileDirectiveReader(pduBuf, maxSize),
+ info(info),
+ optionArray(optionsArray),
+ optionArrayMaxSize(optArrayMaxSize) {}
ReturnValue_t MetadataPduReader::parseData() {
+ parsedOptions = 0;
ReturnValue_t result = FileDirectiveReader::parseData();
if (result != returnvalue::OK) {
return result;
@@ -19,39 +25,43 @@ ReturnValue_t MetadataPduReader::parseData() {
remSize -= 1;
buf += 1;
auto endianness = getEndianness();
- result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
+ result = info.getMutFileSize().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
- result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness);
+ result = srcFileName.deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
- result = info.getDestFileName().deSerialize(&buf, &remSize, endianness);
+ result = destFileName.deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
- info.setOptionsLen(0);
if (remSize > 0) {
- if (not info.canHoldOptions()) {
+ if (optionArrayMaxSize == 0 or optionArray == nullptr) {
return cfdp::METADATA_CANT_PARSE_OPTIONS;
}
- cfdp::Tlv** optionsArray = nullptr;
- size_t optsMaxLen = 0;
size_t optsIdx = 0;
- info.getOptions(&optionsArray, nullptr, &optsMaxLen);
while (remSize > 0) {
- if (optsIdx > optsMaxLen) {
+ if (optsIdx > optionArrayMaxSize) {
return cfdp::METADATA_CANT_PARSE_OPTIONS;
}
- result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness);
+ result = optionArray[optsIdx].deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) {
return result;
}
optsIdx++;
}
- info.setOptionsLen(optsIdx);
+ parsedOptions = optsIdx;
}
return result;
}
+
+size_t MetadataPduReader::getNumberOfParsedOptions() const { return parsedOptions; }
+
+const cfdp::StringLv& MetadataPduReader::getSourceFileName() const { return srcFileName; }
+
+const cfdp::StringLv& MetadataPduReader::getDestFileName() const { return destFileName; }
+
+const MetadataGenericInfo& MetadataPduReader::getGenericInfo() const { return info; }
diff --git a/src/fsfw/cfdp/pdu/MetadataPduReader.h b/src/fsfw/cfdp/pdu/MetadataPduReader.h
index 3e8c0f30..a409928e 100644
--- a/src/fsfw/cfdp/pdu/MetadataPduReader.h
+++ b/src/fsfw/cfdp/pdu/MetadataPduReader.h
@@ -2,16 +2,28 @@
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
-#include "fsfw/cfdp/pdu/MetadataInfo.h"
+#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
class MetadataPduReader : public FileDirectiveReader {
public:
- MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
+ MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataGenericInfo& info,
+ cfdp::Tlv* optionsArray, size_t optArrayMaxSize);
ReturnValue_t parseData() override;
+ [[nodiscard]] const MetadataGenericInfo& getGenericInfo() const;
+ [[nodiscard]] const cfdp::StringLv& getSourceFileName() const;
+ [[nodiscard]] const cfdp::StringLv& getDestFileName() const;
+
+ [[nodiscard]] size_t getNumberOfParsedOptions() const;
+
private:
- MetadataInfo& info;
+ cfdp::StringLv srcFileName;
+ cfdp::StringLv destFileName;
+ MetadataGenericInfo& info;
+ cfdp::Tlv* optionArray;
+ size_t optionArrayMaxSize;
+ size_t parsedOptions = 0;
};
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */
diff --git a/src/fsfw/cfdp/pdu/NakInfo.cpp b/src/fsfw/cfdp/pdu/NakInfo.cpp
index 14d06cb0..8ae317f4 100644
--- a/src/fsfw/cfdp/pdu/NakInfo.cpp
+++ b/src/fsfw/cfdp/pdu/NakInfo.cpp
@@ -1,6 +1,6 @@
#include "NakInfo.h"
-NakInfo::NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope)
+NakInfo::NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope)
: startOfScope(startOfScope), endOfScope(endOfScope) {}
size_t NakInfo::getSerializedSize(bool fssLarge) {
@@ -57,9 +57,9 @@ void NakInfo::setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmen
}
}
-cfdp::FileSize& NakInfo::getStartOfScope() { return startOfScope; }
+cfdp::Fss& NakInfo::getStartOfScope() { return startOfScope; }
-cfdp::FileSize& NakInfo::getEndOfScope() { return endOfScope; }
+cfdp::Fss& NakInfo::getEndOfScope() { return endOfScope; }
size_t NakInfo::getSegmentRequestsLen() const { return segmentRequestsLen; }
diff --git a/src/fsfw/cfdp/pdu/NakInfo.h b/src/fsfw/cfdp/pdu/NakInfo.h
index 02d6b6f4..f8f6b147 100644
--- a/src/fsfw/cfdp/pdu/NakInfo.h
+++ b/src/fsfw/cfdp/pdu/NakInfo.h
@@ -3,21 +3,21 @@
#include
-#include "fsfw/cfdp/FileSize.h"
+#include "fsfw/cfdp/Fss.h"
class NakInfo {
public:
- using SegmentRequest = std::pair;
+ using SegmentRequest = std::pair;
- NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope);
+ NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope);
void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen,
size_t* maxSegmentRequestLen);
size_t getSerializedSize(bool fssLarge = false);
- cfdp::FileSize& getStartOfScope();
- cfdp::FileSize& getEndOfScope();
+ cfdp::Fss& getStartOfScope();
+ cfdp::Fss& getEndOfScope();
bool hasSegmentRequests() const;
bool canHoldSegmentRequests() const;
@@ -31,8 +31,8 @@ class NakInfo {
void setSegmentRequestLen(size_t readLen);
private:
- cfdp::FileSize startOfScope;
- cfdp::FileSize endOfScope;
+ cfdp::Fss startOfScope;
+ cfdp::Fss endOfScope;
SegmentRequest* segmentRequests = nullptr;
size_t segmentRequestsLen = 0;
size_t maxSegmentRequestsLen = 0;
diff --git a/src/fsfw/cfdp/pdu/NakPduCreator.h b/src/fsfw/cfdp/pdu/NakPduCreator.h
index bfcff78d..601078fc 100644
--- a/src/fsfw/cfdp/pdu/NakPduCreator.h
+++ b/src/fsfw/cfdp/pdu/NakPduCreator.h
@@ -4,7 +4,7 @@
#include
#include "NakInfo.h"
-#include "fsfw/cfdp/FileSize.h"
+#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
diff --git a/src/fsfw/cfdp/pdu/PduHeaderReader.h b/src/fsfw/cfdp/pdu/PduHeaderReader.h
index a2e122cd..d910e0e3 100644
--- a/src/fsfw/cfdp/pdu/PduHeaderReader.h
+++ b/src/fsfw/cfdp/pdu/PduHeaderReader.h
@@ -105,7 +105,8 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
* @return
*/
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
- void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const;
+ static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
+ void* sourcePtr);
void* sourceIdRaw = nullptr;
void* seqNumRaw = nullptr;
void* destIdRaw = nullptr;
diff --git a/src/fsfw/cfdp/tlv/CMakeLists.txt b/src/fsfw/cfdp/tlv/CMakeLists.txt
index 617b1b0f..09adf941 100644
--- a/src/fsfw/cfdp/tlv/CMakeLists.txt
+++ b/src/fsfw/cfdp/tlv/CMakeLists.txt
@@ -8,4 +8,5 @@ target_sources(
StringLv.cpp
FlowLabelTlv.cpp
MessageToUserTlv.cpp
- FaultHandlerOverrideTlv.cpp)
+ FaultHandlerOverrideTlv.cpp
+ ReservedMessageCreator.cpp)
diff --git a/src/fsfw/cfdp/tlv/Lv.cpp b/src/fsfw/cfdp/tlv/Lv.cpp
index e7fa414a..0972d973 100644
--- a/src/fsfw/cfdp/tlv/Lv.cpp
+++ b/src/fsfw/cfdp/tlv/Lv.cpp
@@ -14,23 +14,6 @@ cfdp::Lv::Lv(const std::vector& data) : value(data.data(), data.size(),
cfdp::Lv::Lv() : value(static_cast(nullptr), 0, true) {}
-cfdp::Lv::Lv(const Lv& other)
- : value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
- if (other.value.getSerializedSize() - 1 > 0) {
- zeroLen = false;
- }
-}
-
-cfdp::Lv& cfdp::Lv::operator=(const Lv& other) {
- size_t otherSize = 0;
- auto* otherVal = const_cast(other.getValue(&otherSize));
- if (otherVal == nullptr or otherSize == 0) {
- this->zeroLen = true;
- }
- this->value.setConstBuffer(otherVal, otherSize);
- return *this;
-}
-
ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
if (maxSize < 1) {
@@ -49,10 +32,8 @@ ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize
}
size_t cfdp::Lv::getSerializedSize() const {
- if (zeroLen) {
+ if (zeroLen or value.getConstBuffer() == nullptr) {
return 1;
- } else if (value.getConstBuffer() == nullptr) {
- return 0;
}
return value.getSerializedSize();
}
@@ -85,7 +66,34 @@ ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size,
const uint8_t* cfdp::Lv::getValue(size_t* size) const {
if (size != nullptr) {
// Length without length field
- *size = value.getSerializedSize() - 1;
+ *size = getSerializedSize() - 1;
}
return value.getConstBuffer();
}
+cfdp::Lv::Lv(cfdp::Lv&& other) noexcept
+ : value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
+ if (other.value.getSerializedSize() - 1 > 0) {
+ zeroLen = false;
+ }
+ // Leave other class in intact state.
+ other.zeroLen = false;
+ other.value = SerialBufferAdapter();
+}
+
+cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
+ size_t otherSize = 0;
+ this->zeroLen = false;
+ auto* otherVal = const_cast(other.getValue(&otherSize));
+ if (otherVal == nullptr or otherSize == 0) {
+ this->zeroLen = true;
+ }
+ this->value.setConstBuffer(otherVal, otherSize);
+ // Leave other class in intact state.
+ other.zeroLen = false;
+ other.value = SerialBufferAdapter();
+ return *this;
+}
+
+size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }
+
+bool cfdp::Lv::isEmpty() const { return zeroLen; }
diff --git a/src/fsfw/cfdp/tlv/Lv.h b/src/fsfw/cfdp/tlv/Lv.h
index efabfdef..ee8e18c6 100644
--- a/src/fsfw/cfdp/tlv/Lv.h
+++ b/src/fsfw/cfdp/tlv/Lv.h
@@ -18,8 +18,12 @@ class Lv : public SerializeIF {
Lv(const uint8_t* value, size_t size);
Lv();
- Lv(const Lv&);
- Lv& operator=(const Lv&);
+ // Semantically, this class is a zero-copy helper, so the copy ctor and copy assigment do not
+ // really make sense here.
+ Lv(const Lv&) = delete;
+ Lv& operator=(const Lv&) = delete;
+ Lv(Lv&&) noexcept;
+ Lv& operator=(Lv&&) noexcept;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
@@ -36,6 +40,8 @@ class Lv : public SerializeIF {
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
+ size_t getValueLen() const;
+
/**
* Get value field and its size.
* @param size Optionally retrieve size. Size will be the size of the actual value field
@@ -44,6 +50,8 @@ class Lv : public SerializeIF {
*/
const uint8_t* getValue(size_t* size) const;
+ bool isEmpty() const;
+
private:
bool zeroLen = true;
SerialBufferAdapter value;
diff --git a/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp b/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp
index 9a3e55ff..714379b6 100644
--- a/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp
+++ b/src/fsfw/cfdp/tlv/MessageToUserTlv.cpp
@@ -7,3 +7,22 @@ MessageToUserTlv::MessageToUserTlv() : Tlv() {}
MessageToUserTlv::MessageToUserTlv(const std::vector& data)
: Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {}
+
+MessageToUserTlv::MessageToUserTlv(const uint8_t* value, size_t size)
+ : Tlv(cfdp::TlvType::MSG_TO_USER, value, size) {}
+
+bool MessageToUserTlv::isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
+ size_t& msgLen) const {
+ if (cfdp::Tlv::getLengthField() < 5) {
+ return false;
+ }
+ if (std::strncmp(reinterpret_cast(getValue()), "cfdp", 4) == 0) {
+ messageType = getValue()[4];
+ if (msgDataStart != nullptr) {
+ *msgDataStart = getValue() + 5;
+ }
+ msgLen = cfdp::Tlv::getSerializedSize() - 5;
+ return true;
+ }
+ return false;
+}
diff --git a/src/fsfw/cfdp/tlv/MessageToUserTlv.h b/src/fsfw/cfdp/tlv/MessageToUserTlv.h
index e7f63ed2..7018a386 100644
--- a/src/fsfw/cfdp/tlv/MessageToUserTlv.h
+++ b/src/fsfw/cfdp/tlv/MessageToUserTlv.h
@@ -9,8 +9,12 @@ class MessageToUserTlv : public cfdp::Tlv {
public:
MessageToUserTlv();
MessageToUserTlv(uint8_t* value, size_t size);
+ MessageToUserTlv(const uint8_t* value, size_t size);
explicit MessageToUserTlv(const std::vector& data);
+ bool isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
+ size_t& msgLen) const;
+
private:
};
diff --git a/src/fsfw/cfdp/tlv/ReservedMessageCreator.cpp b/src/fsfw/cfdp/tlv/ReservedMessageCreator.cpp
new file mode 100644
index 00000000..d37338ed
--- /dev/null
+++ b/src/fsfw/cfdp/tlv/ReservedMessageCreator.cpp
@@ -0,0 +1,39 @@
+#include "ReservedMessageCreator.h"
+
+cfdp::ReservedMessageCreator::ReservedMessageCreator(uint8_t messageType, uint8_t *msgData,
+ size_t msgLen)
+ : messageType(messageType), msgData(msgData), msgSize(msgLen) {}
+
+ReturnValue_t cfdp::ReservedMessageCreator::serialize(
+ uint8_t **buffer, size_t *size, size_t maxSize,
+ SerializeIF::Endianness streamEndianness) const {
+ if (*size + getSerializedSize() > maxSize) {
+ return SerializeIF::BUFFER_TOO_SHORT;
+ }
+ **buffer = TlvType::MSG_TO_USER;
+ *buffer += 1;
+ *size += 1;
+ **buffer = getSerializedSize() - 2;
+ *size += 1;
+ *buffer += 1;
+ std::memcpy(*buffer, MSG_HEADER, 4);
+ *buffer += 4;
+ *size += 4;
+ **buffer = messageType;
+ *buffer += 1;
+ *size += 1;
+ std::memcpy(*buffer, msgData, msgSize);
+ *buffer += msgSize;
+ *size += msgSize;
+ return returnvalue::OK;
+}
+
+size_t cfdp::ReservedMessageCreator::getSerializedSize() const {
+ // 2 bytes type and length, 4 bytes CFDP, 1 byte reserved message type, message data.
+ return 2 + 5 + msgSize;
+}
+
+ReturnValue_t cfdp::ReservedMessageCreator::deSerialize(const uint8_t **buffer, size_t *size,
+ SerializeIF::Endianness streamEndianness) {
+ return returnvalue::FAILED;
+}
diff --git a/src/fsfw/cfdp/tlv/ReservedMessageCreator.h b/src/fsfw/cfdp/tlv/ReservedMessageCreator.h
new file mode 100644
index 00000000..363791c8
--- /dev/null
+++ b/src/fsfw/cfdp/tlv/ReservedMessageCreator.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "Tlv.h"
+
+namespace cfdp {
+
+class ReservedMessageCreator : public SerializeIF {
+ public:
+ static constexpr char MSG_HEADER[] = "cfdp";
+
+ ReservedMessageCreator(uint8_t messageType, uint8_t *msgData, size_t msgLen);
+ [[nodiscard]] ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
+ Endianness streamEndianness) const override;
+ [[nodiscard]] size_t getSerializedSize() const override;
+ ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
+ Endianness streamEndianness) override;
+
+ private:
+ uint8_t messageType;
+ uint8_t *msgData;
+ size_t msgSize;
+};
+
+} // namespace cfdp
diff --git a/src/fsfw/cfdp/tlv/StringLv.cpp b/src/fsfw/cfdp/tlv/StringLv.cpp
index 60c278a7..ce290460 100644
--- a/src/fsfw/cfdp/tlv/StringLv.cpp
+++ b/src/fsfw/cfdp/tlv/StringLv.cpp
@@ -7,3 +7,12 @@ cfdp::StringLv::StringLv(const char* filename, size_t len)
: Lv(reinterpret_cast(filename), len) {}
cfdp::StringLv::StringLv() : Lv() {}
+
+const char* cfdp::StringLv::getCString(size_t& fileSize) const {
+ return reinterpret_cast(getValue(&fileSize));
+}
+
+std::string cfdp::StringLv::getString() const {
+ size_t fileSize;
+ return {getCString(fileSize), fileSize};
+}
diff --git a/src/fsfw/cfdp/tlv/StringLv.h b/src/fsfw/cfdp/tlv/StringLv.h
index 6c200b8b..3a1dba36 100644
--- a/src/fsfw/cfdp/tlv/StringLv.h
+++ b/src/fsfw/cfdp/tlv/StringLv.h
@@ -13,6 +13,8 @@ class StringLv : public Lv {
explicit StringLv(const std::string& fileName);
explicit StringLv(const char* filename, size_t len);
+ const char* getCString(size_t& fileSize) const;
+ std::string getString() const;
// Delete the move constructor to avoid passing in a temporary
StringLv(const std::string&&) = delete;
};
diff --git a/src/fsfw/cfdp/tlv/Tlv.cpp b/src/fsfw/cfdp/tlv/Tlv.cpp
index c3fce612..39635e53 100644
--- a/src/fsfw/cfdp/tlv/Tlv.cpp
+++ b/src/fsfw/cfdp/tlv/Tlv.cpp
@@ -54,6 +54,7 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
return STREAM_TOO_SHORT;
}
+ rawData = *buffer;
uint8_t rawType = **buffer;
if (not checkType(rawType)) {
return INVALID_TLV_TYPE;
@@ -102,3 +103,5 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }
void cfdp::Tlv::setType(TlvType type) { this->type = type; }
+
+const uint8_t *cfdp::Tlv::getRawData() const { return rawData; }
diff --git a/src/fsfw/cfdp/tlv/Tlv.h b/src/fsfw/cfdp/tlv/Tlv.h
index 786a3b79..deea12c3 100644
--- a/src/fsfw/cfdp/tlv/Tlv.h
+++ b/src/fsfw/cfdp/tlv/Tlv.h
@@ -47,6 +47,7 @@ class Tlv : public TlvIF {
void setValue(uint8_t *value, size_t len);
[[nodiscard]] const uint8_t *getValue() const;
+ [[nodiscard]] const uint8_t *getRawData() const;
void setType(TlvType type);
[[nodiscard]] TlvType getType() const override;
[[nodiscard]] uint8_t getLengthField() const override;
@@ -55,6 +56,7 @@ class Tlv : public TlvIF {
bool checkType(uint8_t rawType);
bool zeroLen = true;
+ const uint8_t *rawData = nullptr;
TlvType type = TlvType::INVALID_TLV;
SerialBufferAdapter value;
};
diff --git a/src/fsfw/controller/ControllerBase.cpp b/src/fsfw/controller/ControllerBase.cpp
index b51f86a3..4536819e 100644
--- a/src/fsfw/controller/ControllerBase.cpp
+++ b/src/fsfw/controller/ControllerBase.cpp
@@ -72,18 +72,17 @@ void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
*submode_ = this->submode;
}
-void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
-
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
+void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
+
+void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
+
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue();
performControlOperation(opCode);
return returnvalue::OK;
}
-
-void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
-
ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) {
case HEALTHY:
diff --git a/src/fsfw/coordinates/Sgp4Propagator.cpp b/src/fsfw/coordinates/Sgp4Propagator.cpp
index 62c2670e..352e06db 100644
--- a/src/fsfw/coordinates/Sgp4Propagator.cpp
+++ b/src/fsfw/coordinates/Sgp4Propagator.cpp
@@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
timeval timeSinceEpoch = time - epoch;
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
- double monthsSinceEpoch = minutesSinceEpoch / 60 / 24 / 30;
+ double daysSinceEpoch = minutesSinceEpoch / 60 / 24;
- if ((monthsSinceEpoch > 1) || (monthsSinceEpoch < -1)) {
+ if ((daysSinceEpoch > 7) || (daysSinceEpoch < -7)) {
return TLE_TOO_OLD;
}
diff --git a/src/fsfw/devicehandlers/CMakeLists.txt b/src/fsfw/devicehandlers/CMakeLists.txt
index 180a89da..77254bdd 100644
--- a/src/fsfw/devicehandlers/CMakeLists.txt
+++ b/src/fsfw/devicehandlers/CMakeLists.txt
@@ -7,4 +7,5 @@ target_sources(
DeviceHandlerFailureIsolation.cpp
DeviceHandlerMessage.cpp
DeviceTmReportingWrapper.cpp
+ FreshDeviceHandlerBase.cpp
HealthDevice.cpp)
diff --git a/src/fsfw/devicehandlers/DeviceHandlerIF.h b/src/fsfw/devicehandlers/DeviceHandlerIF.h
index 5e1fdd2f..acdb561c 100644
--- a/src/fsfw/devicehandlers/DeviceHandlerIF.h
+++ b/src/fsfw/devicehandlers/DeviceHandlerIF.h
@@ -85,6 +85,7 @@ class DeviceHandlerIF {
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8);
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
+ static const ReturnValue_t NON_OP_STATE_OF_CHARGE = MAKE_RETURN_CODE(0xAB);
// Standard codes used in scanForReply
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
diff --git a/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp
new file mode 100644
index 00000000..2b4ab27b
--- /dev/null
+++ b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp
@@ -0,0 +1,201 @@
+#include "FreshDeviceHandlerBase.h"
+
+#include "fsfw/devicehandlers/DeviceHandlerFailureIsolation.h"
+#include "fsfw/ipc/QueueFactory.h"
+#include "fsfw/subsystem/helper.h"
+
+FreshDeviceHandlerBase::FreshDeviceHandlerBase(DhbConfig config)
+ : SystemObject(config.objectId),
+ actionHelper(this, nullptr),
+ modeHelper(this),
+ healthHelper(this, getObjectId()),
+ paramHelper(this),
+ poolManager(this, nullptr),
+ defaultFdirParent(config.defaultFdirParent) {
+ auto mqArgs = MqArgs(config.objectId, static_cast(this));
+ messageQueue = QueueFactory::instance()->createMessageQueue(
+ config.msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
+}
+FreshDeviceHandlerBase::~FreshDeviceHandlerBase() {
+ QueueFactory::instance()->deleteMessageQueue(messageQueue);
+ if (not hasCustomFdir) {
+ delete fdirInstance;
+ }
+}
+
+[[nodiscard]] object_id_t FreshDeviceHandlerBase::getObjectId() const {
+ return SystemObject::getObjectId();
+}
+
+ReturnValue_t FreshDeviceHandlerBase::performOperation(uint8_t opCode) {
+ performDeviceOperationPreQueueHandling(opCode);
+ handleQueue();
+ performDeviceOperation(opCode);
+ poolManager.performHkOperation();
+ return returnvalue::OK;
+}
+
+ReturnValue_t FreshDeviceHandlerBase::performDeviceOperationPreQueueHandling(uint8_t opCode) {
+ return returnvalue::OK;
+}
+
+void FreshDeviceHandlerBase::startTransition(Mode_t mode_, Submode_t submode_) {
+ triggerEvent(CHANGING_MODE, mode_, submode_);
+ // Complete mode transition immediately by default.
+ setMode(mode_, submode_);
+}
+
+void FreshDeviceHandlerBase::setMode(Mode_t newMode, Submode_t newSubmode) {
+ mode = newMode;
+ submode = newSubmode;
+ modeHelper.modeChanged(mode, submode);
+ modeChanged(mode, submode);
+ announceMode(false);
+}
+
+void FreshDeviceHandlerBase::setMode(Mode_t newMode) { setMode(newMode, submode); }
+
+void FreshDeviceHandlerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
+ *mode_ = this->mode;
+ *submode_ = this->submode;
+}
+
+void FreshDeviceHandlerBase::announceMode(bool recursive) {
+ triggerEvent(MODE_INFO, mode, submode);
+}
+
+void FreshDeviceHandlerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
+
+[[nodiscard]] MessageQueueId_t FreshDeviceHandlerBase::getCommandQueue() const {
+ return messageQueue->getId();
+}
+
+ReturnValue_t FreshDeviceHandlerBase::handleQueue() {
+ CommandMessage command;
+ ReturnValue_t result;
+ for (result = messageQueue->receiveMessage(&command); result == returnvalue::OK;
+ result = messageQueue->receiveMessage(&command)) {
+ result = actionHelper.handleActionMessage(&command);
+ if (result == returnvalue::OK) {
+ continue;
+ }
+
+ result = modeHelper.handleModeCommand(&command);
+ if (result == returnvalue::OK) {
+ continue;
+ }
+
+ result = healthHelper.handleHealthCommand(&command);
+ if (result == returnvalue::OK) {
+ continue;
+ }
+
+ result = paramHelper.handleParameterMessage(&command);
+ if (result == returnvalue::OK) {
+ continue;
+ }
+
+ result = poolManager.handleHousekeepingMessage(&command);
+ if (result == returnvalue::OK) {
+ continue;
+ }
+
+ result = handleCommandMessage(&command);
+ if (result == returnvalue::OK) {
+ continue;
+ }
+ command.setToUnknownCommand();
+ messageQueue->reply(&command);
+ }
+ return result;
+}
+
+HasHealthIF::HealthState FreshDeviceHandlerBase::getHealth() { return healthHelper.getHealth(); }
+
+const HasHealthIF* FreshDeviceHandlerBase::getOptHealthIF() const { return this; }
+
+const HasModesIF& FreshDeviceHandlerBase::getModeIF() const { return *this; }
+
+ModeTreeChildIF& FreshDeviceHandlerBase::getModeTreeChildIF() { return *this; }
+
+ReturnValue_t FreshDeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
+ return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
+}
+
+// Executable Overrides.
+void FreshDeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
+
+// Pool Manager overrides.
+LocalDataPoolManager* FreshDeviceHandlerBase::getHkManagerHandle() { return &poolManager; }
+
+[[nodiscard]] uint32_t FreshDeviceHandlerBase::getPeriodicOperationFrequency() const {
+ return this->executingTask->getPeriodMs();
+}
+
+ReturnValue_t FreshDeviceHandlerBase::initializeAfterTaskCreation() {
+ return poolManager.initializeAfterTaskCreation();
+}
+
+ReturnValue_t FreshDeviceHandlerBase::setHealth(HasHealthIF::HealthState health) {
+ // Assembly should handle commanding to OFF.
+ healthHelper.setHealth(health);
+ return returnvalue::OK;
+}
+
+void FreshDeviceHandlerBase::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) {
+ fdirInstance->triggerEvent(event, parameter1, parameter2);
+}
+
+void FreshDeviceHandlerBase::forwardEvent(Event event, uint32_t parameter1,
+ uint32_t parameter2) const {
+ fdirInstance->triggerEvent(event, parameter1, parameter2);
+}
+
+void FreshDeviceHandlerBase::setToExternalControl() { setHealth(HealthState::EXTERNAL_CONTROL); }
+
+// System Object overrides.
+ReturnValue_t FreshDeviceHandlerBase::initialize() {
+ ReturnValue_t result = modeHelper.initialize();
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ result = healthHelper.initialize();
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ result = actionHelper.initialize(messageQueue);
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ result = paramHelper.initialize();
+ if (result != returnvalue::OK) {
+ return result;
+ }
+
+ result = poolManager.initialize(messageQueue);
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ if (fdirInstance == nullptr) {
+ hasCustomFdir = false;
+ fdirInstance = new DeviceHandlerFailureIsolation(getObjectId(), defaultFdirParent);
+ }
+
+ result = fdirInstance->initialize();
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ return SystemObject::initialize();
+}
+
+ReturnValue_t FreshDeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uniqueId,
+ ParameterWrapper* parameterWrapper,
+ const ParameterWrapper* newValues,
+ uint16_t startAtIndex) {
+ ReturnValue_t result =
+ fdirInstance->getParameter(domainId, uniqueId, parameterWrapper, newValues, startAtIndex);
+ if (result != INVALID_DOMAIN_ID) {
+ return result;
+ }
+ return INVALID_DOMAIN_ID;
+}
diff --git a/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h
new file mode 100644
index 00000000..c911c1dd
--- /dev/null
+++ b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h
@@ -0,0 +1,167 @@
+#pragma once
+
+#include "fsfw/action.h"
+#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
+#include "fsfw/datapoollocal/LocalDataPoolManager.h"
+#include "fsfw/devicehandlers/DeviceHandlerIF.h"
+#include "fsfw/fdir/FailureIsolationBase.h"
+#include "fsfw/health/HasHealthIF.h"
+#include "fsfw/health/HealthHelper.h"
+#include "fsfw/modes/HasModesIF.h"
+#include "fsfw/objectmanager.h"
+#include "fsfw/parameters/ParameterHelper.h"
+#include "fsfw/parameters/ReceivesParameterMessagesIF.h"
+#include "fsfw/retval.h"
+#include "fsfw/subsystem/ModeTreeChildIF.h"
+#include "fsfw/subsystem/ModeTreeConnectionIF.h"
+#include "fsfw/tasks/ExecutableObjectIF.h"
+#include "fsfw/tasks/PeriodicTaskIF.h"
+
+struct DhbConfig {
+ explicit DhbConfig(object_id_t objectId) : objectId(objectId) {}
+ object_id_t objectId;
+ FailureIsolationBase* fdirInstance = nullptr;
+ object_id_t defaultFdirParent = objects::NO_OBJECT;
+ uint32_t msgQueueDepth = 10;
+};
+
+class FreshDeviceHandlerBase : public SystemObject,
+ public DeviceHandlerIF,
+ public HasModesIF,
+ public HasHealthIF,
+ public ExecutableObjectIF,
+ public ModeTreeChildIF,
+ public ModeTreeConnectionIF,
+ public HasActionsIF,
+ public ReceivesParameterMessagesIF,
+ public HasLocalDataPoolIF {
+ public:
+ explicit FreshDeviceHandlerBase(DhbConfig config);
+ ~FreshDeviceHandlerBase() override;
+
+ /**
+ * Periodic helper executed function, implemented by child class.
+ */
+ virtual void performDeviceOperation(uint8_t opCode) = 0;
+
+ [[nodiscard]] object_id_t getObjectId() const override;
+
+ [[nodiscard]] MessageQueueId_t getCommandQueue() const override;
+
+ HasHealthIF::HealthState getHealth() override;
+
+ // Mode Tree Overrides.
+ [[nodiscard]] const HasHealthIF* getOptHealthIF() const override;
+ [[nodiscard]] const HasModesIF& getModeIF() const override;
+ ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
+ ModeTreeChildIF& getModeTreeChildIF() override;
+
+ [[nodiscard]] uint32_t getPeriodicOperationFrequency() const override;
+
+ protected:
+ // Pool Manager overrides.
+ LocalDataPoolManager* getHkManagerHandle() override;
+ ActionHelper actionHelper;
+ ModeHelper modeHelper;
+ HealthHelper healthHelper;
+ ParameterHelper paramHelper;
+ LocalDataPoolManager poolManager;
+
+ bool hasCustomFdir = false;
+ FailureIsolationBase* fdirInstance;
+ object_id_t defaultFdirParent;
+
+ /**
+ * Pointer to the task which executes this component,
+ * is invalid before setTaskIF was called.
+ */
+ PeriodicTaskIF* executingTask = nullptr;
+
+ Mode_t mode = HasModesIF::MODE_UNDEFINED;
+ Submode_t submode = 0;
+
+ MessageQueueIF* messageQueue;
+
+ /**
+ * The default queue handler will process all messages for the interfaces implemented
+ * by this class. If there are special requirements, for example that action commands are
+ * received on a different queue, the user can override this function for those special
+ * requirements.
+ */
+ virtual ReturnValue_t handleQueue();
+
+ // Mode Helpers.
+ virtual void modeChanged(Mode_t mode, Submode_t submode);
+ /**
+ * The default implementation sets the new mode immediately. If this is not applicable for
+ * certain modes, the user should provide a custom implementation, which performs rougly
+ * the same functionality of this function, when all the steps have been taken to reach the
+ * new mode.
+ */
+ void startTransition(Mode_t mode, Submode_t submode) override;
+ virtual void setMode(Mode_t newMode, Submode_t newSubmode);
+ virtual void setMode(Mode_t newMode);
+ void getMode(Mode_t* mode, Submode_t* submode) override;
+ void setToExternalControl() override;
+ void announceMode(bool recursive) override;
+ // System Object overrides.
+ ReturnValue_t initialize() override;
+
+ /**
+ * Implemented by child class. Handle all command messages which are
+ * not health, mode, action or housekeeping messages.
+ * @param message
+ * @return
+ */
+ virtual ReturnValue_t handleCommandMessage(CommandMessage* message) = 0;
+
+ // HK manager abstract functions.
+ LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
+ ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
+ LocalDataPoolManager& poolManager) override = 0;
+
+ // Mode abstract functions
+ ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
+ uint32_t* msToReachTheMode) override = 0;
+ // Health Overrides.
+ ReturnValue_t setHealth(HealthState health) override;
+ // Action override. Forward to user.
+ ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
+ const uint8_t* data, size_t size) override = 0;
+ // Executable overrides.
+ ReturnValue_t performOperation(uint8_t opCode) override;
+ ReturnValue_t initializeAfterTaskCreation() override;
+
+ /**
+ * This calls the FDIR instance event trigger function.
+ * @param event
+ * @param parameter1
+ * @param parameter2
+ */
+ void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override;
+ /**
+ * This calls the FDIR instance event forward function.
+ * @param event
+ * @param parameter1
+ * @param parameter2
+ */
+ void forwardEvent(Event event, uint32_t parameter1, uint32_t parameter2) const override;
+ /**
+ * This implementation handles the FDIR parameters. The user can override this to handle
+ * custom parameters.
+ * @param domainId
+ * @param uniqueId
+ * @param parameterWrapper
+ * @param newValues
+ * @param startAtIndex
+ * @return
+ */
+ ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
+ const ParameterWrapper* newValues, uint16_t startAtIndex) override;
+
+ virtual ReturnValue_t performDeviceOperationPreQueueHandling(uint8_t opCode);
+
+ private:
+ // Executable Overrides.
+ void setTaskIF(PeriodicTaskIF* task) override;
+};
diff --git a/src/fsfw/filesystem/HasFileSystemIF.h b/src/fsfw/filesystem/HasFileSystemIF.h
index a507938e..4f041135 100644
--- a/src/fsfw/filesystem/HasFileSystemIF.h
+++ b/src/fsfw/filesystem/HasFileSystemIF.h
@@ -17,7 +17,7 @@ struct FilesystemParams {
};
struct FileOpParams {
- FileOpParams(const char* path, size_t size) : fsParams(path), size(size) {}
+ FileOpParams(const char* path, size_t opSize) : fsParams(path), size(opSize) {}
[[nodiscard]] const char* path() const { return fsParams.path; }
@@ -80,6 +80,8 @@ class HasFileSystemIF {
virtual bool isDirectory(const char* path) = 0;
+ virtual bool getFileSize(FilesystemParams params, uint64_t& fileSize) = 0;
+
virtual bool fileExists(FilesystemParams params) = 0;
/**
diff --git a/src/fsfw/globalfunctions/math/QuaternionOperations.cpp b/src/fsfw/globalfunctions/math/QuaternionOperations.cpp
index f65a1847..ce44dc08 100644
--- a/src/fsfw/globalfunctions/math/QuaternionOperations.cpp
+++ b/src/fsfw/globalfunctions/math/QuaternionOperations.cpp
@@ -39,6 +39,39 @@ void QuaternionOperations::inverse(const double* quaternion, double* inverseQuat
VectorOperations::mulScalar(inverseQuaternion, -1, inverseQuaternion, 3);
}
+void QuaternionOperations::slerp(const double q1[4], const double q2[4], const double weight,
+ double q[4]) {
+ double q1s[4] = {0, 0, 0, 0}, q2I[4] = {0, 0, 0, 0}, qD[4] = {0, 0, 0, 0}, left[4] = {0, 0, 0, 0},
+ right[4] = {0, 0, 0, 0}, angle = 0;
+
+ // we need to be able to invert this quaternion
+ std::memcpy(q1s, q1, 4 * sizeof(double));
+ // calculate angle between orientations
+ inverse(q2, q2I);
+ multiply(q1s, q2I, qD);
+ angle = std::acos(qD[3]);
+
+ if (std::cos(angle) < 0.0) {
+ // we need to invert one quaternion
+ VectorOperations::mulScalar(q1s, -1, q1s, 4);
+ multiply(q1s, q2I, qD);
+ angle = std::acos(qD[3]);
+ }
+
+ if (std::sin(angle) == 0.0) {
+ // nothing to calculate here
+ std::memcpy(q, q1s, 4 * sizeof(double));
+ return;
+ }
+
+ VectorOperations::mulScalar(q1s, std::sin((1 - weight) * angle) / std::sin(angle), left,
+ 4);
+ VectorOperations::mulScalar(q2, std::sin(weight * angle) / std::sin(angle), right, 4);
+ VectorOperations::add(left, right, q, 4);
+
+ normalize(q);
+}
+
QuaternionOperations::QuaternionOperations() {}
void QuaternionOperations::normalize(const double* quaternion, double* unitQuaternion) {
diff --git a/src/fsfw/globalfunctions/math/QuaternionOperations.h b/src/fsfw/globalfunctions/math/QuaternionOperations.h
index e8ca400a..473cee2b 100644
--- a/src/fsfw/globalfunctions/math/QuaternionOperations.h
+++ b/src/fsfw/globalfunctions/math/QuaternionOperations.h
@@ -23,6 +23,8 @@ class QuaternionOperations {
static void inverse(const double *quaternion, double *inverseQuaternion);
+ static void slerp(const double q1[4], const double q2[4], const double weight, double q[4]);
+
/**
* returns angle in ]-Pi;Pi] or [0;Pi] if abs == true
*/
diff --git a/src/fsfw/objectmanager/ObjectManager.cpp b/src/fsfw/objectmanager/ObjectManager.cpp
index e3af0ee4..e4a575f0 100644
--- a/src/fsfw/objectmanager/ObjectManager.cpp
+++ b/src/fsfw/objectmanager/ObjectManager.cpp
@@ -118,8 +118,9 @@ void ObjectManager::initialize() {
<< result << std::dec << std::setfill(' ') << std::endl;
#else
sif::printError(
- "ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
- result);
+ "ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n",
+ it.first, result);
+#endif
#endif
errorCount++;
}
diff --git a/src/fsfw/osal/common/TcpTmTcBridge.cpp b/src/fsfw/osal/common/TcpTmTcBridge.cpp
index 0bf3ab28..80c2ddd1 100644
--- a/src/fsfw/osal/common/TcpTmTcBridge.cpp
+++ b/src/fsfw/osal/common/TcpTmTcBridge.cpp
@@ -21,7 +21,7 @@ TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
: TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
mutex = MutexFactory::instance()->createMutex();
// Connection is always up, TM is requested by connecting to server and receiving packets
- registerCommConnect();
+ TmTcBridge::registerCommConnect();
}
ReturnValue_t TcpTmTcBridge::initialize() {
diff --git a/src/fsfw/osal/common/TcpTmTcServer.h b/src/fsfw/osal/common/TcpTmTcServer.h
index b8c6ea2c..2b549d87 100644
--- a/src/fsfw/osal/common/TcpTmTcServer.h
+++ b/src/fsfw/osal/common/TcpTmTcServer.h
@@ -123,6 +123,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
StorageManagerIF* tmStore = nullptr;
private:
+ //! [EXPORT] : [SKIP]
static constexpr ReturnValue_t CONN_BROKEN = returnvalue::makeCode(1, 0);
//! TMTC bridge is cached.
object_id_t tmtcBridgeId = objects::NO_OBJECT;
diff --git a/src/fsfw/power/PowerSwitcherComponent.h b/src/fsfw/power/PowerSwitcherComponent.h
index 8c74e76f..f0aac2ee 100644
--- a/src/fsfw/power/PowerSwitcherComponent.h
+++ b/src/fsfw/power/PowerSwitcherComponent.h
@@ -38,6 +38,8 @@ class PowerSwitcherComponent : public SystemObject,
protected:
PowerSwitcher switcher;
+ ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
+ uint32_t *msToReachTheMode) override;
private:
MessageQueueIF *queue = nullptr;
@@ -56,8 +58,6 @@ class PowerSwitcherComponent : public SystemObject,
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
void getMode(Mode_t *mode, Submode_t *submode) override;
- ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
- uint32_t *msToReachTheMode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
virtual void performFaultyOperation();
void setToExternalControl() override;
diff --git a/src/fsfw/pus/Service11TelecommandScheduling.h b/src/fsfw/pus/Service11TelecommandScheduling.h
index 83b2b4c0..fd9cf733 100644
--- a/src/fsfw/pus/Service11TelecommandScheduling.h
+++ b/src/fsfw/pus/Service11TelecommandScheduling.h
@@ -43,6 +43,7 @@ class Service11TelecommandScheduling final : public PusServiceBase {
static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4);
static constexpr ReturnValue_t CONTAINED_TC_TOO_SMALL = returnvalue::makeCode(CLASS_ID, 5);
static constexpr ReturnValue_t CONTAINED_TC_CRC_MISSMATCH = returnvalue::makeCode(CLASS_ID, 6);
+ static constexpr ReturnValue_t MAP_IS_FULL = returnvalue::makeCode(CLASS_ID, 7);
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;
diff --git a/src/fsfw/pus/Service11TelecommandScheduling.tpp b/src/fsfw/pus/Service11TelecommandScheduling.tpp
index 8352f85d..21852b63 100644
--- a/src/fsfw/pus/Service11TelecommandScheduling.tpp
+++ b/src/fsfw/pus/Service11TelecommandScheduling.tpp
@@ -150,6 +150,9 @@ inline ReturnValue_t Service11TelecommandScheduling::handleResetCom
template
inline ReturnValue_t Service11TelecommandScheduling::doInsertActivity(
const uint8_t *data, size_t size) {
+ if(telecommandMap.full()) {
+ return MAP_IS_FULL;
+ }
uint32_t timestamp = 0;
ReturnValue_t result = SerializeAdapter::deSerialize(×tamp, &data, &size, DEF_END);
if (result != returnvalue::OK) {
diff --git a/src/fsfw/returnvalues/FwClassIds.h b/src/fsfw/returnvalues/FwClassIds.h
index 9a5cc812..9a4fa992 100644
--- a/src/fsfw/returnvalues/FwClassIds.h
+++ b/src/fsfw/returnvalues/FwClassIds.h
@@ -61,7 +61,8 @@ enum : uint8_t {
HAS_ACTIONS_IF, // HF
DEVICE_COMMUNICATION_IF, // DC
BSP, // BSP
- CFDP, // CFDP
+ CFDP_BASE, // CFDP
+ CFDP_HANDLER, // CFDP
TIME_STAMPER_IF, // TSI
SGP4PROPAGATOR_CLASS, // SGP4
MUTEX_IF, // MUX
diff --git a/src/fsfw/serialize/SerialBufferAdapter.cpp b/src/fsfw/serialize/SerialBufferAdapter.cpp
index 01eb76f9..3d0de695 100644
--- a/src/fsfw/serialize/SerialBufferAdapter.cpp
+++ b/src/fsfw/serialize/SerialBufferAdapter.cpp
@@ -107,14 +107,6 @@ uint8_t* SerialBufferAdapter::getBuffer() {
template
const uint8_t* SerialBufferAdapter::getConstBuffer() const {
- if (constBuffer == nullptr) {
-#if FSFW_CPP_OSTREAM_ENABLED == 1
- sif::error << "SerialBufferAdapter::getConstBuffer:"
- " Buffers are unitialized!"
- << std::endl;
-#endif
- return nullptr;
- }
return constBuffer;
}
diff --git a/src/fsfw/serialize/SerialBufferAdapter.h b/src/fsfw/serialize/SerialBufferAdapter.h
index 9030d7cc..37bc69b3 100644
--- a/src/fsfw/serialize/SerialBufferAdapter.h
+++ b/src/fsfw/serialize/SerialBufferAdapter.h
@@ -63,7 +63,17 @@ class SerialBufferAdapter : public SerializeIF {
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
+ /**
+ * Please note that this function can also return a nullpointer in case the length field contains
+ * 0.
+ * @return
+ */
uint8_t* getBuffer();
+ /**
+ * Please note that this function can also return a nullpointer in case the length field contains
+ * 0.
+ * @return
+ */
[[nodiscard]] const uint8_t* getConstBuffer() const;
void setConstBuffer(const uint8_t* buf, count_t bufLen);
diff --git a/src/fsfw/storagemanager/LocalPool.cpp b/src/fsfw/storagemanager/LocalPool.cpp
index b62c19b6..9a4b53a6 100644
--- a/src/fsfw/storagemanager/LocalPool.cpp
+++ b/src/fsfw/storagemanager/LocalPool.cpp
@@ -89,7 +89,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) {
ReturnValue_t status = returnvalue::OK;
size_type pageSize = getSubpoolElementSize(storeId.poolIndex);
if ((pageSize != 0) and (storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
- uint16_t packetPosition = getRawPosition(storeId);
+ size_type packetPosition = getRawPosition(storeId);
uint8_t* ptr = &store[storeId.poolIndex][packetPosition];
std::memset(ptr, 0, pageSize);
// Set free list
diff --git a/src/fsfw/tmtcservices/TmTcBridge.cpp b/src/fsfw/tmtcservices/TmTcBridge.cpp
index d91170c1..9801b21e 100644
--- a/src/fsfw/tmtcservices/TmTcBridge.cpp
+++ b/src/fsfw/tmtcservices/TmTcBridge.cpp
@@ -23,18 +23,8 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
-ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle) {
- if (sentPacketsPerCycle <= LIMIT_STORED_DATA_SENT_PER_CYCLE) {
- this->sentPacketsPerCycle = sentPacketsPerCycle;
- return returnvalue::OK;
- } else {
-#if FSFW_CPP_OSTREAM_ENABLED == 1
- sif::warning << "TmTcBridge::setNumberOfSentPacketsPerCycle: Number of "
- << "packets sent per cycle exceeds limits. "
- << "Keeping default value." << std::endl;
-#endif
- return returnvalue::FAILED;
- }
+void TmTcBridge::setNumberOfSentPacketsPerCycle(uint32_t sentPacketsPerCycle_) {
+ this->sentPacketsPerCycle = sentPacketsPerCycle_;
}
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
@@ -144,7 +134,7 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
- if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
+ if (!communicationLinkUp or packetSentCounter >= sentPacketsPerCycle) {
result = storeDownlinkData(&message);
if (result != returnvalue::OK) {
tmStore->deleteData(message.getStorageId());
diff --git a/src/fsfw/tmtcservices/TmTcBridge.h b/src/fsfw/tmtcservices/TmTcBridge.h
index 858793cc..c87be45c 100644
--- a/src/fsfw/tmtcservices/TmTcBridge.h
+++ b/src/fsfw/tmtcservices/TmTcBridge.h
@@ -15,10 +15,9 @@ class TmTcBridge : public AcceptsTelemetryIF,
public ExecutableObjectIF,
public SystemObject {
public:
- static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
- static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
+ static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 20;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
@@ -32,7 +31,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
* @return -@c returnvalue::OK if value was set successfully
* -@c returnvalue::FAILED otherwise, stored value stays the same
*/
- ReturnValue_t setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle);
+ void setNumberOfSentPacketsPerCycle(uint32_t sentPacketsPerCycle);
/**
* Set number of packets sent per performOperation().Please note that this
@@ -151,7 +150,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
* This FIFO can be used to store downlink data which can not be sent at the moment.
*/
DynamicFIFO* tmFifo = nullptr;
- uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
+ uint32_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
};
diff --git a/src/fsfw/util/CMakeLists.txt b/src/fsfw/util/CMakeLists.txt
new file mode 100644
index 00000000..a0d48465
--- /dev/null
+++ b/src/fsfw/util/CMakeLists.txt
@@ -0,0 +1 @@
+target_sources(${LIB_FSFW_NAME} PRIVATE)
diff --git a/src/fsfw/util/ProvidesSeqCountIF.h b/src/fsfw/util/ProvidesSeqCountIF.h
new file mode 100644
index 00000000..d88f9024
--- /dev/null
+++ b/src/fsfw/util/ProvidesSeqCountIF.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include
+
+class ProvidesSeqCountIF {
+ public:
+ virtual ~ProvidesSeqCountIF() = default;
+
+ [[nodiscard]] virtual unsigned int bitWidth() const = 0;
+
+ virtual uint64_t get() = 0;
+ virtual void increment() = 0;
+
+ virtual uint64_t getAndIncrement() {
+ uint64_t val = get();
+ increment();
+ return val;
+ }
+};
diff --git a/src/fsfw/util/SeqCountProvider.h b/src/fsfw/util/SeqCountProvider.h
new file mode 100644
index 00000000..fe16431f
--- /dev/null
+++ b/src/fsfw/util/SeqCountProvider.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include
+
+#include "ProvidesSeqCountIF.h"
+
+template
+class SeqCountProvider : public ProvidesSeqCountIF {
+ static_assert(std::is_same::value || std::is_same::value ||
+ std::is_same::value,
+ "Only uint8_t, uint16_t, and uint32_t are allowed.");
+
+ public:
+ [[nodiscard]] unsigned int bitWidth() const override { return sizeof(T) * 8; }
+ uint64_t get() override { return counter; }
+ // I'm also abusing the primitive C variable overflow wrap around here.
+ void increment() override { counter++; }
+
+ private:
+ T counter{};
+};
+
+using SeqCountProviderU8 = SeqCountProvider;
+using SeqCountProviderU16 = SeqCountProvider;
+using SeqCountProviderU32 = SeqCountProvider;
diff --git a/src/fsfw_hal/host/HostFilesystem.cpp b/src/fsfw_hal/host/HostFilesystem.cpp
index 20984f77..b574c6c0 100644
--- a/src/fsfw_hal/host/HostFilesystem.cpp
+++ b/src/fsfw_hal/host/HostFilesystem.cpp
@@ -184,3 +184,11 @@ ReturnValue_t HostFilesystem::getBaseFilename(FilesystemParams params, char *nam
baseNameLen = baseName.size();
return returnvalue::OK;
}
+
+bool HostFilesystem::getFileSize(FilesystemParams params, uint64_t &fileSize) {
+ if (!fileExists(params)) {
+ return false;
+ }
+ fileSize = std::filesystem::file_size(params.path);
+ return true;
+}
diff --git a/src/fsfw_hal/host/HostFilesystem.h b/src/fsfw_hal/host/HostFilesystem.h
index da217aec..fd745e09 100644
--- a/src/fsfw_hal/host/HostFilesystem.h
+++ b/src/fsfw_hal/host/HostFilesystem.h
@@ -11,6 +11,7 @@ class HostFilesystem : public HasFileSystemIF {
ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) override;
+ virtual bool getFileSize(FilesystemParams params, uint64_t &fileSize) override;
bool isDirectory(const char *path) override;
bool fileExists(FilesystemParams params) override;
ReturnValue_t truncateFile(FilesystemParams params) override;
diff --git a/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp b/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp
index 4d688bd5..611b34dc 100644
--- a/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp
+++ b/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp
@@ -282,7 +282,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t *recvPtr, SPI_HandleT
#endif
#endif
spiCookie.setTransferState(spi::TransferStates::FAILURE);
- return spi::HAL_TIMEOUT_RETVAL;
+ return spi::TIMEOUT;
}
case (HAL_ERROR):
default: {
@@ -296,7 +296,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t *recvPtr, SPI_HandleT
#endif
#endif
spiCookie.setTransferState(spi::TransferStates::FAILURE);
- return spi::HAL_ERROR_RETVAL;
+ return spi::GENERIC_ERROR;
}
}
return returnvalue::OK;
diff --git a/src/fsfw_hal/stm32h7/spi/spiDefinitions.h b/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
index cf05d986..60c662b1 100644
--- a/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
+++ b/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
@@ -9,11 +9,6 @@
namespace spi {
-static constexpr uint8_t HAL_SPI_ID = CLASS_ID::HAL_SPI;
-static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 0);
-static constexpr ReturnValue_t HAL_BUSY_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 1);
-static constexpr ReturnValue_t HAL_ERROR_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 2);
-
enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE };
enum SpiBus { SPI_1, SPI_2 };
diff --git a/unittests/CatchFactory.cpp b/unittests/CatchFactory.cpp
index 668ab395..10823636 100644
--- a/unittests/CatchFactory.cpp
+++ b/unittests/CatchFactory.cpp
@@ -32,7 +32,7 @@ void Factory::produceFrameworkObjects(void* args) {
setStaticFrameworkObjectIds();
new EventManager(objects::EVENT_MANAGER, 80);
new HealthTable(objects::HEALTH_TABLE);
- new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 20, false, 1.0);
+ new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 20, false, 5.0);
{
PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}};
diff --git a/unittests/action/TestActionHelper.cpp b/unittests/action/TestActionHelper.cpp
index de021bb8..3b22dcee 100644
--- a/unittests/action/TestActionHelper.cpp
+++ b/unittests/action/TestActionHelper.cpp
@@ -57,7 +57,7 @@ TEST_CASE("Action Helper", "[action]") {
step += 1;
CHECK(testMqMock.wasMessageSent());
CommandMessage testMessage;
- REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
+ REQUIRE(testMqMock.getNextSentMessageToDefaultDest(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED));
REQUIRE(testMessage.getParameter() == static_cast(testActionId));
uint32_t parameter2 = ((uint32_t)step << 16) | (uint32_t)status;
@@ -71,7 +71,7 @@ TEST_CASE("Action Helper", "[action]") {
actionHelper.finish(false, testMqMock.getId(), testActionId, status);
CHECK(testMqMock.wasMessageSent());
CommandMessage testMessage;
- REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
+ REQUIRE(testMqMock.getNextSentMessageToDefaultDest(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::COMPLETION_FAILED));
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast(status));
@@ -87,7 +87,7 @@ TEST_CASE("Action Helper", "[action]") {
REQUIRE(ipcStore->getData(toLongParamAddress).first ==
static_cast(StorageManagerIF::DATA_DOES_NOT_EXIST));
CommandMessage testMessage;
- REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
+ REQUIRE(testMqMock.getNextSentMessageToDefaultDest(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED));
REQUIRE(ActionMessage::getReturnCode(&testMessage) == 0xAFFE);
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
diff --git a/unittests/cfdp/CMakeLists.txt b/unittests/cfdp/CMakeLists.txt
index 1867a534..aba30ede 100644
--- a/unittests/cfdp/CMakeLists.txt
+++ b/unittests/cfdp/CMakeLists.txt
@@ -1,5 +1,6 @@
-target_sources(${FSFW_TEST_TGT} PRIVATE testCfdp.cpp testOtherTlvs.cpp
- testTlv.cpp testLvs.cpp)
+target_sources(
+ ${FSFW_TEST_TGT} PRIVATE testCfdp.cpp testOtherTlvs.cpp
+ testReservedMsgCreator.cpp testTlv.cpp testLvs.cpp)
add_subdirectory(handler)
add_subdirectory(pdu)
diff --git a/unittests/cfdp/handler/CMakeLists.txt b/unittests/cfdp/handler/CMakeLists.txt
index f70e5dfb..6a8b25ec 100644
--- a/unittests/cfdp/handler/CMakeLists.txt
+++ b/unittests/cfdp/handler/CMakeLists.txt
@@ -1,3 +1,4 @@
target_sources(
- ${FSFW_TEST_TGT} PRIVATE testDistributor.cpp testDestHandler.cpp
- testSourceHandler.cpp testFaultHandler.cpp)
+ ${FSFW_TEST_TGT}
+ PRIVATE testDistributor.cpp testDestHandler.cpp testReservedMsgParser.cpp
+ testPutRequest.cpp testSourceHandler.cpp testFaultHandler.cpp)
diff --git a/unittests/cfdp/handler/testDestHandler.cpp b/unittests/cfdp/handler/testDestHandler.cpp
index 0224a20b..4aa2dc32 100644
--- a/unittests/cfdp/handler/testDestHandler.cpp
+++ b/unittests/cfdp/handler/testDestHandler.cpp
@@ -50,18 +50,18 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
auto destHandler = DestHandler(dp, fp);
CHECK(destHandler.initialize() == OK);
- auto metadataPreparation = [&](FileSize cfdpFileSize, ChecksumType checksumType) {
+ auto metadataPreparation = [&](Fss cfdpFileSize, ChecksumType checksumType) {
std::string srcNameString = "hello.txt";
std::string destNameString = "hello-cpy.txt";
StringLv srcName(srcNameString);
StringLv destName(destNameString);
- MetadataInfo info(false, checksumType, cfdpFileSize, srcName, destName);
+ MetadataGenericInfo info(false, checksumType, std::move(cfdpFileSize));
TransactionSeqNum seqNum(UnsignedByteField(1));
conf.sourceId = remoteId;
conf.destId = localId;
conf.mode = TransmissionMode::UNACKNOWLEDGED;
conf.seqNum = seqNum;
- MetadataPduCreator metadataCreator(conf, info);
+ MetadataPduCreator metadataCreator(conf, info, srcName, destName, nullptr, 0);
REQUIRE(tcStore.getFreeElement(&storeId, metadataCreator.getSerializedSize(), &buf) == OK);
REQUIRE(metadataCreator.serialize(buf, serLen, metadataCreator.getSerializedSize()) == OK);
PacketInfo packetInfo(metadataCreator.getPduType(), storeId,
@@ -81,17 +81,17 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
auto& idMetadataPair = userMock.metadataRecvd.back();
REQUIRE(idMetadataPair.first == destHandler.getTransactionId());
REQUIRE(idMetadataPair.second.sourceId.getValue() == 3);
- REQUIRE(idMetadataPair.second.fileSize == fileLen);
+ REQUIRE(idMetadataPair.second.fileSize.getSize(nullptr) == fileLen);
REQUIRE(strcmp(idMetadataPair.second.destFileName, destName) == 0);
REQUIRE(strcmp(idMetadataPair.second.sourceFileName, sourceName) == 0);
userMock.metadataRecvd.pop();
REQUIRE(fsMock.fileMap.find(destName) != fsMock.fileMap.end());
REQUIRE(res.result == OK);
- REQUIRE(res.state == CfdpStates::BUSY_CLASS_1_NACKED);
+ REQUIRE(res.state == CfdpState::BUSY_CLASS_1_NACKED);
REQUIRE(res.step == DestHandler::TransactionStep::RECEIVING_FILE_DATA_PDUS);
};
- auto eofPreparation = [&](FileSize cfdpFileSize, uint32_t crc) {
+ auto eofPreparation = [&](Fss cfdpFileSize, uint32_t crc) {
EofInfo eofInfo(cfdp::ConditionCode::NO_ERROR, crc, std::move(cfdpFileSize));
EofPduCreator eofCreator(conf, eofInfo);
REQUIRE(tcStore.getFreeElement(&storeId, eofCreator.getSerializedSize(), &buf) == OK);
@@ -102,14 +102,14 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
auto eofCheck = [&](const cfdp::DestHandler::FsmResult& res, const TransactionId& id) {
REQUIRE(res.result == OK);
- REQUIRE(res.state == CfdpStates::IDLE);
+ REQUIRE(res.state == CfdpState::IDLE);
REQUIRE(res.errors == 0);
REQUIRE(res.step == DestHandler::TransactionStep::IDLE);
// Assert that the packet was deleted after handling
REQUIRE(not tcStore.hasDataAtId(storeId));
REQUIRE(packetInfoList.empty());
- REQUIRE(userMock.eofsRevd.size() == 1);
- auto& eofId = userMock.eofsRevd.back();
+ REQUIRE(userMock.eofRecvdRecvd.size() == 1);
+ auto& eofId = userMock.eofRecvdRecvd.back();
CHECK(eofId == id);
REQUIRE(userMock.finishedRecvd.size() == 1);
auto& idParamPair = userMock.finishedRecvd.back();
@@ -120,7 +120,7 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
auto fileDataPduCheck = [&](const cfdp::DestHandler::FsmResult& res,
const std::vector& idsToCheck) {
REQUIRE(res.result == OK);
- REQUIRE(res.state == CfdpStates::BUSY_CLASS_1_NACKED);
+ REQUIRE(res.state == CfdpState::BUSY_CLASS_1_NACKED);
REQUIRE(res.step == DestHandler::TransactionStep::RECEIVING_FILE_DATA_PDUS);
for (const auto id : idsToCheck) {
REQUIRE(not tcStore.hasDataAtId(id));
@@ -129,50 +129,50 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
};
SECTION("State") {
- CHECK(destHandler.getCfdpState() == CfdpStates::IDLE);
+ CHECK(destHandler.getCfdpState() == CfdpState::IDLE);
CHECK(destHandler.getTransactionStep() == DestHandler::TransactionStep::IDLE);
}
SECTION("Idle State Machine Iteration") {
- auto res = destHandler.performStateMachine();
+ auto res = destHandler.stateMachine();
CHECK(res.result == OK);
CHECK(res.callStatus == CallStatus::CALL_AFTER_DELAY);
CHECK(res.errors == 0);
- CHECK(destHandler.getCfdpState() == CfdpStates::IDLE);
+ CHECK(destHandler.getCfdpState() == CfdpState::IDLE);
CHECK(destHandler.getTransactionStep() == DestHandler::TransactionStep::IDLE);
}
SECTION("Empty File Transfer") {
- const DestHandler::FsmResult& res = destHandler.performStateMachine();
+ const DestHandler::FsmResult& res = destHandler.stateMachine();
CHECK(res.result == OK);
- FileSize cfdpFileSize(0);
+ Fss cfdpFileSize(0);
metadataPreparation(cfdpFileSize, ChecksumType::NULL_CHECKSUM);
- destHandler.performStateMachine();
+ destHandler.stateMachine();
metadataCheck(res, "hello.txt", "hello-cpy.txt", 0);
- destHandler.performStateMachine();
+ destHandler.stateMachine();
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
auto transactionId = destHandler.getTransactionId();
eofPreparation(cfdpFileSize, 0);
// After EOF, operation is done because no closure was requested
- destHandler.performStateMachine();
+ destHandler.stateMachine();
eofCheck(res, transactionId);
}
SECTION("Small File Transfer") {
- const DestHandler::FsmResult& res = destHandler.performStateMachine();
+ const DestHandler::FsmResult& res = destHandler.stateMachine();
CHECK(res.result == OK);
std::string fileData = "hello test data";
etl::crc32 crcCalc;
crcCalc.add(fileData.begin(), fileData.end());
uint32_t crc32 = crcCalc.value();
- FileSize cfdpFileSize(fileData.size());
+ Fss cfdpFileSize(fileData.size());
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
- destHandler.performStateMachine();
+ destHandler.stateMachine();
metadataCheck(res, "hello.txt", "hello-cpy.txt", fileData.size());
- destHandler.performStateMachine();
+ destHandler.stateMachine();
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
auto transactionId = destHandler.getTransactionId();
- FileSize offset(0);
+ Fss offset(0);
FileDataInfo fdPduInfo(offset, reinterpret_cast(fileData.data()),
fileData.size());
FileDataCreator fdPduCreator(conf, fdPduInfo);
@@ -180,16 +180,16 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK);
PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt);
packetInfoList.push_back(packetInfo);
- destHandler.performStateMachine();
+ destHandler.stateMachine();
fileDataPduCheck(res, {storeId});
eofPreparation(cfdpFileSize, crc32);
// After EOF, operation is done because no closure was requested
- destHandler.performStateMachine();
+ destHandler.stateMachine();
eofCheck(res, transactionId);
}
SECTION("Segmented File Transfer") {
- const DestHandler::FsmResult& res = destHandler.performStateMachine();
+ const DestHandler::FsmResult& res = destHandler.stateMachine();
CHECK(res.result == OK);
std::random_device dev;
std::mt19937 rng(dev());
@@ -201,17 +201,17 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
etl::crc32 crcCalc;
crcCalc.add(largerFileData.begin(), largerFileData.end());
uint32_t crc32 = crcCalc.value();
- FileSize cfdpFileSize(largerFileData.size());
+ Fss cfdpFileSize(largerFileData.size());
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
- destHandler.performStateMachine();
+ destHandler.stateMachine();
metadataCheck(res, "hello.txt", "hello-cpy.txt", largerFileData.size());
- destHandler.performStateMachine();
+ destHandler.stateMachine();
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
auto transactionId = destHandler.getTransactionId();
std::vector idsToCheck;
{
- FileSize offset(0);
+ Fss offset(0);
FileDataInfo fdPduInfo(offset, reinterpret_cast(largerFileData.data()),
largerFileData.size() / 2);
FileDataCreator fdPduCreator(conf, fdPduInfo);
@@ -223,7 +223,7 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
}
{
- FileSize offset(512);
+ Fss offset(512);
FileDataInfo fdPduInfo(offset, reinterpret_cast(largerFileData.data() + 512),
largerFileData.size() / 2);
FileDataCreator fdPduCreator(conf, fdPduInfo);
@@ -234,11 +234,11 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
packetInfoList.push_back(packetInfo);
}
- destHandler.performStateMachine();
+ destHandler.stateMachine();
fileDataPduCheck(res, idsToCheck);
eofPreparation(cfdpFileSize, crc32);
// After EOF, operation is done because no closure was requested
- destHandler.performStateMachine();
+ destHandler.stateMachine();
eofCheck(res, transactionId);
}
}
\ No newline at end of file
diff --git a/unittests/cfdp/handler/testDistributor.cpp b/unittests/cfdp/handler/testDistributor.cpp
index 8b6c46af..f6685c89 100644
--- a/unittests/cfdp/handler/testDistributor.cpp
+++ b/unittests/cfdp/handler/testDistributor.cpp
@@ -21,7 +21,7 @@ TEST_CASE("CFDP Distributor", "[cfdp][distributor]") {
auto tcAcceptor = AcceptsTcMock("CFDP Receiver", 0, receiverQueueId);
// Set up Metadata PDU for generate test data.
- cfdp::FileSize fileSize(12);
+ cfdp::Fss fileSize(12);
const cfdp::EntityId& sourceId(groundEntityId);
const cfdp::EntityId& destId(obswEntityId);
cfdp::TransactionSeqNum seqNum(UnsignedByteField(12));
@@ -30,9 +30,8 @@ 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,
- destFileName);
- MetadataPduCreator creator(pduConf, metadataInfo);
+ MetadataGenericInfo metadataInfo(false, cfdp::ChecksumType::CRC_32, fileSize);
+ MetadataPduCreator creator(pduConf, metadataInfo, sourceFileName, destFileName, nullptr, 0);
uint8_t* dataPtr = nullptr;
SECTION("State") {
diff --git a/unittests/cfdp/handler/testPutRequest.cpp b/unittests/cfdp/handler/testPutRequest.cpp
new file mode 100644
index 00000000..6dcf5ca8
--- /dev/null
+++ b/unittests/cfdp/handler/testPutRequest.cpp
@@ -0,0 +1,59 @@
+#include
+#include
+
+#include "fsfw/cfdp/handler/PutRequest.h"
+#include "fsfw/cfdp/tlv/ReservedMessageCreator.h"
+
+TEST_CASE("Put Request", "[cfdp]") {
+ using namespace cfdp;
+ using namespace returnvalue;
+
+ std::array reservedMsgCustomData{};
+ std::array reservedMsgBuf{};
+ std::array buffer{};
+ EntityId destId(WidthInBytes::ONE_BYTE, 5);
+ std::string srcFileName = "hello.txt";
+ std::string destFileName = "hello2.txt";
+ uint8_t* msgBufPtr = reservedMsgCustomData.data();
+ size_t msgSize = 0;
+ cfdp::StringLv srcName(srcFileName);
+ cfdp::StringLv destName(destFileName);
+ CHECK(destId.serializeAsLv(&msgBufPtr, &msgSize, reservedMsgCustomData.size()) == OK);
+ CHECK(srcName.serialize(&msgBufPtr, &msgSize, reservedMsgCustomData.size(),
+ SerializeIF::Endianness::NETWORK) == OK);
+ CHECK(destName.serialize(&msgBufPtr, &msgSize, reservedMsgCustomData.size(),
+ SerializeIF::Endianness::NETWORK) == OK);
+ ReservedMessageCreator creator(static_cast(ProxyOpMessageType::PUT_REQUEST),
+ reservedMsgCustomData.data(), msgSize);
+ msgSize = 0;
+ ReturnValue_t result = creator.serializeBe(reservedMsgBuf.data(), msgSize, buffer.size());
+ CHECK(result == returnvalue::OK);
+
+ SECTION("Put Request with reserved message") {
+ PutRequest putRequest(destId, reservedMsgBuf.data(), msgSize, nullptr, 0);
+ uint8_t* bufPtr = buffer.data();
+ size_t serLen = 0;
+ REQUIRE(putRequest.serialize(&bufPtr, &serLen, buffer.size(),
+ SerializeIF::Endianness::NETWORK) == OK);
+
+ CHECK(putRequest.getSerializedSize() == serLen);
+ PutRequest requestDeserialized;
+ size_t deserLen = putRequest.getSerializedSize();
+ const uint8_t* deserPtr = buffer.data();
+ REQUIRE(requestDeserialized.deSerialize(&deserPtr, &deserLen,
+ SerializeIF::Endianness::NETWORK) == OK);
+ CHECK(requestDeserialized.getDestId().getWidth() == destId.getWidth());
+ CHECK(requestDeserialized.getDestId().getValue() == destId.getValue());
+ size_t totalMsgsSize = 0;
+ const uint8_t* msgsToUserStart = requestDeserialized.getMessagesToUser(totalMsgsSize);
+ CHECK(totalMsgsSize == msgSize);
+ cfdp::Tlv genericTlv;
+ genericTlv.deSerialize(&msgsToUserStart, &totalMsgsSize, SerializeIF::Endianness::NETWORK);
+ CHECK(genericTlv.getType() == TlvType::MSG_TO_USER);
+ CHECK(genericTlv.getLengthField() == genericTlv.getSerializedSize() - 2);
+ CHECK(genericTlv.getValue()[0] == 'c');
+ CHECK(genericTlv.getValue()[1] == 'f');
+ CHECK(genericTlv.getValue()[2] == 'd');
+ CHECK(genericTlv.getValue()[3] == 'p');
+ }
+}
diff --git a/unittests/cfdp/handler/testReservedMsgParser.cpp b/unittests/cfdp/handler/testReservedMsgParser.cpp
new file mode 100644
index 00000000..e87dc06d
--- /dev/null
+++ b/unittests/cfdp/handler/testReservedMsgParser.cpp
@@ -0,0 +1,67 @@
+#include
+
+#include "fsfw/cfdp/CfdpMessage.h"
+#include "fsfw/cfdp/VarLenFields.h"
+#include "fsfw/cfdp/handler/PutRequest.h"
+#include "fsfw/cfdp/handler/ReservedMessageParser.h"
+#include "fsfw/cfdp/tlv/Lv.h"
+#include "fsfw/cfdp/tlv/ReservedMessageCreator.h"
+#include "fsfw/cfdp/tlv/StringLv.h"
+#include "fsfw/globalfunctions/arrayprinter.h"
+#include "fsfw/serialize.h"
+#include "mocks/MessageQueueMock.h"
+#include "mocks/StorageManagerMock.h"
+
+TEST_CASE("Reserved Message Parser", "[cfdp]") {
+ using namespace cfdp;
+ using namespace returnvalue;
+
+ std::string srcFileName = "hello.txt";
+ std::string destFileName = "hello2.txt";
+ MessageQueueId_t destQueueId = 2;
+ MessageQueueMock msgQueue(1);
+ LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}};
+ StorageManagerMock ipcStore(0, storeCfg);
+ std::array buffer{};
+ uint8_t msgBuf[32]{};
+
+ EntityId entityId(cfdp::WidthInBytes::ONE_BYTE, 5);
+ uint8_t* msgBufPtr = msgBuf;
+ size_t serLen = 0;
+ cfdp::StringLv srcName(srcFileName);
+ cfdp::StringLv destName(destFileName);
+ CHECK(entityId.serializeAsLv(&msgBufPtr, &serLen, sizeof(msgBuf)) == OK);
+ CHECK(srcName.serialize(&msgBufPtr, &serLen, sizeof(msgBuf), SerializeIF::Endianness::NETWORK) ==
+ OK);
+ CHECK(destName.serialize(&msgBufPtr, &serLen, sizeof(msgBuf), SerializeIF::Endianness::NETWORK) ==
+ OK);
+ ReservedMessageCreator creator(static_cast(ProxyOpMessageType::PUT_REQUEST), msgBuf,
+ serLen);
+ serLen = 0;
+ ReturnValue_t result = creator.serializeBe(buffer.data(), serLen, buffer.size());
+ CHECK(result == returnvalue::OK);
+ MessageToUserTlv msgToUser;
+ CHECK(msgToUser.deSerializeBe(buffer.data(), serLen, buffer.size()) == OK);
+ ReservedMessageParser parser(ipcStore, msgQueue, destQueueId);
+ REQUIRE(parser.parse(&msgToUser, 1) == OK);
+ CommandMessage msg;
+ CHECK(msgQueue.wasMessageSent());
+ CHECK(msgQueue.numberOfSentMessages() == 1);
+ CHECK(msgQueue.getNextSentMessage(destQueueId, msg) == OK);
+ store_address_t storeId = CfdpMessage::getStoreId(&msg);
+ const uint8_t* data;
+ size_t packetLen;
+ CHECK(ipcStore.getData(storeId, &data, &packetLen) == OK);
+ CHECK(packetLen > 0);
+ PutRequest putRequest;
+ size_t dummy = packetLen;
+ REQUIRE(putRequest.deSerialize(&data, &dummy, SerializeIF::Endianness::MACHINE) == OK);
+ CHECK(putRequest.getDestId().getValue() == entityId.getValue());
+ CHECK(putRequest.getDestId().getWidth() == entityId.getWidth());
+ auto& sourceNameLv = putRequest.getSourceName();
+ std::string srcNameRead = sourceNameLv.getString();
+ CHECK(srcNameRead == srcFileName);
+ auto& destNameLv = putRequest.getDestName();
+ std::string destNameRead = destNameLv.getString();
+ CHECK(destNameRead == destFileName);
+}
diff --git a/unittests/cfdp/handler/testSourceHandler.cpp b/unittests/cfdp/handler/testSourceHandler.cpp
index 570ecb08..7fbec9a1 100644
--- a/unittests/cfdp/handler/testSourceHandler.cpp
+++ b/unittests/cfdp/handler/testSourceHandler.cpp
@@ -1,3 +1,286 @@
-#include
+#include
-TEST_CASE("CFDP Source Handler", "[cfdp]") {}
\ No newline at end of file
+#include
+#include
+#include
+
+#include "fsfw/cfdp.h"
+#include "fsfw/cfdp/handler/PutRequest.h"
+#include "fsfw/cfdp/handler/SourceHandler.h"
+#include "fsfw/cfdp/pdu/EofPduCreator.h"
+#include "fsfw/cfdp/pdu/EofPduReader.h"
+#include "fsfw/cfdp/pdu/FileDataReader.h"
+#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
+#include "fsfw/cfdp/pdu/MetadataPduReader.h"
+#include "fsfw/tmtcservices/TmTcMessage.h"
+#include "fsfw/util/SeqCountProvider.h"
+#include "mocks/AcceptsTmMock.h"
+#include "mocks/EventReportingProxyMock.h"
+#include "mocks/FilesystemMock.h"
+#include "mocks/MessageQueueMock.h"
+#include "mocks/StorageManagerMock.h"
+#include "mocks/cfdp/FaultHandlerMock.h"
+#include "mocks/cfdp/RemoteConfigTableMock.h"
+#include "mocks/cfdp/UserMock.h"
+
+TEST_CASE("CFDP Source Handler", "[cfdp]") {
+ using namespace cfdp;
+ using namespace returnvalue;
+ using namespace std::filesystem;
+ const size_t MAX_FILE_SEGMENT_SIZE = 255;
+
+ MessageQueueId_t destQueueId = 2;
+ AcceptsTmMock tmReceiver(destQueueId);
+ MessageQueueMock mqMock(destQueueId);
+ EntityId localId = EntityId(UnsignedByteField(2));
+ EntityId remoteId = EntityId(UnsignedByteField(5));
+ FaultHandlerMock fhMock;
+ LocalEntityCfg localEntityCfg(localId, IndicationCfg(), fhMock);
+ FilesystemMock fsMock;
+ UserMock userMock(fsMock);
+ SeqCountProviderU16 seqCountProvider;
+ SourceHandlerParams dp(localEntityCfg, userMock, seqCountProvider);
+
+ EventReportingProxyMock eventReporterMock;
+ LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}};
+ StorageManagerMock tcStore(2, storeCfg);
+ StorageManagerMock tmStore(3, storeCfg);
+ FsfwParams fp(tmReceiver, &mqMock, &eventReporterMock);
+ fp.tcStore = &tcStore;
+ fp.tmStore = &tmStore;
+ auto sourceHandler = SourceHandler(dp, fp);
+
+ RemoteEntityCfg cfg;
+ cfg.maxFileSegmentLen = MAX_FILE_SEGMENT_SIZE;
+ cfg.remoteId = remoteId;
+ std::string srcFileName = "/tmp/cfdp-test.txt";
+ std::string destFileName = "/tmp/cfdp-test2.txt";
+ FilesystemParams srcFileNameFs(srcFileName.c_str());
+ fsMock.createFile(srcFileNameFs);
+ cfdp::StringLv srcNameLv(srcFileNameFs.path, std::strlen(srcFileNameFs.path));
+ FilesystemParams destFileNameFs(destFileName.c_str());
+ cfdp::StringLv destNameLv(destFileNameFs.path, std::strlen(destFileNameFs.path));
+ PutRequest putRequest(remoteId, srcNameLv, destNameLv);
+ CHECK(sourceHandler.initialize() == OK);
+
+ auto onePduSentCheck = [&](const SourceHandler::FsmResult& fsmResult, TmTcMessage& tmtcMessage,
+ const uint8_t** pduPtr) {
+ CHECK(fsmResult.errors == 0);
+ CHECK(fsmResult.packetsSent == 1);
+ CHECK(mqMock.numberOfSentMessages() == 1);
+ REQUIRE(mqMock.getNextSentMessage(destQueueId, tmtcMessage) == OK);
+ auto accessor = tmStore.getData(tmtcMessage.getStorageId());
+ REQUIRE(accessor.first == OK);
+ *pduPtr = accessor.second.data();
+ return std::move(accessor);
+ };
+ auto genericMetadataCheck = [&](const SourceHandler::FsmResult& fsmResult,
+ size_t expectedFileSize, uint16_t expectedSeqNum) {
+ CHECK(fsmResult.errors == 0);
+ CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
+ TmTcMessage tmtcMessage;
+ const uint8_t* pduPtr;
+ auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
+ CHECK(accessor.second.size() == 55);
+ MetadataGenericInfo metadataInfo;
+ MetadataPduReader metadataReader(pduPtr, accessor.second.size(), metadataInfo, nullptr, 0);
+ REQUIRE(metadataReader.parseData() == OK);
+ std::string srcNameRead = metadataReader.getSourceFileName().getString();
+ CHECK(srcNameRead == srcFileName);
+ TransactionSeqNum seqNum;
+ metadataReader.getTransactionSeqNum(seqNum);
+ CHECK(seqNum.getValue() == expectedSeqNum);
+ CHECK(userMock.transactionIndicRecvd.size() == 1);
+ CHECK(userMock.transactionIndicRecvd.back() == TransactionId(localId, seqNum));
+ EntityId srcId;
+ metadataReader.getSourceId(srcId);
+ EntityId destId;
+ metadataReader.getDestId(destId);
+ CHECK(srcId.getValue() == localId.getValue());
+ CHECK(destId.getValue() == remoteId.getValue());
+ std::string destNameRead = metadataReader.getDestFileName().getString();
+ CHECK(destNameRead == destFileName);
+ if (expectedFileSize == 0) {
+ CHECK(metadataInfo.getChecksumType() == ChecksumType::NULL_CHECKSUM);
+ } else {
+ CHECK(metadataInfo.getChecksumType() == ChecksumType::CRC_32);
+ }
+ CHECK(metadataInfo.getFileSize().value() == expectedFileSize);
+ CHECK(!metadataInfo.isClosureRequested());
+ mqMock.clearMessages();
+ };
+ auto genericEofCheck = [&](const SourceHandler::FsmResult& fsmResult, size_t expectedFileSize,
+ uint32_t expectedChecksum, uint16_t expectedSeqNum) {
+ CHECK(fsmResult.errors == 0);
+ CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
+ TmTcMessage tmtcMessage;
+ const uint8_t* pduPtr;
+ auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
+ // 10 byte PDU header, 1 byte directive field, 1 byte condition code, 4 byte checksum,
+ // 4 byte FSS
+ CHECK(accessor.second.size() == 20);
+ EofInfo eofInfo;
+ EofPduReader eofReader(pduPtr, accessor.second.size(), eofInfo);
+ REQUIRE(eofReader.parseData() == OK);
+ TransactionSeqNum seqNum;
+ eofReader.getTransactionSeqNum(seqNum);
+ CHECK(seqNum.getValue() == expectedSeqNum);
+ auto transactionId = TransactionId(localId, seqNum);
+ CHECK(userMock.eofSentRecvd.size() == 1);
+ CHECK(userMock.eofSentRecvd.back() == transactionId);
+ CHECK(eofInfo.getChecksum() == expectedChecksum);
+ CHECK(eofInfo.getConditionCode() == ConditionCode::NO_ERROR);
+ CHECK(eofInfo.getFileSize().value() == expectedFileSize);
+ };
+ auto genericNoticeOfCompletionCheck = [&](const SourceHandler::FsmResult& fsmResult,
+ uint16_t expectedSeqNum) {
+ CHECK(fsmResult.callStatus == CallStatus::DONE);
+ CHECK(userMock.finishedRecvd.size() == 1);
+ CHECK(userMock.finishedRecvd.back().first ==
+ TransactionId(localId, TransactionSeqNum(cfdp::WidthInBytes::TWO_BYTES, expectedSeqNum)));
+ CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
+ CHECK(sourceHandler.getState() == CfdpState::IDLE);
+ };
+
+ SECTION("Test Basic") {
+ CHECK(sourceHandler.getState() == CfdpState::IDLE);
+ CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
+ }
+
+ SECTION("Transfer empty file") {
+ CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
+
+ size_t expectedFileSize = 0;
+ const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
+ // Verify metadata PDU was sent.
+ genericMetadataCheck(fsmResult, expectedFileSize, 0);
+
+ sourceHandler.stateMachine();
+ // Verify EOF PDU was sent. No file data PDU is sent for an empty file and the checksum is 0.
+ genericEofCheck(fsmResult, expectedFileSize, 0, 0);
+
+ // Verify notice of completion.
+ sourceHandler.stateMachine();
+ genericNoticeOfCompletionCheck(fsmResult, 0);
+ }
+
+ SECTION("Transfer small file") {
+ uint16_t expectedSeqNum = 0;
+ fsMock.createFile(srcFileNameFs);
+ std::string fileContent = "hello world\n";
+ size_t expectedFileSize = fileContent.size();
+ FileOpParams params(srcFileName.c_str(), expectedFileSize);
+ fsMock.writeToFile(params, reinterpret_cast(fileContent.data()));
+ CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
+ const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
+
+ // Verify metadata PDU was sent.
+ genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum);
+
+ // Verify that a small file data PDU was sent.
+ sourceHandler.stateMachine();
+ TmTcMessage tmtcMessage;
+ const uint8_t* pduPtr;
+ auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
+ FileDataInfo fdInfo;
+ FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
+ // 10 byte PDU header, 4 byte offset, 12 bytes file data.
+ CHECK(accessor.second.size() == 26);
+ CHECK(fdReader.parseData() == OK);
+ CHECK(fdInfo.getOffset().value() == 0);
+ size_t fileSize = 0;
+ const uint8_t* fileData = fdInfo.getFileData(&fileSize);
+ REQUIRE(fileSize == fileContent.size());
+ CHECK(fileData != nullptr);
+ std::string dataReadBack(reinterpret_cast(fileData), fileSize);
+ CHECK(dataReadBack == fileContent);
+ mqMock.clearMessages();
+
+ sourceHandler.stateMachine();
+
+ etl::crc32 crcCalc;
+ crcCalc.add(fileContent.data(), fileContent.data() + fileContent.size());
+ // Verify EOF PDU was sent.
+ genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum);
+
+ // Verify notice of completion.
+ sourceHandler.stateMachine();
+ genericNoticeOfCompletionCheck(fsmResult, expectedSeqNum);
+ }
+
+ SECTION("Transfer two segment file") {
+ uint16_t expectedSeqNum = 0;
+ // Create 400 bytes of random data. This should result in two file segments, with one
+ // having the maximum size.
+ std::random_device dev;
+ std::mt19937 rng(dev());
+ std::uniform_int_distribution distU8(0, 255);
+ std::array largerFileData{};
+ for (auto& val : largerFileData) {
+ val = distU8(rng);
+ }
+ size_t expectedFileSize = largerFileData.size();
+ fsMock.createFile(srcFileNameFs);
+ FileOpParams params(srcFileName.c_str(), expectedFileSize);
+ fsMock.writeToFile(params, reinterpret_cast(largerFileData.data()));
+ CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
+ const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
+ // Verify metadata PDU was sent.
+ genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum);
+
+ // Check first file data PDU. It should have the maximum file segment size.
+ sourceHandler.stateMachine();
+ TmTcMessage tmtcMessage;
+ const uint8_t* pduPtr;
+ FileDataInfo fdInfo;
+ {
+ CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
+ auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
+ FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
+ // 10 byte PDU header, 4 byte offset, 255 byte file data
+ CHECK(accessor.second.size() == 269);
+ CHECK(fdReader.parseData() == OK);
+ CHECK(fdInfo.getOffset().value() == 0);
+ size_t fileSize = 0;
+ const uint8_t* fileData = fdInfo.getFileData(&fileSize);
+ // Maximum file segment size.
+ REQUIRE(fileSize == MAX_FILE_SEGMENT_SIZE);
+ for (unsigned i = 0; i < fileSize; i++) {
+ CHECK(fileData[i] == largerFileData[i]);
+ }
+ }
+ mqMock.clearMessages();
+
+ // Check second file data PDU.
+ sourceHandler.stateMachine();
+ {
+ CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
+ auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
+ FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
+ // 10 byte PDU header, 4 byte offset, remaining file data (400 - 255 == 145).
+ CHECK(accessor.second.size() == 10 + 4 + largerFileData.size() - MAX_FILE_SEGMENT_SIZE);
+ CHECK(fdReader.parseData() == OK);
+ CHECK(fdInfo.getOffset().value() == MAX_FILE_SEGMENT_SIZE);
+ size_t fileDataSize = 0;
+ const uint8_t* fileData = fdInfo.getFileData(&fileDataSize);
+ // Maximum file segment size.
+ REQUIRE(fileDataSize == largerFileData.size() - MAX_FILE_SEGMENT_SIZE);
+ for (unsigned i = 0; i < fileDataSize; i++) {
+ CHECK(fileData[i] == largerFileData[MAX_FILE_SEGMENT_SIZE + i]);
+ }
+ }
+ mqMock.clearMessages();
+
+ // Check EOF and verify checksum.
+ sourceHandler.stateMachine();
+
+ etl::crc32 crcCalc;
+ crcCalc.add(largerFileData.data(), largerFileData.data() + largerFileData.size());
+ // Verify EOF PDU was sent.
+ genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum);
+
+ // Verify notice of completion.
+ sourceHandler.stateMachine();
+ genericNoticeOfCompletionCheck(fsmResult, expectedSeqNum);
+ }
+}
\ No newline at end of file
diff --git a/unittests/cfdp/pdu/testCfdpHeader.cpp b/unittests/cfdp/pdu/testCfdpHeader.cpp
index 1fc7dfd4..447e3722 100644
--- a/unittests/cfdp/pdu/testCfdpHeader.cpp
+++ b/unittests/cfdp/pdu/testCfdpHeader.cpp
@@ -110,9 +110,9 @@ TEST_CASE("CFDP Header", "[cfdp]") {
}
SECTION("Other variable sized fields") {
- pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
- pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
- pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
+ pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
+ pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
+ pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
REQUIRE(pduConf.sourceId.getSerializedSize() == 4);
REQUIRE(creator.getSerializedSize() == 14);
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
@@ -146,9 +146,9 @@ TEST_CASE("CFDP Header", "[cfdp]") {
}
SECTION("Buffer Too Short") {
- pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
- pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
- pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
+ pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
+ pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
+ pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
for (uint8_t idx = 0; idx < 14; idx++) {
REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) ==
SerializeIF::BUFFER_TOO_SHORT);
@@ -157,11 +157,11 @@ TEST_CASE("CFDP Header", "[cfdp]") {
}
SECTION("Invalid Variable Sized Fields") {
- result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
+ result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
REQUIRE(result == returnvalue::FAILED);
- result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
+ result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
REQUIRE(result == returnvalue::FAILED);
- result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
+ result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
REQUIRE(result == returnvalue::FAILED);
}
@@ -207,7 +207,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
SerializeIF::Endianness::MACHINE);
REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0);
- pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 1);
+ pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 1);
serTarget = serBuf.data();
serSize = 1;
result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE);
@@ -257,11 +257,11 @@ TEST_CASE("CFDP Header", "[cfdp]") {
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
creator.setPduType(cfdp::PduType::FILE_DATA);
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
- result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
+ result = pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
REQUIRE(result == returnvalue::OK);
- result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
+ result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
REQUIRE(result == returnvalue::OK);
- result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
+ result = pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
REQUIRE(result == returnvalue::OK);
serTarget = serBuf.data();
serSize = 0;
@@ -302,8 +302,8 @@ TEST_CASE("CFDP Header", "[cfdp]") {
SECTION("Manipulate Source Dest ID") {
serTarget = serBuf.data();
serSize = 0;
- pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22);
- pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48);
+ pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 22);
+ pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 48);
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
reader.getSourceId(sourceDestId);
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
diff --git a/unittests/cfdp/pdu/testEofPdu.cpp b/unittests/cfdp/pdu/testEofPdu.cpp
index 83e61780..0eb0342b 100644
--- a/unittests/cfdp/pdu/testEofPdu.cpp
+++ b/unittests/cfdp/pdu/testEofPdu.cpp
@@ -14,7 +14,7 @@ TEST_CASE("EOF PDU", "[cfdp][pdu]") {
size_t sz = 0;
EntityId destId(WidthInBytes::TWO_BYTES, 2);
EntityIdTlv faultLoc(destId);
- FileSize fileSize(12);
+ Fss fileSize(12);
// We can already set the fault location, it will be ignored
EofInfo eofInfo(cfdp::ConditionCode::NO_ERROR, 5, fileSize, &faultLoc);
TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15);
diff --git a/unittests/cfdp/pdu/testFileData.cpp b/unittests/cfdp/pdu/testFileData.cpp
index 39139378..80b02603 100644
--- a/unittests/cfdp/pdu/testFileData.cpp
+++ b/unittests/cfdp/pdu/testFileData.cpp
@@ -22,7 +22,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") {
for (uint8_t idx = 0; idx < 10; idx++) {
fileBuffer[idx] = idx;
}
- FileSize offset(50);
+ Fss offset(50);
FileDataInfo info(offset, fileBuffer.data(), 10);
SECTION("Serialization") {
@@ -107,8 +107,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") {
serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK);
REQUIRE(result == returnvalue::OK);
- FileSize emptyOffset;
- FileDataInfo emptyInfo(emptyOffset);
+ FileDataInfo emptyInfo;
FileDataReader deserializer(fileDataBuffer.data(), fileDataBuffer.size(), emptyInfo);
result = deserializer.parseData();
REQUIRE(result == returnvalue::OK);
diff --git a/unittests/cfdp/pdu/testKeepAlivePdu.cpp b/unittests/cfdp/pdu/testKeepAlivePdu.cpp
index d07bccae..f8eeda42 100644
--- a/unittests/cfdp/pdu/testKeepAlivePdu.cpp
+++ b/unittests/cfdp/pdu/testKeepAlivePdu.cpp
@@ -16,7 +16,7 @@ TEST_CASE("Keep Alive PDU", "[cfdp][pdu]") {
EntityId sourceId(WidthInBytes::TWO_BYTES, 1);
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
- FileSize progress(0x50);
+ Fss progress(0x50);
SECTION("Serialize") {
KeepAlivePduCreator serializer(pduConf, progress);
diff --git a/unittests/cfdp/pdu/testMetadataPdu.cpp b/unittests/cfdp/pdu/testMetadataPdu.cpp
index a9f8bf86..e13b4717 100644
--- a/unittests/cfdp/pdu/testMetadataPdu.cpp
+++ b/unittests/cfdp/pdu/testMetadataPdu.cpp
@@ -6,11 +6,10 @@
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
-#include "fsfw/globalfunctions/arrayprinter.h"
TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
using namespace cfdp;
- ReturnValue_t result = returnvalue::OK;
+ ReturnValue_t result;
std::array mdBuffer = {};
uint8_t* buffer = mdBuffer.data();
size_t sz = 0;
@@ -22,30 +21,22 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
std::string firstFileName = "hello.txt";
cfdp::StringLv sourceFileName(firstFileName);
cfdp::StringLv destFileName;
- FileSize fileSize(35);
- MetadataInfo info(false, ChecksumType::MODULAR, fileSize, sourceFileName, destFileName);
+ Fss fileSize(35);
+ MetadataGenericInfo info(false, ChecksumType::MODULAR, fileSize);
FilestoreResponseTlv response(FilestoreActionCode::CREATE_DIRECTORY, FSR_CREATE_NOT_ALLOWED,
sourceFileName, nullptr);
std::array msg = {0x41, 0x42, 0x43};
cfdp::Tlv responseTlv;
std::array responseBuf = {};
- uint8_t* responseBufPtr = responseBuf.data();
response.convertToTlv(responseTlv, buffer, responseBuf.size(), SerializeIF::Endianness::MACHINE);
MessageToUserTlv msgToUser(msg.data(), msg.size());
std::array options{&responseTlv, &msgToUser};
+ std::array tlvDeser{};
REQUIRE(options[0]->getSerializedSize() == 2 + 1 + 10 + 1);
REQUIRE(options[1]->getSerializedSize() == 5);
- SECTION("Serialize") {
- MetadataPduCreator serializer(pduConf, info);
- result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
- REQUIRE(result == returnvalue::OK);
- REQUIRE(serializer.getWholePduSize() == 27);
- REQUIRE(info.getSourceFileName().getSerializedSize() == 10);
- REQUIRE(info.getDestFileName().getSerializedSize() == 1);
- REQUIRE(info.getSerializedSize() == 16);
- REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 17);
+ auto metadataCheckPartOne = [&]() {
REQUIRE(mdBuffer[10] == FileDirective::METADATA);
// no closure requested and checksum type is modular => 0x00
REQUIRE(mdBuffer[11] == 0x00);
@@ -64,20 +55,59 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
REQUIRE(mdBuffer[23] == 't');
REQUIRE(mdBuffer[24] == 'x');
REQUIRE(mdBuffer[25] == 't');
- REQUIRE(mdBuffer[26] == 0);
+ };
+ SECTION("Serialize with empty dest name") {
+ MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, nullptr, 0);
+ result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
+ REQUIRE(result == returnvalue::OK);
+ CHECK(sz == serializer.getSerializedSize());
+ // 10 byte heater + 1 byte PDU directive field + 1 byte PDU content + FSS field (4) + source
+ // name field (10) + dest name field (1).
+ REQUIRE(serializer.getWholePduSize() == 27);
+ REQUIRE(serializer.getSourceFileName().getSerializedSize() == 10);
+ REQUIRE(serializer.getDestFileName().getSerializedSize() == 1);
+ REQUIRE(info.getSerializedSize() == 5);
+ REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 17);
+ REQUIRE(serializer.getSerializedSize() == serializer.getWholePduSize());
+ metadataCheckPartOne();
+ REQUIRE(mdBuffer[26] == 0);
+ }
+
+ SECTION("Serialize with dest name") {
+ std::string secondFileName = "hello2.txt";
+ cfdp::StringLv destFileName2(secondFileName);
+ MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName2, nullptr, 0);
+ result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
+ REQUIRE(result == returnvalue::OK);
+ // 10 byte heater + 1 byte PDU directive field + 1 byte PDU content + FSS field (4) + source
+ // name field (10) + dest name field (11).
+ REQUIRE(serializer.getWholePduSize() == 37);
+ CHECK(sz == serializer.getSerializedSize());
+ REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 27);
+ REQUIRE(serializer.getSerializedSize() == serializer.getWholePduSize());
+ metadataCheckPartOne();
+ // Size of destination name field
+ REQUIRE(mdBuffer[26] == 10);
+ REQUIRE(mdBuffer[27] == 'h');
+ REQUIRE(mdBuffer[28] == 'e');
+ REQUIRE(mdBuffer[29] == 'l');
+ REQUIRE(mdBuffer[30] == 'l');
+ REQUIRE(mdBuffer[31] == 'o');
+ REQUIRE(mdBuffer[32] == '2');
+ REQUIRE(mdBuffer[33] == '.');
+ REQUIRE(mdBuffer[34] == 't');
+ REQUIRE(mdBuffer[35] == 'x');
+ REQUIRE(mdBuffer[36] == 't');
+ }
+
+ SECTION("Serialize with 2 options") {
std::string otherFileName = "hello2.txt";
cfdp::StringLv otherFileNameLv(otherFileName.data(), otherFileName.size());
- info.setSourceFileName(otherFileNameLv);
- size_t sizeOfOptions = options.size();
- info.setOptionsArray(options.data(), sizeOfOptions, sizeOfOptions);
- REQUIRE(info.getMaxOptionsLen() == 2);
- info.setMaxOptionsLen(3);
- REQUIRE(info.getMaxOptionsLen() == 3);
+ MetadataPduCreator serializer(pduConf, info, otherFileNameLv, destFileName, options.data(),
+ options.size());
info.setChecksumType(cfdp::ChecksumType::CRC_32C);
info.setClosureRequested(true);
- uint8_t* buffer = mdBuffer.data();
- size_t sz = 0;
serializer.updateDirectiveFieldLen();
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
@@ -98,49 +128,47 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
// TLV unittests
REQUIRE(sz == 10 + 37);
for (size_t maxSz = 0; maxSz < sz; maxSz++) {
- uint8_t* buffer = mdBuffer.data();
- size_t sz = 0;
+ buffer = mdBuffer.data();
+ sz = 0;
result = serializer.serialize(&buffer, &sz, maxSz, SerializeIF::Endianness::NETWORK);
REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT);
}
for (size_t initSz = 1; initSz < 47; initSz++) {
- uint8_t* buffer = mdBuffer.data();
- size_t sz = initSz;
+ buffer = mdBuffer.data();
+ sz = initSz;
result = serializer.serialize(&buffer, &sz, 46, SerializeIF::Endianness::NETWORK);
REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT);
}
- info.setDestFileName(destFileName);
}
SECTION("Deserialize") {
- MetadataPduCreator serializer(pduConf, info);
+ MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, nullptr, 0);
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
REQUIRE(result == returnvalue::OK);
- MetadataPduReader deserializer(mdBuffer.data(), mdBuffer.size(), info);
+ MetadataPduReader deserializer(mdBuffer.data(), mdBuffer.size(), info, nullptr, 0);
result = deserializer.parseData();
REQUIRE(result == returnvalue::OK);
size_t fullSize = deserializer.getWholePduSize();
for (size_t maxSz = 0; maxSz < fullSize; maxSz++) {
- MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info);
+ MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info, nullptr, 0);
result = invalidSzDeser.parseData();
REQUIRE(result != returnvalue::OK);
}
- size_t sizeOfOptions = options.size();
- size_t maxSize = 4;
- info.setOptionsArray(options.data(), sizeOfOptions, maxSize);
- REQUIRE(info.getOptionsLen() == 2);
+ }
+
+ SECTION("Deserialize with 2 options") {
+ MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, options.data(),
+ options.size());
info.setChecksumType(cfdp::ChecksumType::CRC_32C);
info.setClosureRequested(true);
- uint8_t* buffer = mdBuffer.data();
- size_t sz = 0;
serializer.updateDirectiveFieldLen();
- info.setSourceFileName(sourceFileName);
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
REQUIRE(result == returnvalue::OK);
- MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info);
+ MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info, tlvDeser.data(),
+ tlvDeser.max_size());
result = deserializer2.parseData();
REQUIRE(result == returnvalue::OK);
REQUIRE(options[0]->getType() == cfdp::TlvType::FILESTORE_RESPONSE);
@@ -151,12 +179,15 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
for (size_t invalidFieldLen = 0; invalidFieldLen < 36; invalidFieldLen++) {
mdBuffer[1] = (invalidFieldLen >> 8) & 0xff;
mdBuffer[2] = invalidFieldLen & 0xff;
+ if (invalidFieldLen == 17) {
+ volatile uint32_t dummy = 0;
+ }
result = deserializer2.parseData();
if (invalidFieldLen == 17) {
- REQUIRE(info.getOptionsLen() == 0);
+ REQUIRE(deserializer2.getNumberOfParsedOptions() == 0);
}
if (invalidFieldLen == 31) {
- REQUIRE(info.getOptionsLen() == 1);
+ REQUIRE(deserializer2.getNumberOfParsedOptions() == 1);
}
// This is the precise length where there are no options or one option
if (invalidFieldLen != 17 and invalidFieldLen != 31) {
@@ -165,11 +196,25 @@ TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
}
mdBuffer[1] = (36 >> 8) & 0xff;
mdBuffer[2] = 36 & 0xff;
- info.setOptionsArray(nullptr, std::nullopt, std::nullopt);
+ }
+
+ SECTION("Can not parse options") {
+ MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, options.data(),
+ options.size());
+ info.setChecksumType(cfdp::ChecksumType::CRC_32C);
+ info.setClosureRequested(true);
+ buffer = mdBuffer.data();
+ sz = 0;
+ serializer.updateDirectiveFieldLen();
+
+ // info.setSourceFileName(sourceFileName);
+ result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
+ REQUIRE(result == returnvalue::OK);
+
+ MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info, nullptr, 0);
REQUIRE(deserializer2.parseData() == cfdp::METADATA_CANT_PARSE_OPTIONS);
- info.setOptionsArray(options.data(), sizeOfOptions, std::nullopt);
for (size_t maxSz = 0; maxSz < 46; maxSz++) {
- MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info);
+ MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info, nullptr, 0);
if (not invalidSzDeser.isNull()) {
result = invalidSzDeser.parseData();
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
diff --git a/unittests/cfdp/pdu/testNakPdu.cpp b/unittests/cfdp/pdu/testNakPdu.cpp
index 7974dab1..c3650c63 100644
--- a/unittests/cfdp/pdu/testNakPdu.cpp
+++ b/unittests/cfdp/pdu/testNakPdu.cpp
@@ -17,8 +17,8 @@ TEST_CASE("NAK PDU", "[cfdp][pdu]") {
EntityId sourceId(WidthInBytes::TWO_BYTES, 1);
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
- FileSize startOfScope(50);
- FileSize endOfScope(1050);
+ Fss startOfScope(50);
+ Fss endOfScope(1050);
NakInfo info(startOfScope, endOfScope);
SECTION("Serializer") {
NakPduCreator serializer(pduConf, info);
@@ -40,8 +40,8 @@ TEST_CASE("NAK PDU", "[cfdp][pdu]") {
REQUIRE(result == returnvalue::OK);
REQUIRE(scope == 1050);
- NakInfo::SegmentRequest segReq0(cfdp::FileSize(2020), cfdp::FileSize(2520));
- NakInfo::SegmentRequest segReq1(cfdp::FileSize(2932), cfdp::FileSize(3021));
+ NakInfo::SegmentRequest segReq0(cfdp::Fss(2020), cfdp::Fss(2520));
+ NakInfo::SegmentRequest segReq1(cfdp::Fss(2932), cfdp::Fss(3021));
// Now add 2 segment requests to NAK info and serialize them as well
std::array segReqs = {segReq0, segReq1};
size_t segReqsLen = segReqs.size();
@@ -100,8 +100,8 @@ TEST_CASE("NAK PDU", "[cfdp][pdu]") {
REQUIRE(info.getStartOfScope().getSize() == 50);
REQUIRE(info.getEndOfScope().getSize() == 1050);
- NakInfo::SegmentRequest segReq0(cfdp::FileSize(2020), cfdp::FileSize(2520));
- NakInfo::SegmentRequest segReq1(cfdp::FileSize(2932), cfdp::FileSize(3021));
+ NakInfo::SegmentRequest segReq0(cfdp::Fss(2020), cfdp::Fss(2520));
+ NakInfo::SegmentRequest segReq1(cfdp::Fss(2932), cfdp::Fss(3021));
// Now add 2 segment requests to NAK info and serialize them as well
std::array segReqs = {segReq0, segReq1};
size_t segReqsLen = segReqs.size();
diff --git a/unittests/cfdp/testCfdp.cpp b/unittests/cfdp/testCfdp.cpp
index 467b5b2d..60b14b77 100644
--- a/unittests/cfdp/testCfdp.cpp
+++ b/unittests/cfdp/testCfdp.cpp
@@ -2,7 +2,7 @@
#include
#include
-#include "fsfw/cfdp/FileSize.h"
+#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
#include "fsfw/globalfunctions/arrayprinter.h"
@@ -79,7 +79,7 @@ TEST_CASE("CFDP Base", "[cfdp]") {
std::array fssBuf = {};
uint8_t* buffer = fssBuf.data();
size_t size = 0;
- cfdp::FileSize fss;
+ cfdp::Fss fss;
REQUIRE(fss.getSize() == 0);
fss.setFileSize(0x20, false);
result = fss.serialize(&buffer, &size, fssBuf.size(), SerializeIF::Endianness::MACHINE);
diff --git a/unittests/cfdp/testLvs.cpp b/unittests/cfdp/testLvs.cpp
index 22094568..8415f0d8 100644
--- a/unittests/cfdp/testLvs.cpp
+++ b/unittests/cfdp/testLvs.cpp
@@ -23,12 +23,6 @@ TEST_CASE("CFDP LV", "[cfdp][lv]") {
auto lv = cfdp::Lv(lvRawBuf.data(), 2);
REQUIRE(lv.getSerializedSize() == 3);
- SECTION("Copy") {
- auto lvCopy = cfdp::Lv(lv);
- REQUIRE(lvCopy.getSerializedSize() == 3);
- REQUIRE(lv.getValue(nullptr) == lvCopy.getValue(nullptr));
- }
-
serPtr = rawBuf.data();
deserSize = 0;
REQUIRE(lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK) ==
@@ -41,6 +35,16 @@ TEST_CASE("CFDP LV", "[cfdp][lv]") {
REQUIRE(sourceIdRaw == 0x0ff0);
}
+ SECTION("Move LV") {
+ std::array lvRawBuf{};
+ serPtr = lvRawBuf.data();
+ REQUIRE(sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(),
+ SerializeIF::Endianness::NETWORK) == returnvalue::OK);
+ auto lv = cfdp::Lv(lvRawBuf.data(), 2);
+ auto lvMovedCopy = cfdp::Lv(std::move(lv));
+ REQUIRE(lvMovedCopy.getSerializedSize() == 3);
+ }
+
SECTION("Empty Serialization") {
auto lvEmpty = Lv();
REQUIRE(lvEmpty.getSerializedSize() == 1);
diff --git a/unittests/cfdp/testReservedMsgCreator.cpp b/unittests/cfdp/testReservedMsgCreator.cpp
new file mode 100644
index 00000000..1873becf
--- /dev/null
+++ b/unittests/cfdp/testReservedMsgCreator.cpp
@@ -0,0 +1,49 @@
+#include
+#include
+
+#include "fsfw/cfdp/VarLenFields.h"
+#include "fsfw/cfdp/tlv/ReservedMessageCreator.h"
+#include "fsfw/cfdp/tlv/StringLv.h"
+
+TEST_CASE("Reserved Message Creator", "[cfdp][tlv]") {
+ using namespace cfdp;
+ using namespace returnvalue;
+
+ std::string srcFileName = "hello.txt";
+ std::string destFileName = "hello2.txt";
+ std::array buffer{};
+ uint8_t msgBuf[32]{};
+ EntityId entityId(cfdp::WidthInBytes::ONE_BYTE, 5);
+ uint8_t* msgBufPtr = msgBuf;
+ size_t serLen = 0;
+ cfdp::StringLv srcName(srcFileName);
+ cfdp::StringLv destName(destFileName);
+ CHECK(entityId.serializeAsLv(&msgBufPtr, &serLen, sizeof(msgBuf)) == OK);
+ CHECK(srcName.serialize(&msgBufPtr, &serLen, sizeof(msgBuf), SerializeIF::Endianness::NETWORK) ==
+ OK);
+ CHECK(destName.serialize(&msgBufPtr, &serLen, sizeof(msgBuf), SerializeIF::Endianness::NETWORK) ==
+ OK);
+ ReservedMessageCreator creator(static_cast(ProxyOpMessageType::PUT_REQUEST), msgBuf,
+ serLen);
+ serLen = 0;
+ ReturnValue_t result = creator.serializeBe(buffer.data(), serLen, buffer.size());
+ CHECK(result == returnvalue::OK);
+ CHECK(buffer[0] == TlvType::MSG_TO_USER);
+ // 4 bytes "cfdp" header, 1 byte message type, entity ID LV, source name LV and dest name LV
+ CHECK(buffer[1] ==
+ 5 + 1 + entityId.getSerializedSize() + 1 + srcFileName.size() + 1 + destFileName.size());
+ CHECK(buffer[2] == 'c');
+ CHECK(buffer[3] == 'f');
+ CHECK(buffer[4] == 'd');
+ CHECK(buffer[5] == 'p');
+ CHECK(buffer[6] == static_cast(ProxyOpMessageType::PUT_REQUEST));
+ CHECK(buffer[7] == 1);
+ CHECK(buffer[8] == entityId.getValue());
+ CHECK(buffer[9] == srcFileName.size());
+ size_t currentIdx = 10;
+ CHECK(std::string(reinterpret_cast(buffer.data()) + currentIdx,
+ srcFileName.size()) == srcFileName);
+ currentIdx += srcFileName.size() + 1;
+ CHECK(std::string(reinterpret_cast(buffer.data()) + currentIdx,
+ destFileName.size()) == destFileName);
+}
diff --git a/unittests/cfdp/testTlv.cpp b/unittests/cfdp/testTlv.cpp
index 979bfac5..020365f8 100644
--- a/unittests/cfdp/testTlv.cpp
+++ b/unittests/cfdp/testTlv.cpp
@@ -40,7 +40,7 @@ TEST_CASE("CFDP TLV", "[cfdp][tlv]") {
SECTION("TLV Other Value") {
auto tlv = Tlv(TlvType::ENTITY_ID, rawBuf.data(), deserSize);
// Set new value
- sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12);
+ sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 12);
REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(),
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
tlv.setValue(rawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES);
diff --git a/unittests/datapoollocal/testLocalPoolManager.cpp b/unittests/datapoollocal/testLocalPoolManager.cpp
index f65083e2..31d2f876 100644
--- a/unittests/datapoollocal/testLocalPoolManager.cpp
+++ b/unittests/datapoollocal/testLocalPoolManager.cpp
@@ -82,7 +82,7 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == returnvalue::OK);
CHECK(messageSent.getCommand() ==
static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
- REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == returnvalue::OK);
+ REQUIRE(poolOwnerMock.getNextSentMessageToDefaultDest(messageSent) == returnvalue::OK);
CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT));
/* Clear message to avoid memory leak, our mock won't do it for us (yet) */
CommandMessageCleaner::clearCommandMessage(&messageSent);
@@ -259,11 +259,11 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
CHECK(messageSent.getCommand() ==
static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(poolOwnerMock.clearLastSentMessage(subscriberId) == returnvalue::OK);
- REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == returnvalue::OK);
+ REQUIRE(poolOwnerMock.getNextSentMessageToDefaultDest(messageSent) == returnvalue::OK);
CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT));
REQUIRE(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == MessageQueueIF::EMPTY);
- REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == MessageQueueIF::EMPTY);
+ REQUIRE(poolOwnerMock.getNextSentMessageToDefaultDest(messageSent) == MessageQueueIF::EMPTY);
}
SECTION("PeriodicHKAndMessaging") {
diff --git a/unittests/mocks/AcceptsTmMock.h b/unittests/mocks/AcceptsTmMock.h
index b12e1094..c736c952 100644
--- a/unittests/mocks/AcceptsTmMock.h
+++ b/unittests/mocks/AcceptsTmMock.h
@@ -9,8 +9,8 @@ class AcceptsTmMock : public SystemObject, public AcceptsTelemetryIF {
AcceptsTmMock(object_id_t registeredId, MessageQueueId_t queueToReturn);
explicit AcceptsTmMock(MessageQueueId_t queueToReturn);
- MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
- const char* getName() const override;
+ [[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
+ [[nodiscard]] const char* getName() const override;
MessageQueueId_t returnedQueue;
};
diff --git a/unittests/mocks/FilesystemMock.cpp b/unittests/mocks/FilesystemMock.cpp
index 24850227..51c0c686 100644
--- a/unittests/mocks/FilesystemMock.cpp
+++ b/unittests/mocks/FilesystemMock.cpp
@@ -39,7 +39,8 @@ ReturnValue_t FilesystemMock::readFromFile(FileOpParams params, uint8_t **buffer
if (readSize + readLen > maxSize) {
return SerializeIF::STREAM_TOO_SHORT;
}
- std::copy(info.fileRaw.data() + params.offset, info.fileRaw.data() + readLen, *buffer);
+ std::copy(info.fileRaw.data() + params.offset, info.fileRaw.data() + params.offset + readLen,
+ *buffer);
*buffer += readLen;
readSize += readLen;
}
@@ -80,7 +81,7 @@ ReturnValue_t FilesystemMock::removeDirectory(FilesystemParams params, bool dele
ReturnValue_t FilesystemMock::rename(const char *oldPath, const char *newPath,
FileSystemArgsIF *args) {
- renameQueue.push(RenameInfo(oldPath, newPath));
+ renameQueue.emplace(oldPath, newPath);
return returnvalue::OK;
}
@@ -90,7 +91,7 @@ void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data)
if (iter == fileMap.end()) {
FileSegmentQueue queue;
if (params.size > 0) {
- queue.push(FileWriteInfo(filename, params.offset, data, params.size));
+ queue.emplace(filename, params.offset, data, params.size);
}
FileInfo info;
info.fileSegQueue = queue;
@@ -100,7 +101,7 @@ void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data)
fileMap.emplace(filename, info);
} else {
FileInfo &info = iter->second;
- info.fileSegQueue.push(FileWriteInfo(filename, params.offset, data, params.size));
+ info.fileSegQueue.emplace(filename, params.offset, data, params.size);
if (data == nullptr) {
return;
}
@@ -145,3 +146,13 @@ ReturnValue_t FilesystemMock::getBaseFilename(FilesystemParams params, char *nam
}
bool FilesystemMock::isDirectory(const char *path) { return false; }
+
+bool FilesystemMock::getFileSize(FilesystemParams params, size_t &fileSize) {
+ std::string filename(params.path);
+ auto iter = fileMap.find(filename);
+ if (iter != fileMap.end()) {
+ fileSize = iter->second.fileRaw.size();
+ return true;
+ }
+ return false;
+}
diff --git a/unittests/mocks/FilesystemMock.h b/unittests/mocks/FilesystemMock.h
index 2ddbefc3..b24d5c4c 100644
--- a/unittests/mocks/FilesystemMock.h
+++ b/unittests/mocks/FilesystemMock.h
@@ -62,6 +62,7 @@ class FilesystemMock : public HasFileSystemIF {
bool isDirectory(const char *path) override;
bool fileExists(FilesystemParams params) override;
ReturnValue_t truncateFile(FilesystemParams params) override;
+ bool getFileSize(FilesystemParams params, size_t &fileSize) override;
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;
ReturnValue_t readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
diff --git a/unittests/mocks/MessageQueueMock.cpp b/unittests/mocks/MessageQueueMock.cpp
index cac5a0d9..96a6ee86 100644
--- a/unittests/mocks/MessageQueueMock.cpp
+++ b/unittests/mocks/MessageQueueMock.cpp
@@ -124,7 +124,7 @@ ReturnValue_t MessageQueueMock::getNextSentMessage(MessageQueueId_t id,
return returnvalue::OK;
}
-ReturnValue_t MessageQueueMock::getNextSentMessage(MessageQueueMessageIF& message) {
+ReturnValue_t MessageQueueMock::getNextSentMessageToDefaultDest(MessageQueueMessageIF& message) {
return getNextSentMessage(MessageQueueBase::getDefaultDestination(), message);
}
diff --git a/unittests/mocks/MessageQueueMock.h b/unittests/mocks/MessageQueueMock.h
index 52ba5dfe..cacb72e4 100644
--- a/unittests/mocks/MessageQueueMock.h
+++ b/unittests/mocks/MessageQueueMock.h
@@ -26,7 +26,7 @@ class MessageQueueMock : public MessageQueueBase {
explicit MessageQueueMock(MessageQueueId_t queueId);
//! Get next message which was sent to the default destination
- ReturnValue_t getNextSentMessage(MessageQueueMessageIF& message);
+ ReturnValue_t getNextSentMessageToDefaultDest(MessageQueueMessageIF& message);
//! Get message which was sent to a specific ID
ReturnValue_t getNextSentMessage(MessageQueueId_t id, MessageQueueMessageIF& message);
[[nodiscard]] bool wasMessageSent() const;
diff --git a/unittests/mocks/StorageManagerMock.h b/unittests/mocks/StorageManagerMock.h
index a0a59a47..ce5f3811 100644
--- a/unittests/mocks/StorageManagerMock.h
+++ b/unittests/mocks/StorageManagerMock.h
@@ -32,6 +32,7 @@ class StorageManagerMock : public LocalPool {
std::pair nextFreeElementCallFails;
using LocalPool::getFreeElement;
+ using StorageManagerIF::getData;
void reset();
};
diff --git a/unittests/mocks/cfdp/UserMock.cpp b/unittests/mocks/cfdp/UserMock.cpp
index ca15a5e6..78223506 100644
--- a/unittests/mocks/cfdp/UserMock.cpp
+++ b/unittests/mocks/cfdp/UserMock.cpp
@@ -4,19 +4,20 @@ namespace cfdp {
cfdp::UserMock::UserMock(HasFileSystemIF& vfs) : UserBase(vfs) {}
-void UserMock::transactionIndication(const TransactionId& id) {}
-void UserMock::eofSentIndication(const TransactionId& id) {}
+void UserMock::transactionIndication(const TransactionId& id) { transactionIndicRecvd.emplace(id); }
+
+void UserMock::eofSentIndication(const TransactionId& id) { eofSentRecvd.emplace(id); }
void UserMock::abandonedIndication(const TransactionId& id, cfdp::ConditionCode code,
uint64_t progress) {}
-void UserMock::eofRecvIndication(const TransactionId& id) { eofsRevd.push(id); }
+void UserMock::eofRecvIndication(const TransactionId& id) { eofRecvdRecvd.push(id); }
void UserMock::transactionFinishedIndication(const TransactionFinishedParams& finishedParams) {
- finishedRecvd.push({finishedParams.id, finishedParams});
+ finishedRecvd.emplace(finishedParams.id, finishedParams);
}
void UserMock::metadataRecvdIndication(const MetadataRecvdParams& params) {
- metadataRecvd.push({params.id, params});
+ metadataRecvd.emplace(params.id, params);
}
void UserMock::fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) {}
@@ -27,7 +28,7 @@ void UserMock::faultIndication(const TransactionId& id, cfdp::ConditionCode code
}
void UserMock::reset() {
- std::queue().swap(eofsRevd);
+ std::queue().swap(eofRecvdRecvd);
std::queue>().swap(metadataRecvd);
std::queue>().swap(finishedRecvd);
}
diff --git a/unittests/mocks/cfdp/UserMock.h b/unittests/mocks/cfdp/UserMock.h
index e2a4a483..ad9e152d 100644
--- a/unittests/mocks/cfdp/UserMock.h
+++ b/unittests/mocks/cfdp/UserMock.h
@@ -23,8 +23,10 @@ class UserMock : public UserBase {
void resumedIndication(const TransactionId& id, size_t progress) override;
void faultIndication(const TransactionId& id, ConditionCode code, size_t progress) override;
+ std::queue transactionIndicRecvd;
std::queue> metadataRecvd;
- std::queue eofsRevd;
+ std::queue eofRecvdRecvd;
+ std::queue eofSentRecvd;
std::queue> finishedRecvd;
void reset();
};
diff --git a/unittests/tmtcservices/testSendHelper.cpp b/unittests/tmtcservices/testSendHelper.cpp
index 43816835..07315e44 100644
--- a/unittests/tmtcservices/testSendHelper.cpp
+++ b/unittests/tmtcservices/testSendHelper.cpp
@@ -71,7 +71,7 @@ TEST_CASE("TM Send Helper", "[tm-send-helper]") {
REQUIRE(msgQueue.wasMessageSent());
REQUIRE(msgQueue.numberOfSentMessagesToDefault() == 1);
TmTcMessage msg;
- REQUIRE(msgQueue.getNextSentMessage(msg) == returnvalue::OK);
+ REQUIRE(msgQueue.getNextSentMessageToDefaultDest(msg) == returnvalue::OK);
REQUIRE(msg.getStorageId() == storeId);
REQUIRE(pool.hasDataAtId(msg.getStorageId()));
}
diff --git a/unittests/tmtcservices/testStoreAndSendHelper.cpp b/unittests/tmtcservices/testStoreAndSendHelper.cpp
index 46418dfe..6fe9f8e2 100644
--- a/unittests/tmtcservices/testStoreAndSendHelper.cpp
+++ b/unittests/tmtcservices/testStoreAndSendHelper.cpp
@@ -52,7 +52,7 @@ TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
REQUIRE(msgQueue.wasMessageSent());
REQUIRE(msgQueue.numberOfSentMessagesToDefault() == 1);
TmTcMessage msg;
- REQUIRE(msgQueue.getNextSentMessage(msg) == returnvalue::OK);
+ REQUIRE(msgQueue.getNextSentMessageToDefaultDest(msg) == returnvalue::OK);
REQUIRE(msg.getStorageId() == storeId);
REQUIRE(pool.hasDataAtId(msg.getStorageId()));
storeHelper.deletePacket();
diff --git a/unittests/util/CMakeLists.txt b/unittests/util/CMakeLists.txt
index fb660d54..47c10569 100644
--- a/unittests/util/CMakeLists.txt
+++ b/unittests/util/CMakeLists.txt
@@ -1 +1,2 @@
-target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp)
+target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp
+ testSeqCountProvider.cpp)
diff --git a/unittests/util/testSeqCountProvider.cpp b/unittests/util/testSeqCountProvider.cpp
new file mode 100644
index 00000000..fce8bf43
--- /dev/null
+++ b/unittests/util/testSeqCountProvider.cpp
@@ -0,0 +1,35 @@
+#include
+
+#include "fsfw/util/SeqCountProvider.h"
+
+TEST_CASE("Seq Count Providers", "[util]") {
+ auto genericProviderTest = [](ProvidesSeqCountIF& provider, unsigned expectedWidth) {
+ CHECK(provider.get() == 0);
+ CHECK(provider.bitWidth() == expectedWidth);
+ CHECK(provider.getAndIncrement() == 0);
+ CHECK(provider.getAndIncrement() == 1);
+ CHECK(provider.get() == 2);
+ provider.increment();
+ provider.increment();
+ CHECK(provider.get() == 4);
+ };
+ {
+ SeqCountProviderU16 provider;
+ genericProviderTest(provider, 16);
+ }
+
+ {
+ SeqCountProviderU32 provider;
+ genericProviderTest(provider, 32);
+ }
+
+ {
+ SeqCountProviderU8 provider;
+ genericProviderTest(provider, 8);
+ for (unsigned i = 4; i < UINT8_MAX + 1; i++) {
+ provider.increment();
+ }
+ // Verify wrap-around.
+ CHECK(provider.get() == 0);
+ }
+}