move generic handler to framework

This commit is contained in:
Robin Müller 2022-09-15 16:53:28 +02:00
parent 886c966420
commit 9e4f2add7d
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
6 changed files with 34 additions and 223 deletions

View File

@ -1,2 +1 @@
target_sources(${TARGET_NAME} PRIVATE InitMission.cpp ObjectFactory.cpp
CfdpHandler.cpp)
target_sources(${TARGET_NAME} PRIVATE InitMission.cpp ObjectFactory.cpp)

View File

@ -1,139 +0,0 @@
#include "CfdpHandler.h"
#include "fsfw/cfdp/pdu/AckPduReader.h"
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
using namespace cfdp;
CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg)
: SystemObject(fsfwParams.objectId),
destHandler(DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, *this), cfdpCfg.userHandler,
cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList,
cfdpCfg.lostSegmentsList),
FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore,
fsfwParams.tmStore)) {
// TODO: Make queue params configurable, or better yet, expect it to be passed externally
msgQueue = QueueFactory::instance()->createMessageQueue();
destHandler.setMsgQueue(*msgQueue);
}
[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; }
[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const {
return destHandler.getDestHandlerParams().cfg.localId.getValue();
}
[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue->getId(); }
ReturnValue_t CfdpHandler::initialize() {
ReturnValue_t result = destHandler.initialize();
if (result != OK) {
return result;
}
tcStore = destHandler.getTcStore();
tmStore = destHandler.getTmStore();
return SystemObject::initialize();
}
ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) {
// TODO: Receive TC packets and route them to source and dest handler, depending on which is
// correct or more appropriate
ReturnValue_t status;
ReturnValue_t result = OK;
TmTcMessage tmtcMsg;
for (status = msgQueue->receiveMessage(&tmtcMsg); status == returnvalue::OK;
status = msgQueue->receiveMessage(&tmtcMsg)) {
result = handleCfdpPacket(tmtcMsg);
if (result != OK) {
status = result;
}
}
auto& fsmRes = destHandler.performStateMachine();
// TODO: Error handling?
while (fsmRes.callStatus == CallStatus::CALL_AGAIN) {
destHandler.performStateMachine();
// TODO: Error handling?
}
return status;
}
ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
auto accessorPair = tcStore->getData(msg.getStorageId());
if(accessorPair.first != OK) {
return accessorPair.first;
}
PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size());
ReturnValue_t result = reader.parseData();
if (result != returnvalue::OK) {
return INVALID_PDU_FORMAT;
}
// The CFDP distributor should have taken care of ensuring the destination ID is correct
PduTypes type = reader.getPduType();
// Only the destination handler can process these PDUs
if (type == PduTypes::FILE_DATA) {
// Disable auto-deletion of packet
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId());
result = destHandler.passPacket(info);
} else {
// Route depending on PDU type and directive type if applicable. It retrieves directive type
// from the raw stream for better performance (with sanity and directive code check).
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
// procedure.
// PDU header only. Invalid supplied data. A directive packet should have a valid data field
// with at least one byte being the directive code
const uint8_t* pduDataField = reader.getPduDataField();
if (pduDataField == nullptr) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast<FileDirectives>(pduDataField[0]);
auto passToDestHandler = [&]() {
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId(), directive);
result = destHandler.passPacket(info);
};
auto passToSourceHandler = [&]() {
};
if (directive == FileDirectives::METADATA or directive == FileDirectives::EOF_DIRECTIVE or
directive == FileDirectives::PROMPT) {
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
// the destination handler
passToDestHandler();
} else if (directive == FileDirectives::FINISH or directive == FileDirectives::NAK or
directive == FileDirectives::KEEP_ALIVE) {
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
// the source handler
passToSourceHandler();
} else if (directive == FileDirectives::ACK) {
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
// the source handler, for a Finished PDU, it is passed to the destination handler.
FileDirectives ackedDirective;
if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) {
return INVALID_ACK_DIRECTIVE_FIELDS;
}
if (ackedDirective == FileDirectives::EOF_DIRECTIVE) {
passToSourceHandler();
} else if (ackedDirective == FileDirectives::FINISH) {
passToDestHandler();
}
}
}
return result;
}
void CfdpHandler::noticeOfSuspensionCb(cfdp::ConditionCode code) {}
void CfdpHandler::noticeOfCancellationCb(cfdp::ConditionCode code) {}
void CfdpHandler::abandonCb(cfdp::ConditionCode code) {}
void CfdpHandler::ignoreCb(cfdp::ConditionCode code) {}

View File

@ -1,72 +0,0 @@
#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#include <utility>
#include "fsfw/cfdp/handler/DestHandler.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
struct FsfwHandlerParams {
FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest,
StorageManagerIF& tcStore, StorageManagerIF& tmStore)
: objectId(objectId), vfs(vfs), packetDest(packetDest), tcStore(tcStore), tmStore(tmStore) {}
object_id_t objectId{};
HasFileSystemIF& vfs;
AcceptsTelemetryIF& packetDest;
StorageManagerIF& tcStore;
StorageManagerIF& tmStore;
};
struct CfdpHandlerCfg {
CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg,
cfdp::UserBase &userHandler,
cfdp::PacketInfoListBase& packetInfo,
cfdp::LostSegmentsListBase& lostSegmentsList,
cfdp::RemoteConfigTableIF& remoteCfgProvider)
: id(std::move(localId)),
indicCfg(indicationCfg),
packetInfoList(packetInfo),
lostSegmentsList(lostSegmentsList),
remoteCfgProvider(remoteCfgProvider),
userHandler(userHandler) {}
cfdp::EntityId id;
cfdp::IndicationCfg indicCfg;
cfdp::PacketInfoListBase& packetInfoList;
cfdp::LostSegmentsListBase& lostSegmentsList;
cfdp::RemoteConfigTableIF& remoteCfgProvider;
cfdp::UserBase& userHandler;
};
class CfdpHandler : public SystemObject,
public cfdp::FaultHandlerBase,
public ExecutableObjectIF,
public AcceptsTelecommandsIF {
public:
explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg);
[[nodiscard]] const char* getName() const override;
[[nodiscard]] uint32_t getIdentifier() const override;
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode) override;
void noticeOfSuspensionCb(cfdp::ConditionCode code) override;
void noticeOfCancellationCb(cfdp::ConditionCode code) override;
void abandonCb(cfdp::ConditionCode code) override;
void ignoreCb(cfdp::ConditionCode code) override;
private:
MessageQueueIF* msgQueue = nullptr;
cfdp::DestHandler destHandler;
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
};
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H

