This commit is contained in:
Robin Müller 2023-07-27 17:15:01 +02:00
parent f49e607881
commit a856f91c67
Signed by: muellerr
GPG Key ID: 407F9B00F858F270
8 changed files with 92 additions and 42 deletions

View File

@ -185,3 +185,17 @@ 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<cfdp::TransmissionMode>(this->transmissionMode);
}
return hasTransmissionMode;
}

View File

@ -22,7 +22,9 @@ class PutRequest : public SerializeIF {
PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
const uint8_t* fsRequests, size_t fsRequestsSize);
/**
* Put request to initiate file transfers.
* 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
@ -53,6 +55,9 @@ class PutRequest : public SerializeIF {
[[nodiscard]] bool isMetadataOnly() const;
bool getTransmissionMode(TransmissionMode& mode) const;
bool getClosureRequested(bool& closureRequested) const;
[[nodiscard]] const EntityId& getDestId() const;
void setDestId(EntityId id);

View File

@ -138,21 +138,23 @@ ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
return OK;
}
ReturnValue_t cfdp::SourceHandler::putRequest(PutRequestFull& putRequest, RemoteEntityCfg& cfg) {
ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
if (state != CfdpState::IDLE) {
return SOURCE_TRANSACTION_PENDING;
}
if (putRequest.sourceNameSize > transactionParams.sourceName.size()) {
return FAILED;
if (cfg.remoteId != putRequest.getDestId()) {
return WRONG_REMOTE_CFG_ENTITY_ID;
}
if (putRequest.destNameSize > transactionParams.destName.size()) {
return FAILED;
if (putRequest.getSourceName().getValueLen() == 0) {
return SOURCE_NAME_EMPTY;
}
std::memcpy(transactionParams.destName.data(), putRequest.destName, putRequest.destNameSize);
std::memcpy(transactionParams.sourceName.data(), putRequest.sourceName,
putRequest.sourceNameSize);
transactionParams.sourceNameSize = putRequest.sourceNameSize;
transactionParams.destNameSize = putRequest.destNameSize;
if (putRequest.getDestName().getValueLen() == 0) {
return DEST_NAME_EMPTY;
}
const char* srcNamePtr = putRequest.getSourceName().getString(transactionParams.sourceNameSize);
const char* destNamePtr = putRequest.getDestName().getString(transactionParams.destNameSize);
std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
FilesystemParams params(transactionParams.sourceName.data());
if (!sourceParams.user.vfs.fileExists(params)) {
return FILE_DOES_NOT_EXIST;
@ -160,9 +162,15 @@ ReturnValue_t cfdp::SourceHandler::putRequest(PutRequestFull& putRequest, Remote
if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
return FILE_SEGMENT_LEN_INVALID;
}
transactionParams.closureRequested = putRequest.closureRequested;
transactionParams.pduConf.mode = putRequest.transmissionMode;
transactionParams.pduConf.destId = putRequest.destId;
// 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;
}
transactionParams.pduConf.destId = putRequest.getDestId();
// Only used for PDU forwarding, file is sent to file receiver regularly here.
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
@ -304,3 +312,6 @@ ReturnValue_t cfdp::SourceHandler::reset() {
transactionParams.reset();
return OK;
}
cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }

View File

@ -7,6 +7,7 @@
#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"
@ -26,6 +27,17 @@ struct SourceHandlerParams {
class SourceHandler {
public:
enum class TransactionStep : uint8_t {
IDLE = 0,
TRANSACTION_START = 1,
CRC_PROCEDURE = 2,
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;
@ -38,33 +50,25 @@ class SourceHandler {
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 putRequest(PutRequestFull& putRequest, RemoteEntityCfg& cfg);
ReturnValue_t transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg);
FsmResult& stateMachine();
ReturnValue_t initialize();
private:
enum class TransactionStep : uint8_t {
IDLE = 0,
TRANSACTION_START = 1,
CRC_PROCEDURE = 2,
SENDING_METADATA = 3,
SENDING_FILE_DATA = 4,
SENDING_EOF = 5,
WAIT_FOR_ACK = 6,
WAIT_FOR_FINISH = 7,
NOTICE_OF_COMPLETION = 8
};
struct TransactionParams {
uint32_t crc{};
std::array<char, 524> sourceName{};
std::array<char, UINT8_MAX + 1> sourceName{};
size_t sourceNameSize = 0;
std::array<char, 524> destName{};
std::array<char, UINT8_MAX + 1> destName{};
size_t destNameSize = 0;
cfdp::Fss fileSize;
size_t progress = 0;
@ -72,7 +76,7 @@ class SourceHandler {
RemoteEntityCfg remoteCfg;
PduConfig pduConf;
cfdp::TransactionId id{};
cfdp::WidthInBytes seqCountWidth;
cfdp::WidthInBytes seqCountWidth{};
void reset() {
sourceNameSize = 0;

View File

@ -48,18 +48,6 @@ template <size_t SIZE>
using PacketInfoList = etl::list<PacketInfo, SIZE>;
using PacketInfoListBase = etl::ilist<PacketInfo>;
struct PutRequestFull {
public:
EntityId destId;
TransmissionMode transmissionMode = TransmissionMode::UNACKNOWLEDGED;
char destName[524]{};
size_t destNameSize = 0;
char sourceName[524]{};
size_t sourceNameSize = 0;
bool closureRequested = true;
// MessageToUserTlv
};
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
namespace events {
@ -75,7 +63,10 @@ static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, seve
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, 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);
} // namespace cfdp
#endif // FSFW_CFDP_HANDLER_DEFS_H

View File

@ -93,3 +93,5 @@ cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
other.value = SerialBufferAdapter<uint8_t>();
return *this;
}
size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }

View File

@ -40,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

View File

@ -1,6 +1,8 @@
#include <catch2/catch_test_macros.hpp>
#include <filesystem>
#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/FileDataCreator.h"
@ -18,6 +20,7 @@
TEST_CASE("CFDP Source Handler", "[cfdp]") {
using namespace cfdp;
using namespace returnvalue;
using namespace std::filesystem;
MessageQueueId_t destQueueId = 2;
AcceptsTmMock tmReceiver(destQueueId);
MessageQueueMock mqMock(destQueueId);
@ -36,4 +39,22 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
StorageManagerMock tmStore(3, storeCfg);
FsfwParams fp(tmReceiver, &mqMock, &eventReporterMock);
auto sourceHandler = SourceHandler(dp, fp);
SECTION("Test Basic") {
CHECK(sourceHandler.getState() == CfdpState::IDLE);
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
}
SECTION("Transfer empty file") {
RemoteEntityCfg cfg;
EntityId id(cfdp::WidthInBytes::ONE_BYTE, 5);
cfg.remoteId = id;
FilesystemParams srcFileName("/tmp/cfdp-test.txt");
fsMock.createFile(srcFileName);
cfdp::StringLv srcNameLv(srcFileName.path, std::strlen(srcFileName.path));
FilesystemParams destFileName("/tmp/cfdp-test.txt");
cfdp::StringLv destNameLv(destFileName.path, std::strlen(destFileName.path));
PutRequest putRequest(id, srcNameLv, destNameLv);
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
}
}