2022-09-14 19:29:43 +02:00
|
|
|
#include "SourceHandler.h"
|
2023-06-30 11:36:19 +02:00
|
|
|
|
2023-07-17 09:53:23 +02:00
|
|
|
#include <etl/crc32.h>
|
2023-07-17 11:37:20 +02:00
|
|
|
|
2023-07-17 09:53:23 +02:00
|
|
|
#include <array>
|
|
|
|
|
2023-07-19 14:02:03 +02:00
|
|
|
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
2023-07-19 00:12:14 +02:00
|
|
|
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
2023-07-17 16:40:44 +02:00
|
|
|
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
2023-07-17 11:37:20 +02:00
|
|
|
#include "fsfw/filesystem/HasFileSystemIF.h"
|
2023-08-03 14:34:21 +02:00
|
|
|
#include "fsfw/globalfunctions/arrayprinter.h"
|
2023-07-18 09:38:46 +02:00
|
|
|
#include "fsfw/objectmanager.h"
|
2023-07-19 23:22:55 +02:00
|
|
|
#include "fsfw/serviceinterface.h"
|
2023-07-18 09:38:46 +02:00
|
|
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
2023-07-17 09:53:23 +02:00
|
|
|
|
|
|
|
using namespace returnvalue;
|
|
|
|
|
2023-07-17 10:25:09 +02:00
|
|
|
cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
|
2023-07-19 23:22:55 +02:00
|
|
|
: sourceParams(std::move(params)), fsfwParams(fsfwParams) {
|
|
|
|
// The entity ID portion of the transaction ID will always remain fixed.
|
|
|
|
transactionParams.id.entityId = sourceParams.cfg.localId;
|
2023-08-03 15:13:26 +02:00
|
|
|
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
|
2023-07-19 23:22:55 +02:00
|
|
|
if (sourceParams.seqCountProvider.bitWidth() == 8) {
|
2023-08-03 15:13:26 +02:00
|
|
|
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
|
2023-07-19 23:22:55 +02:00
|
|
|
} else if (sourceParams.seqCountProvider.bitWidth() == 16) {
|
2023-08-03 15:13:26 +02:00
|
|
|
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::TWO_BYTES);
|
2023-07-19 23:22:55 +02:00
|
|
|
} else if (sourceParams.seqCountProvider.bitWidth() == 32) {
|
2023-08-03 15:13:26 +02:00
|
|
|
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::FOUR_BYTES);
|
|
|
|
} else if (sourceParams.seqCountProvider.bitWidth() == 64) {
|
|
|
|
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::EIGHT_BYTES);
|
2023-07-19 23:22:55 +02:00
|
|
|
} else {
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::error << "cfdp::SourceHandler: Seq count provider bit width "
|
|
|
|
<< sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl;
|
|
|
|
#else
|
2023-07-19 23:43:40 +02:00
|
|
|
sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n",
|
|
|
|
sourceParams.seqCountProvider.bitWidth());
|
2023-07-19 23:22:55 +02:00
|
|
|
#endif
|
|
|
|
// Yeah, what am I supposed to do here? Can't throw an exception in the FSFW..
|
2023-08-03 15:13:26 +02:00
|
|
|
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
|
2023-07-19 23:22:55 +02:00
|
|
|
}
|
2023-08-14 12:13:29 +02:00
|
|
|
transactionParams.pduConf.seqNum.setValue(0);
|
2023-07-19 23:22:55 +02:00
|
|
|
}
|
2023-07-17 09:53:23 +02:00
|
|
|
|
2023-07-17 15:21:22 +02:00
|
|
|
cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
2023-07-17 15:11:51 +02:00
|
|
|
ReturnValue_t result;
|
2023-07-14 15:56:38 +02:00
|
|
|
if (step == TransactionStep::IDLE) {
|
|
|
|
step = TransactionStep::TRANSACTION_START;
|
|
|
|
}
|
|
|
|
if (step == TransactionStep::TRANSACTION_START) {
|
2023-07-19 23:22:55 +02:00
|
|
|
sourceParams.user.transactionIndication(transactionParams.id);
|
2023-07-14 15:56:38 +02:00
|
|
|
step = TransactionStep::CRC_PROCEDURE;
|
|
|
|
}
|
|
|
|
if (step == TransactionStep::CRC_PROCEDURE) {
|
2023-07-17 15:11:51 +02:00
|
|
|
result = checksumGeneration();
|
2023-07-17 09:53:23 +02:00
|
|
|
if (result != OK) {
|
|
|
|
// TODO: Some error handling
|
|
|
|
}
|
2023-07-17 15:03:08 +02:00
|
|
|
step = TransactionStep::SENDING_METADATA;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
|
|
|
if (step == TransactionStep::SENDING_METADATA) {
|
2023-07-17 15:11:51 +02:00
|
|
|
result = prepareAndSendMetadataPdu();
|
|
|
|
if (result != OK) {
|
|
|
|
// TODO: Error handling
|
|
|
|
}
|
2023-08-14 20:47:27 +02:00
|
|
|
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
2023-07-17 15:21:22 +02:00
|
|
|
return fsmResult;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
|
|
|
if (step == TransactionStep::SENDING_FILE_DATA) {
|
2023-08-03 15:49:23 +02:00
|
|
|
bool noFdPdu = false;
|
|
|
|
result = prepareAndSendNextFileDataPdu(noFdPdu);
|
2023-07-17 15:11:51 +02:00
|
|
|
if (result != OK) {
|
|
|
|
// TODO: Error handling
|
|
|
|
}
|
2023-08-03 15:49:23 +02:00
|
|
|
if (!noFdPdu) {
|
2023-08-14 20:47:27 +02:00
|
|
|
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
2023-08-03 15:49:23 +02:00
|
|
|
return fsmResult;
|
|
|
|
}
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
|
|
|
if (step == TransactionStep::SENDING_EOF) {
|
2023-07-17 15:21:22 +02:00
|
|
|
result = prepareAndSendEofPdu();
|
2023-07-17 15:11:51 +02:00
|
|
|
if (result != OK) {
|
|
|
|
// TODO: Error handling
|
|
|
|
}
|
2023-07-19 23:43:40 +02:00
|
|
|
if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
|
|
|
|
sourceParams.user.eofSentIndication(transactionParams.id);
|
|
|
|
}
|
|
|
|
if (transactionParams.closureRequested) {
|
|
|
|
step = TransactionStep::WAIT_FOR_FINISH;
|
2023-08-14 20:47:27 +02:00
|
|
|
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
|
|
} else {
|
|
|
|
step = TransactionStep::NOTICE_OF_COMPLETION;
|
|
|
|
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
2023-07-19 23:43:40 +02:00
|
|
|
}
|
2023-08-14 20:47:27 +02:00
|
|
|
return fsmResult;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
|
|
|
if (step == TransactionStep::WAIT_FOR_FINISH) {
|
|
|
|
// TODO: In case this is a request with closure, wait for finish.
|
2023-07-17 15:11:51 +02:00
|
|
|
// Done, issue notice of completion
|
|
|
|
step = TransactionStep::NOTICE_OF_COMPLETION;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
|
|
|
if (step == TransactionStep::NOTICE_OF_COMPLETION) {
|
2023-07-19 23:43:40 +02:00
|
|
|
noticeOfCompletion();
|
|
|
|
reset();
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
2023-07-17 15:21:22 +02:00
|
|
|
return fsmResult;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
2023-07-17 15:21:22 +02:00
|
|
|
|
2023-08-14 20:47:27 +02:00
|
|
|
const cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() {
|
2023-08-03 15:49:23 +02:00
|
|
|
fsmResult.packetsSent = 0;
|
2023-08-14 13:19:48 +02:00
|
|
|
fsmResult.errors = 0;
|
2023-08-14 20:47:27 +02:00
|
|
|
fsmResult.callStatus = CallStatus::DONE;
|
2023-07-14 15:56:38 +02:00
|
|
|
if (state == cfdp::CfdpState::IDLE) {
|
2023-07-17 15:21:22 +02:00
|
|
|
return fsmResult;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
|
|
|
if (state == cfdp::CfdpState::BUSY_CLASS_1_NACKED) {
|
|
|
|
return fsmNacked();
|
|
|
|
}
|
2023-07-17 15:21:22 +02:00
|
|
|
return fsmResult;
|
2023-07-14 15:56:38 +02:00
|
|
|
}
|
2023-07-17 09:53:23 +02:00
|
|
|
|
|
|
|
ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
|
2023-07-19 23:43:40 +02:00
|
|
|
if (transactionParams.fileSize.value() == 0) {
|
|
|
|
// NULL checksum for empty file.
|
|
|
|
transactionParams.crc = 0;
|
|
|
|
return OK;
|
|
|
|
}
|
2023-07-17 09:53:23 +02:00
|
|
|
std::array<uint8_t, 1024> buf{};
|
|
|
|
etl::crc32 crcCalc;
|
|
|
|
uint64_t currentOffset = 0;
|
2023-08-04 15:17:53 +02:00
|
|
|
FileOpParams params(transactionParams.sourceName.data(), transactionParams.fileSize.value());
|
2023-07-17 09:53:23 +02:00
|
|
|
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) {
|
|
|
|
// 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
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
crcCalc.add(buf.begin(), buf.begin() + readLen);
|
|
|
|
}
|
|
|
|
currentOffset += readLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
transactionParams.crc = crcCalc.value();
|
|
|
|
return OK;
|
|
|
|
}
|
2023-07-17 10:15:06 +02:00
|
|
|
|
2023-07-27 17:15:01 +02:00
|
|
|
ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
|
2023-07-17 15:03:08 +02:00
|
|
|
if (state != CfdpState::IDLE) {
|
|
|
|
return SOURCE_TRANSACTION_PENDING;
|
|
|
|
}
|
2023-07-27 17:15:01 +02:00
|
|
|
if (cfg.remoteId != putRequest.getDestId()) {
|
|
|
|
return WRONG_REMOTE_CFG_ENTITY_ID;
|
2023-07-17 14:48:37 +02:00
|
|
|
}
|
2023-07-27 17:15:01 +02:00
|
|
|
if (putRequest.getSourceName().getValueLen() == 0) {
|
|
|
|
return SOURCE_NAME_EMPTY;
|
|
|
|
}
|
|
|
|
if (putRequest.getDestName().getValueLen() == 0) {
|
|
|
|
return DEST_NAME_EMPTY;
|
2023-07-18 09:38:46 +02:00
|
|
|
}
|
2023-08-03 15:30:38 +02:00
|
|
|
const char* srcNamePtr = putRequest.getSourceName().getCString(transactionParams.sourceNameSize);
|
|
|
|
const char* destNamePtr = putRequest.getDestName().getCString(transactionParams.destNameSize);
|
2023-07-27 17:15:01 +02:00
|
|
|
std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
|
|
|
|
std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
|
2023-07-17 16:40:44 +02:00
|
|
|
FilesystemParams params(transactionParams.sourceName.data());
|
|
|
|
if (!sourceParams.user.vfs.fileExists(params)) {
|
|
|
|
return FILE_DOES_NOT_EXIST;
|
|
|
|
}
|
2023-07-19 13:44:52 +02:00
|
|
|
if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
|
|
|
|
return FILE_SEGMENT_LEN_INVALID;
|
|
|
|
}
|
2023-07-27 17:15:01 +02:00
|
|
|
// 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;
|
|
|
|
}
|
2023-08-03 15:13:26 +02:00
|
|
|
const EntityId& destId = putRequest.getDestId();
|
2023-08-03 15:30:38 +02:00
|
|
|
// 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());
|
|
|
|
}
|
2023-07-18 09:38:46 +02:00
|
|
|
// Only used for PDU forwarding, file is sent to file receiver regularly here.
|
|
|
|
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
|
2023-08-14 12:13:29 +02:00
|
|
|
transactionParams.pduConf.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement());
|
|
|
|
transactionParams.id.seqNum = transactionParams.pduConf.seqNum;
|
2023-07-18 09:38:46 +02:00
|
|
|
|
|
|
|
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;
|
2023-07-19 13:44:52 +02:00
|
|
|
uint64_t fileSize = 0;
|
2023-07-17 16:40:44 +02:00
|
|
|
sourceParams.user.vfs.getFileSize(params, fileSize);
|
2023-07-18 09:38:46 +02:00
|
|
|
transactionParams.pduConf.largeFile = false;
|
|
|
|
if (fileSize > UINT32_MAX) {
|
|
|
|
transactionParams.pduConf.largeFile = true;
|
2023-07-17 14:48:37 +02:00
|
|
|
}
|
2023-08-03 17:43:03 +02:00
|
|
|
if (fileSize == 0) {
|
|
|
|
transactionParams.checksumType = ChecksumType::NULL_CHECKSUM;
|
|
|
|
} else {
|
|
|
|
transactionParams.checksumType = ChecksumType::CRC_32;
|
|
|
|
}
|
2023-07-18 09:38:46 +02:00
|
|
|
transactionParams.fileSize.setFileSize(fileSize, transactionParams.pduConf.largeFile);
|
2023-08-14 12:13:29 +02:00
|
|
|
transactionParams.progress = 0;
|
2023-07-19 13:44:52 +02:00
|
|
|
transactionParams.remoteCfg = cfg;
|
2023-07-17 14:54:45 +02:00
|
|
|
return OK;
|
2023-07-17 13:43:48 +02:00
|
|
|
}
|
2023-07-17 15:11:51 +02:00
|
|
|
|
|
|
|
ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() {
|
2023-07-18 09:38:46 +02:00
|
|
|
cfdp::StringLv sourceName(transactionParams.sourceName.data(), transactionParams.sourceNameSize);
|
2023-07-19 13:44:52 +02:00
|
|
|
cfdp::StringLv destName(transactionParams.destName.data(), transactionParams.destNameSize);
|
2023-08-03 17:43:03 +02:00
|
|
|
auto metadataInfo =
|
|
|
|
MetadataGenericInfo(transactionParams.closureRequested, transactionParams.checksumType,
|
|
|
|
transactionParams.fileSize);
|
2023-07-27 14:55:46 +02:00
|
|
|
auto metadataPdu =
|
|
|
|
MetadataPduCreator(transactionParams.pduConf, metadataInfo, sourceName, destName, nullptr, 0);
|
2023-07-19 14:06:15 +02:00
|
|
|
ReturnValue_t result = sendGenericPdu(metadataPdu);
|
|
|
|
if (result != OK) {
|
|
|
|
return result;
|
|
|
|
}
|
2023-07-18 09:38:46 +02:00
|
|
|
// Advance FSM if everything works
|
2023-07-17 15:11:51 +02:00
|
|
|
step = TransactionStep::SENDING_FILE_DATA;
|
|
|
|
return OK;
|
|
|
|
}
|
2023-07-17 15:21:22 +02:00
|
|
|
|
2023-08-03 15:49:23 +02:00
|
|
|
ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu(bool& noFileDataPdu) {
|
2023-07-19 13:44:52 +02:00
|
|
|
cfdp::Fss offset(transactionParams.progress);
|
|
|
|
uint64_t readLen;
|
|
|
|
uint64_t fileSize = transactionParams.fileSize.value();
|
2023-08-03 15:49:23 +02:00
|
|
|
noFileDataPdu = false;
|
2023-07-19 13:44:52 +02:00
|
|
|
if (fileSize == 0) {
|
|
|
|
// We are done, no need to send file data PDUs for an empty file.
|
|
|
|
step = TransactionStep::SENDING_EOF;
|
2023-08-03 15:49:23 +02:00
|
|
|
noFileDataPdu = true;
|
2023-07-19 13:44:52 +02:00
|
|
|
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);
|
2023-08-14 12:13:29 +02:00
|
|
|
fileParams.offset = transactionParams.progress;
|
2023-07-19 13:44:52 +02:00
|
|
|
ReturnValue_t result =
|
|
|
|
sourceParams.user.vfs.readFromFile(fileParams, fileBuf.data(), fileBuf.size());
|
|
|
|
if (result != returnvalue::OK) {
|
2023-08-14 12:13:29 +02:00
|
|
|
addError(result);
|
2023-07-19 13:44:52 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
auto fileDataInfo = FileDataInfo(offset, fileBuf.data(), readLen);
|
|
|
|
auto fileDataPdu = FileDataCreator(transactionParams.pduConf, fileDataInfo);
|
2023-07-19 14:06:15 +02:00
|
|
|
result = sendGenericPdu(fileDataPdu);
|
|
|
|
if (result != OK) {
|
|
|
|
return result;
|
|
|
|
}
|
2023-07-19 13:44:52 +02:00
|
|
|
transactionParams.progress += readLen;
|
|
|
|
if (transactionParams.progress >= fileSize) {
|
|
|
|
// Advance FSM after all file data PDUs were sent.
|
|
|
|
step = TransactionStep::SENDING_EOF;
|
|
|
|
}
|
2023-07-17 15:11:51 +02:00
|
|
|
return OK;
|
|
|
|
}
|
2023-07-17 15:21:22 +02:00
|
|
|
|
|
|
|
ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
|
2023-07-19 23:43:40 +02:00
|
|
|
auto eofInfo =
|
|
|
|
EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize);
|
2023-07-19 14:06:15 +02:00
|
|
|
auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
|
|
|
|
ReturnValue_t result = sendGenericPdu(eofPdu);
|
|
|
|
if (result != OK) {
|
|
|
|
return result;
|
|
|
|
}
|
2023-07-17 15:11:51 +02:00
|
|
|
return OK;
|
|
|
|
}
|
2023-07-18 09:38:46 +02:00
|
|
|
|
|
|
|
ReturnValue_t cfdp::SourceHandler::initialize() {
|
|
|
|
if (fsfwParams.tmStore == nullptr) {
|
|
|
|
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
|
|
|
if (fsfwParams.tmStore == nullptr) {
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fsfwParams.tcStore == nullptr) {
|
|
|
|
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
|
|
|
if (fsfwParams.tcStore == nullptr) {
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fsfwParams.msgQueue == nullptr) {
|
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
2023-07-19 13:44:52 +02:00
|
|
|
|
2023-08-03 15:49:23 +02:00
|
|
|
ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
|
2023-07-19 13:44:52 +02:00
|
|
|
uint8_t* dataPtr;
|
|
|
|
store_address_t storeId;
|
|
|
|
ReturnValue_t result =
|
2023-08-03 13:57:55 +02:00
|
|
|
fsfwParams.tmStore->getFreeElement(&storeId, pdu.getSerializedSize(), &dataPtr);
|
2023-07-19 13:44:52 +02:00
|
|
|
if (result != OK) {
|
2023-08-14 12:13:29 +02:00
|
|
|
addError(result);
|
2023-07-19 13:44:52 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
size_t serializedLen = 0;
|
|
|
|
result = pdu.serializeBe(dataPtr, serializedLen, pdu.getSerializedSize());
|
|
|
|
if (result != OK) {
|
2023-08-14 12:13:29 +02:00
|
|
|
addError(result);
|
2023-07-19 13:44:52 +02:00
|
|
|
return result;
|
|
|
|
}
|
2023-08-03 13:57:55 +02:00
|
|
|
TmTcMessage tmMsg(storeId);
|
2023-08-03 15:49:23 +02:00
|
|
|
result =
|
|
|
|
fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg);
|
2023-08-14 21:19:35 +02:00
|
|
|
if (result == MessageQueueIF::FULL) {
|
|
|
|
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
|
|
|
return TARGET_MSG_QUEUE_FULL;
|
|
|
|
} else if (result == OK) {
|
2023-08-03 15:49:23 +02:00
|
|
|
fsmResult.packetsSent += 1;
|
|
|
|
}
|
|
|
|
return result;
|
2023-07-19 13:44:52 +02:00
|
|
|
}
|
2023-07-19 23:43:40 +02:00
|
|
|
|
|
|
|
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;
|
2023-08-14 20:47:27 +02:00
|
|
|
fsmResult.callStatus = CallStatus::DONE;
|
2023-07-19 23:43:40 +02:00
|
|
|
transactionParams.reset();
|
|
|
|
return OK;
|
|
|
|
}
|
2023-07-27 17:15:01 +02:00
|
|
|
cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
|
|
|
|
|
|
|
|
cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }
|
2023-08-14 12:13:29 +02:00
|
|
|
|
|
|
|
void cfdp::SourceHandler::addError(ReturnValue_t error) {
|
2023-08-14 12:19:55 +02:00
|
|
|
if (fsmResult.errors < fsmResult.errorCodes.size()) {
|
|
|
|
fsmResult.errorCodes[fsmResult.errors] = error;
|
|
|
|
fsmResult.errors++;
|
2023-08-14 12:13:29 +02:00
|
|
|
}
|
|
|
|
}
|