CFDP SOURCE handler #157

Merged
muellerr merged 107 commits from cfdp-source-handler into develop 2023-10-19 10:59:55 +02:00
6 changed files with 161 additions and 134 deletions
Showing only changes of commit 7d713219c5 - Show all commits

View File

@ -14,13 +14,13 @@
using namespace returnvalue; using namespace returnvalue;
cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwParams fsfwParams) cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwDestParams fsfwParams)
: tlvVec(params.maxTlvsInOnePdu), : tlvVec(params.maxTlvsInOnePdu),
userTlvVec(params.maxTlvsInOnePdu), userTlvVec(params.maxTlvsInOnePdu),
dp(std::move(params)), destParams(std::move(params)),
fp(fsfwParams), fsfwParams(fsfwParams),
tp(params.maxFilenameLen) { transactionParams(params.maxFilenameLen) {
tp.pduConf.direction = cfdp::Direction::TOWARDS_SENDER; transactionParams.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
} }
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() { const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
@ -28,13 +28,14 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
uint8_t errorIdx = 0; uint8_t errorIdx = 0;
fsmRes.resetOfIteration(); fsmRes.resetOfIteration();
if (fsmRes.step == TransactionStep::IDLE) { 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 if (infoIter->pduType == PduType::FILE_DIRECTIVE and
infoIter->directiveType == FileDirective::METADATA) { infoIter->directiveType == FileDirective::METADATA) {
result = handleMetadataPdu(*infoIter); result = handleMetadataPdu(*infoIter);
checkAndHandleError(result, errorIdx); checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used // Store data was deleted in PDU handler because a store guard is used
dp.packetListRef.erase(infoIter++); destParams.packetListRef.erase(infoIter++);
} else { } else {
infoIter++; infoIter++;
} }
@ -42,11 +43,12 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
if (fsmRes.step == TransactionStep::IDLE) { if (fsmRes.step == TransactionStep::IDLE) {
// To decrease the already high complexity of the software, all packets arriving before // To decrease the already high complexity of the software, all packets arriving before
// a metadata PDU are deleted. // a metadata PDU are deleted.
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) { for (auto infoIter = destParams.packetListRef.begin();
fp.tcStore->deleteData(infoIter->storeId); infoIter != destParams.packetListRef.end();) {
fsfwParams.tcStore->deleteData(infoIter->storeId);
infoIter++; infoIter++;
} }
dp.packetListRef.clear(); destParams.packetListRef.clear();
} }
if (fsmRes.step != TransactionStep::IDLE) { if (fsmRes.step != TransactionStep::IDLE) {
@ -56,19 +58,20 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
} }
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) { if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) { 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) { if (infoIter->pduType == PduType::FILE_DATA) {
result = handleFileDataPdu(*infoIter); result = handleFileDataPdu(*infoIter);
checkAndHandleError(result, errorIdx); checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used // 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 } else if (infoIter->pduType == PduType::FILE_DIRECTIVE and
infoIter->directiveType == FileDirective::EOF_DIRECTIVE) { infoIter->directiveType == FileDirective::EOF_DIRECTIVE) {
// TODO: Support for check timer missing // TODO: Support for check timer missing
result = handleEofPdu(*infoIter); result = handleEofPdu(*infoIter);
checkAndHandleError(result, errorIdx); checkAndHandleError(result, errorIdx);
// Store data was deleted in PDU handler because a store guard is used // Store data was deleted in PDU handler because a store guard is used
dp.packetListRef.erase(infoIter++); destParams.packetListRef.erase(infoIter++);
} else { } else {
infoIter++; infoIter++;
} }
@ -95,29 +98,29 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
} }
ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) { ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) {
if (dp.packetListRef.full()) { if (destParams.packetListRef.full()) {
return FAILED; return FAILED;
} }
dp.packetListRef.push_back(packet); destParams.packetListRef.push_back(packet);
return OK; return OK;
} }
ReturnValue_t cfdp::DestHandler::initialize() { ReturnValue_t cfdp::DestHandler::initialize() {
if (fp.tmStore == nullptr) { if (fsfwParams.tmStore == nullptr) {
fp.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE); fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (fp.tmStore == nullptr) { if (fsfwParams.tmStore == nullptr) {
return FAILED; return FAILED;
} }
} }
if (fp.tcStore == nullptr) { if (fsfwParams.tcStore == nullptr) {
fp.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE); fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (fp.tcStore == nullptr) { if (fsfwParams.tcStore == nullptr) {
return FAILED; return FAILED;
} }
} }
if (fp.msgQueue == nullptr) { if (fsfwParams.msgQueue == nullptr) {
return FAILED; return FAILED;
} }
return OK; return OK;
@ -125,14 +128,14 @@ ReturnValue_t cfdp::DestHandler::initialize() {
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) { ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
// Process metadata PDU // Process metadata PDU
auto constAccessorPair = fp.tcStore->getData(info.storeId); auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) { if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning? // TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first; return constAccessorPair.first;
} }
cfdp::StringLv sourceFileName; cfdp::StringLv sourceFileName;
cfdp::StringLv destFileName; cfdp::StringLv destFileName;
MetadataInfo metadataInfo(tp.fileSize, sourceFileName, destFileName); MetadataInfo metadataInfo(transactionParams.fileSize, sourceFileName, destFileName);
cfdp::Tlv* tlvArrayAsPtr = tlvVec.data(); cfdp::Tlv* tlvArrayAsPtr = tlvVec.data();
metadataInfo.setOptionsArray(&tlvArrayAsPtr, std::nullopt, tlvVec.size()); metadataInfo.setOptionsArray(&tlvArrayAsPtr, std::nullopt, tlvVec.size());
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
@ -150,7 +153,7 @@ ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) { ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
// Process file data PDU // Process file data PDU
auto constAccessorPair = fp.tcStore->getData(info.storeId); auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) { if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning? // TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first; return constAccessorPair.first;
@ -164,46 +167,46 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info)
} }
size_t fileSegmentLen = 0; size_t fileSegmentLen = 0;
const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen); const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen);
FileOpParams fileOpParams(tp.destName.data(), fileSegmentLen); FileOpParams fileOpParams(transactionParams.destName.data(), fileSegmentLen);
fileOpParams.offset = offset.value(); fileOpParams.offset = offset.value();
if (dp.cfg.indicCfg.fileSegmentRecvIndicRequired) { if (destParams.cfg.indicCfg.fileSegmentRecvIndicRequired) {
FileSegmentRecvdParams segParams; FileSegmentRecvdParams segParams;
segParams.offset = offset.value(); segParams.offset = offset.value();
segParams.id = tp.transactionId; segParams.id = transactionParams.transactionId;
segParams.length = fileSegmentLen; segParams.length = fileSegmentLen;
segParams.recContState = fdInfo.getRecordContinuationState(); segParams.recContState = fdInfo.getRecordContinuationState();
size_t segmentMetadatLen = 0; size_t segmentMetadatLen = 0;
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen); auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
segParams.segmentMetadata = {segMetadata, 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) { if (result != returnvalue::OK) {
// TODO: Proper Error handling // TODO: Proper Error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2) sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
<< result << std::endl; << result << std::endl;
#endif #endif
tp.vfsErrorCount++; transactionParams.vfsErrorCount++;
if (tp.vfsErrorCount < 3) { if (transactionParams.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter // TODO: Provide execution step as parameter
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step), fsfwParams.eventReporter->forwardEvent(events::FILESTORE_ERROR,
result); static_cast<uint8_t>(fsmRes.step), result);
} }
return result; return result;
} else { } else {
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE; transactionParams.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
tp.vfsErrorCount = 0; transactionParams.vfsErrorCount = 0;
} }
if (offset.value() + fileSegmentLen > tp.progress) { if (offset.value() + fileSegmentLen > transactionParams.progress) {
tp.progress = offset.value() + fileSegmentLen; transactionParams.progress = offset.value() + fileSegmentLen;
} }
return result; return result;
} }
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) { ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
// Process EOF PDU // Process EOF PDU
auto constAccessorPair = fp.tcStore->getData(info.storeId); auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) { if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning? // TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first; return constAccessorPair.first;
@ -216,16 +219,16 @@ ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
} }
// TODO: Error handling // TODO: Error handling
if (eofInfo.getConditionCode() == ConditionCode::NO_ERROR) { if (eofInfo.getConditionCode() == ConditionCode::NO_ERROR) {
tp.crc = eofInfo.getChecksum(); transactionParams.crc = eofInfo.getChecksum();
uint64_t fileSizeFromEof = eofInfo.getFileSize().value(); uint64_t fileSizeFromEof = eofInfo.getFileSize().value();
// CFDP 4.6.1.2.9: Declare file size error if progress exceeds file size // 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 // TODO: File size error
} }
tp.fileSize.setFileSize(fileSizeFromEof, std::nullopt); transactionParams.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
} }
if (dp.cfg.indicCfg.eofRecvIndicRequired) { if (destParams.cfg.indicCfg.eofRecvIndicRequired) {
dp.user.eofRecvIndication(getTransactionId()); destParams.user.eofRecvIndication(getTransactionId());
} }
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) { if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) { if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
@ -260,7 +263,7 @@ ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
cfdp::EntityId destId; cfdp::EntityId destId;
headerReader.getDestId(destId); headerReader.getDestId(destId);
RemoteEntityCfg* remoteCfg; 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 // TODO: No remote config for dest ID. I consider this a configuration error, which is not
// covered by the standard. // covered by the standard.
// Warning or error, yield or cache appropriate returnvalue // Warning or error, yield or cache appropriate returnvalue
@ -283,42 +286,42 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
size_t sourceNameSize = 0; size_t sourceNameSize = 0;
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize); const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize + 1 > tp.sourceName.size()) { if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large"); fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
return FAILED; return FAILED;
} }
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize); std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
tp.sourceName[sourceNameSize] = '\0'; transactionParams.sourceName[sourceNameSize] = '\0';
size_t destNameSize = 0; size_t destNameSize = 0;
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize); const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
if (destNameSize + 1 > tp.destName.size()) { if (destNameSize + 1 > transactionParams.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large"); fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
return FAILED; return FAILED;
} }
std::memcpy(tp.destName.data(), destNamePtr, destNameSize); std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
tp.destName[destNameSize] = '\0'; transactionParams.destName[destNameSize] = '\0';
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU, // 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 // so there is no need to create a file or truncate an existing file
if (destNameSize > 0 and sourceNameSize > 0) { if (destNameSize > 0 and sourceNameSize > 0) {
FilesystemParams fparams(tp.destName.data()); FilesystemParams fparams(transactionParams.destName.data());
// handling to allow only specifying target directory. Example: // handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt // 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); result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) { if (result != OK) {
return result; return result;
} }
} }
if (dp.user.vfs.fileExists(fparams)) { if (destParams.user.vfs.fileExists(fparams)) {
result = dp.user.vfs.truncateFile(fparams); result = destParams.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error"); fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
return FAILED; return FAILED;
// TODO: Relevant for filestore rejection error? // TODO: Relevant for filestore rejection error?
} }
} else { } else {
result = dp.user.vfs.createFile(fparams); result = destParams.user.vfs.createFile(fparams);
if (result != OK) { if (result != OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error"); fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
return FAILED; return FAILED;
@ -328,7 +331,7 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
} }
EntityId sourceId; EntityId sourceId;
reader.getSourceId(sourceId); reader.getSourceId(sourceId);
if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) { if (not destParams.remoteCfgTable.getRemoteCfg(sourceId, &transactionParams.remoteCfg)) {
// TODO: Warning, event etc. // TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__ sif::warning << "cfdp::DestHandler" << __func__
@ -343,20 +346,20 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) { } else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED; fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
} }
tp.checksumType = info.getChecksumType(); transactionParams.checksumType = info.getChecksumType();
tp.closureRequested = info.isClosureRequested(); transactionParams.closureRequested = info.isClosureRequested();
reader.fillConfig(tp.pduConf); reader.fillConfig(transactionParams.pduConf);
tp.pduConf.direction = Direction::TOWARDS_SENDER; transactionParams.pduConf.direction = Direction::TOWARDS_SENDER;
tp.transactionId.entityId = tp.pduConf.sourceId; transactionParams.transactionId.entityId = transactionParams.pduConf.sourceId;
tp.transactionId.seqNum = tp.pduConf.seqNum; transactionParams.transactionId.seqNum = transactionParams.pduConf.seqNum;
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS; fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId); MetadataRecvdParams params(transactionParams.transactionId, transactionParams.pduConf.sourceId);
params.fileSize = tp.fileSize.getSize(); params.fileSize = transactionParams.fileSize.getSize();
params.destFileName = tp.destName.data(); params.destFileName = transactionParams.destName.data();
params.sourceFileName = tp.sourceName.data(); params.sourceFileName = transactionParams.sourceName.data();
params.msgsToUserArray = dynamic_cast<MessageToUserTlv*>(userTlvVec.data()); params.msgsToUserArray = dynamic_cast<MessageToUserTlv*>(userTlvVec.data());
params.msgsToUserLen = info.getOptionsLen(); params.msgsToUserLen = info.getOptionsLen();
dp.user.metadataRecvdIndication(params); destParams.user.metadataRecvdIndication(params);
return result; return result;
} }
@ -364,19 +367,19 @@ cfdp::CfdpStates cfdp::DestHandler::getCfdpState() const { return fsmRes.state;
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() { ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
ReturnValue_t result; ReturnValue_t result;
if (tp.checksumType != ChecksumType::NULL_CHECKSUM) { if (transactionParams.checksumType != ChecksumType::NULL_CHECKSUM) {
result = checksumVerification(); result = checksumVerification();
if (result != OK) { if (result != OK) {
// TODO: Warning / error handling? // TODO: Warning / error handling?
} }
} else { } else {
tp.conditionCode = ConditionCode::NO_ERROR; transactionParams.conditionCode = ConditionCode::NO_ERROR;
} }
result = noticeOfCompletion(); result = noticeOfCompletion();
if (result != OK) { if (result != OK) {
} }
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) { if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
if (tp.closureRequested) { if (transactionParams.closureRequested) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU; fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
} else { } else {
finish(); finish();
@ -388,39 +391,41 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
} }
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) { ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
char baseNameBuf[tp.destName.size()]{}; // A path may only have a maximum of 256 characters in CFDP, so this buffer should be sufficient
FilesystemParams fparamsSrc(tp.sourceName.data()); // for all use-cases.
char baseNameBuf[512]{};
FilesystemParams fparamsSrc(transactionParams.sourceName.data());
size_t baseNameLen = 0; size_t baseNameLen = 0;
ReturnValue_t result = ReturnValue_t result = destParams.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf,
dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen); sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) { if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name"); fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED; return FAILED;
} }
// Destination name + slash + base name + null termination // 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, fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name"); "dest filename too large after adding source base name");
return FAILED; return FAILED;
} }
tp.destName[destNameSize++] = '/'; transactionParams.destName[destNameSize++] = '/';
std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen); std::memcpy(transactionParams.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen; destNameSize += baseNameLen;
tp.destName[destNameSize++] = '\0'; transactionParams.destName[destNameSize++] = '\0';
return OK; return OK;
} }
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) { void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR, fsfwParams.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
static_cast<uint8_t>(fsmRes.step), result); static_cast<uint8_t>(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl; sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif #endif
} }
void cfdp::DestHandler::finish() { void cfdp::DestHandler::finish() {
tp.reset(); transactionParams.reset();
dp.packetListRef.clear(); destParams.packetListRef.clear();
fsmRes.state = CfdpStates::IDLE; fsmRes.state = CfdpStates::IDLE;
fsmRes.step = TransactionStep::IDLE; fsmRes.step = TransactionStep::IDLE;
} }
@ -430,18 +435,18 @@ ReturnValue_t cfdp::DestHandler::checksumVerification() {
// TODO: Checksum verification and notice of completion // TODO: Checksum verification and notice of completion
etl::crc32 crcCalc; etl::crc32 crcCalc;
uint64_t currentOffset = 0; uint64_t currentOffset = 0;
FileOpParams params(tp.destName.data(), tp.fileSize.value()); FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
while (currentOffset < tp.fileSize.value()) { while (currentOffset < transactionParams.fileSize.value()) {
uint64_t readLen; uint64_t readLen;
if (currentOffset + buf.size() > tp.fileSize.value()) { if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
readLen = tp.fileSize.value() - currentOffset; readLen = transactionParams.fileSize.value() - currentOffset;
} else { } else {
readLen = buf.size(); readLen = buf.size();
} }
if (readLen > 0) { if (readLen > 0) {
params.offset = currentOffset; params.offset = currentOffset;
params.size = readLen; 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) { if (result != OK) {
// TODO: I think this is a case for a filestore rejection, but it might sense to print // 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 // a warning or trigger an event because this should generally not happen
@ -453,40 +458,42 @@ ReturnValue_t cfdp::DestHandler::checksumVerification() {
} }
uint32_t value = crcCalc.value(); uint32_t value = crcCalc.value();
if (value == tp.crc) { if (value == transactionParams.crc) {
tp.conditionCode = ConditionCode::NO_ERROR; transactionParams.conditionCode = ConditionCode::NO_ERROR;
tp.deliveryCode = FileDeliveryCode::DATA_COMPLETE; transactionParams.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
} else { } else {
// TODO: Proper error handling // TODO: Proper error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CRC check for file " << tp.destName.data() << " failed" << std::endl; sif::warning << "CRC check for file " << tp.destName.data() << " failed" << std::endl;
#endif #endif
tp.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE; transactionParams.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
} }
return OK; return OK;
} }
ReturnValue_t cfdp::DestHandler::noticeOfCompletion() { ReturnValue_t cfdp::DestHandler::noticeOfCompletion() {
if (dp.cfg.indicCfg.transactionFinishedIndicRequired) { if (destParams.cfg.indicCfg.transactionFinishedIndicRequired) {
TransactionFinishedParams params(tp.transactionId, tp.conditionCode, tp.deliveryCode, TransactionFinishedParams params(
tp.deliveryStatus); transactionParams.transactionId, transactionParams.conditionCode,
dp.user.transactionFinishedIndication(params); transactionParams.deliveryCode, transactionParams.deliveryStatus);
destParams.user.transactionFinishedIndication(params);
} }
return OK; return OK;
} }
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() { ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
FinishedInfo info(tp.conditionCode, tp.deliveryCode, tp.deliveryStatus); FinishedInfo info(transactionParams.conditionCode, transactionParams.deliveryCode,
FinishPduCreator finishedPdu(tp.pduConf, info); transactionParams.deliveryStatus);
FinishPduCreator finishedPdu(transactionParams.pduConf, info);
store_address_t storeId; store_address_t storeId;
uint8_t* dataPtr = nullptr; uint8_t* dataPtr = nullptr;
ReturnValue_t result = ReturnValue_t result =
fp.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr); fsfwParams.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
if (result != OK) { if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler:sendFinishedPdu: Getting store slot failed" << std::endl; sif::warning << "cfdp::DestHandler:sendFinishedPdu: Getting store slot failed" << std::endl;
#endif #endif
fp.eventReporter->forwardEvent(events::STORE_ERROR, result, 0); fsfwParams.eventReporter->forwardEvent(events::STORE_ERROR, result, 0);
return result; return result;
} }
size_t serLen = 0; size_t serLen = 0;
@ -496,16 +503,16 @@ ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Serializing Finished PDU failed" sif::warning << "cfdp::DestHandler::sendFinishedPdu: Serializing Finished PDU failed"
<< std::endl; << std::endl;
#endif #endif
fp.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0); fsfwParams.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
return result; return result;
} }
TmTcMessage msg(storeId); TmTcMessage msg(storeId);
result = fp.msgQueue->sendMessage(fp.packetDest.getReportReceptionQueue(), &msg); result = fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &msg);
if (result != OK) { if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl; sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
#endif #endif
fp.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0); fsfwParams.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0);
return result; return result;
} }
fsmRes.packetsSent++; fsmRes.packetsSent++;
@ -525,7 +532,9 @@ const cfdp::DestHandler::FsmResult& cfdp::DestHandler::updateFsmRes(uint8_t erro
return fsmRes; 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) { void cfdp::DestHandler::checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx) {
if (result != OK and errorIdx < 3) { if (result != OK and errorIdx < 3) {
@ -534,13 +543,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) { 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::getTmStore() const { return fsfwParams.tmStore; }
StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fp.tcStore; } StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fsfwParams.tcStore; }

View File

@ -20,23 +20,9 @@
namespace cfdp { namespace cfdp {
struct PacketInfo {
PacketInfo(PduType type, store_address_t storeId,
std::optional<FileDirective> directive = std::nullopt)
: pduType(type), directiveType(directive), storeId(storeId) {}
PduType pduType = PduType::FILE_DATA;
std::optional<FileDirective> directiveType = FileDirective::INVALID_DIRECTIVE;
store_address_t storeId = store_address_t::invalid();
PacketInfo() = default;
};
template <size_t SIZE> template <size_t SIZE>
using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>; using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>;
template <size_t SIZE>
using PacketInfoList = etl::list<PacketInfo, SIZE>;
using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>; using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>;
using PacketInfoListBase = etl::ilist<PacketInfo>;
struct DestHandlerParams { struct DestHandlerParams {
DestHandlerParams(LocalEntityCfg cfg, UserBase& user, RemoteConfigTableIF& remoteCfgTable, DestHandlerParams(LocalEntityCfg cfg, UserBase& user, RemoteConfigTableIF& remoteCfgTable,
@ -63,15 +49,15 @@ struct DestHandlerParams {
struct FsfwDestParams { struct FsfwDestParams {
FsfwDestParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue, FsfwDestParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore, EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore,
StorageManagerIF& tmStore) StorageManagerIF& tmStore)
: FsfwParams(packetDest, msgQueue, eventReporter) { : FsfwDestParams(packetDest, msgQueue, eventReporter) {
this->tcStore = &tcStore; this->tcStore = &tcStore;
this->tmStore = &tmStore; this->tmStore = &tmStore;
} }
FsfwDestParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue, FsfwDestParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
EventReportingProxyIF* eventReporter) EventReportingProxyIF* eventReporter)
: packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {} : packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {}
AcceptsTelemetryIF& packetDest; AcceptsTelemetryIF& packetDest;
MessageQueueIF* msgQueue; MessageQueueIF* msgQueue;
@ -115,7 +101,7 @@ class DestHandler {
*/ */
ReturnValue_t PARTIAL_SUCCESS = returnvalue::makeCode(0, 2); ReturnValue_t PARTIAL_SUCCESS = returnvalue::makeCode(0, 2);
ReturnValue_t FAILURE = returnvalue::makeCode(0, 3); ReturnValue_t FAILURE = returnvalue::makeCode(0, 3);
explicit DestHandler(DestHandlerParams handlerParams, FsfwParams fsfwParams); explicit DestHandler(DestHandlerParams handlerParams, FsfwDestParams fsfwParams);
/** /**
* *
@ -179,9 +165,9 @@ class DestHandler {
std::vector<cfdp::Tlv> tlvVec; std::vector<cfdp::Tlv> tlvVec;
std::vector<cfdp::Tlv> userTlvVec; std::vector<cfdp::Tlv> userTlvVec;
DestHandlerParams dp; DestHandlerParams destParams;
FsfwParams fp; FsfwDestParams fsfwParams;
TransactionParams tp; TransactionParams transactionParams;
FsmResult fsmRes; FsmResult fsmRes;
ReturnValue_t startTransaction(MetadataPduReader& reader, MetadataInfo& info); ReturnValue_t startTransaction(MetadataPduReader& reader, MetadataInfo& info);

View File

@ -1,3 +1,3 @@
#include "SourceHandler.h" #include "SourceHandler.h"
SourceHandler::SourceHandler(SourceHandlerParams params) {} SourceHandler::SourceHandler(SourceHandlerParams params, FsfwSourceParams fsfwParams) {}

View File

@ -1,11 +1,24 @@
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H #ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
#define FSFW_CFDP_CFDPSOURCEHANDLER_H #define FSFW_CFDP_CFDPSOURCEHANDLER_H
#include <cstdint>
#include "fsfw/events/EventReportingProxyIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
struct SourceHandlerParams {}; struct SourceHandlerParams {};
struct FsfwSourceParams {
FsfwSourceParams(EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore)
: tcStore(&tcStore){};
EventReportingProxyIF* eventReporter = nullptr;
StorageManagerIF* tcStore = nullptr;
};
class SourceHandler { class SourceHandler {
public: public:
SourceHandler(SourceHandlerParams params); SourceHandler(SourceHandlerParams params, FsfwSourceParams fsfwParams);
private: private:
enum class TransactionStep : uint8_t { enum class TransactionStep : uint8_t {

View File

@ -1,12 +1,29 @@
#ifndef FSFW_CFDP_HANDLER_DEFS_H #ifndef FSFW_CFDP_HANDLER_DEFS_H
#define FSFW_CFDP_HANDLER_DEFS_H #define FSFW_CFDP_HANDLER_DEFS_H
#include "fsfw/storagemanager/storeAddress.h"
namespace cfdp { namespace cfdp {
enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED }; enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP; static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP;
struct PacketInfo {
PacketInfo(PduType type, store_address_t storeId,
std::optional<FileDirective> directive = std::nullopt)
: pduType(type), directiveType(directive), storeId(storeId) {}
PduType pduType = PduType::FILE_DATA;
std::optional<FileDirective> directiveType = FileDirective::INVALID_DIRECTIVE;
store_address_t storeId = store_address_t::invalid();
PacketInfo() = default;
};
template <size_t SIZE>
using PacketInfoList = etl::list<PacketInfo, SIZE>;
using PacketInfoListBase = etl::ilist<PacketInfo>;
namespace events { namespace events {
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW); static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);

View File

@ -38,7 +38,7 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}}; LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}};
StorageManagerMock tcStore(2, storeCfg); StorageManagerMock tcStore(2, storeCfg);
StorageManagerMock tmStore(3, storeCfg); StorageManagerMock tmStore(3, storeCfg);
FsfwParams fp(tmReceiver, &mqMock, &eventReporterMock); FsfwDestParams fp(tmReceiver, &mqMock, &eventReporterMock);
RemoteEntityCfg cfg(remoteId); RemoteEntityCfg cfg(remoteId);
remoteCfgTableMock.addRemoteConfig(cfg); remoteCfgTableMock.addRemoteConfig(cfg);
fp.tcStore = &tcStore; fp.tcStore = &tcStore;