View File

@ -1,6 +1,5 @@
#include "ObjectFactory.h"
#include "CfdpHandler.h"
#include "OBSWConfig.h"
#include "bsp_hosted/fsfwconfig/objects/systemObjectList.h"
#include "common/definitions.h"
@ -8,11 +7,12 @@
#include "example/core/GenericFactory.h"
#include "example/test/FsfwTestTask.h"
#include "example/utility/TmFunnel.h"
#include "fsfw/cfdp.h"
#include "fsfw/storagemanager/PoolManager.h"
#include "fsfw/tcdistribution/CcsdsDistributor.h"
#include "fsfw/tcdistribution/CcsdsDistributorIF.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw_hal/host/HostFilesystem.h"
#include "fsfw/tcdistribution/CcsdsDistributor.h"
#if OBSW_USE_TCP_SERVER == 0
#include <fsfw/osal/common/UdpTcPollingTask.h>
@ -22,9 +22,9 @@
#include "fsfw/osal/common/TcpTmTcServer.h"
#endif
class CfdpExampleUserHandler: public cfdp::UserBase {
class CfdpExampleUserHandler : public cfdp::UserBase {
public:
explicit CfdpExampleUserHandler(HasFileSystemIF& vfs): cfdp::UserBase(vfs) {}
explicit CfdpExampleUserHandler(HasFileSystemIF& vfs) : cfdp::UserBase(vfs) {}
void transactionIndication(const cfdp::TransactionId& id) override {}
void eofSentIndication(const cfdp::TransactionId& id) override {}
@ -36,17 +36,38 @@ class CfdpExampleUserHandler: public cfdp::UserBase {
}
void fileSegmentRecvdIndication(const cfdp::FileSegmentRecvdParams& params) override {}
void reportIndication(const cfdp::TransactionId& id, cfdp::StatusReportIF& report) override {}
void suspendedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code) override {}
void suspendedIndication(const cfdp::TransactionId& id, cfdp::ConditionCodes code) override {}
void resumedIndication(const cfdp::TransactionId& id, size_t progress) override {}
void faultIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
void faultIndication(const cfdp::TransactionId& id, cfdp::ConditionCodes code,
size_t progress) override {}
void abandonedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
void abandonedIndication(const cfdp::TransactionId& id, cfdp::ConditionCodes code,
size_t progress) override {}
void eofRecvIndication(const cfdp::TransactionId& id) override {
sif::info << "EOF PDU received for transaction with " << id << std::endl;
}
};
class CfdpExampleFaultHandler : public cfdp::FaultHandlerBase {
public:
void noticeOfSuspensionCb(cfdp::TransactionId& id, cfdp::ConditionCodes code) override {
sif::warning << "Notice of suspension detected for transaction " << id
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
void noticeOfCancellationCb(cfdp::TransactionId& id, cfdp::ConditionCodes code) override {
sif::warning << "Notice of suspension detected for transaction " << id
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
void abandonCb(cfdp::TransactionId& id, cfdp::ConditionCodes code) override {
sif::warning << "Transaction " << id
<< " was abandoned, condition code : " << cfdp::getConditionCodeString(code)
<< std::endl;
}
void ignoreCb(cfdp::TransactionId& id, cfdp::ConditionCodes code) override {
sif::warning << "Fault ignored for transaction " << id
<< ", condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
};
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
StorageManagerIF* tcStore = nullptr;
@ -105,9 +126,11 @@ void ObjectFactory::produce(void* args) {
remoteCfg.defaultChecksum = cfdp::ChecksumTypes::CRC_32;
auto* remoteCfgProvider = new cfdp::OneRemoteConfigProvider(remoteCfg);
auto* cfdpUserHandler = new CfdpExampleUserHandler(*hostFs);
auto* cfdpFaultHandler = new CfdpExampleFaultHandler();
cfdp::PacketInfoList<64> packetList;
cfdp::LostSegmentsList<128> lostSegments;
CfdpHandlerCfg cfg(localId, indicationCfg, *cfdpUserHandler, packetList, lostSegments, *remoteCfgProvider);
CfdpHandlerCfg cfg(localId, indicationCfg, *cfdpUserHandler, *cfdpFaultHandler, packetList,
lostSegments, *remoteCfgProvider);
auto* cfdpHandler = new CfdpHandler(params, cfg);
CcsdsDistributorIF::DestInfo info("CFDP Destination", common::COMMON_CFDP_APID,
cfdpHandler->getRequestQueue(), true);

@ -1 +1 @@
Subproject commit 6b914a21fd52fe184784b90984bb4bc2db82544d
Subproject commit 29593e31420fa85cb67b8f2b10020ebde5c05ca2

2
fsfw

@ -1 +1 @@
Subproject commit 4fb7375492b27ef51a93c27e08022cfcc59f445a
Subproject commit ed68268c0cd69fd0932ed09fd34000c7d129371d