CFDP SOURCE handler #157
@ -185,3 +185,17 @@ const uint8_t *cfdp::PutRequest::getMessagesToUser(size_t &totalSize) {
|
|||||||
totalSize = this->msgsToUsersTotalSize;
|
totalSize = this->msgsToUsersTotalSize;
|
||||||
return msgsToUserStartPtr;
|
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;
|
||||||
|
}
|
||||||
|
@ -22,7 +22,9 @@ class PutRequest : public SerializeIF {
|
|||||||
PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
|
PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
|
||||||
const uint8_t* fsRequests, size_t fsRequestsSize);
|
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 destId
|
||||||
* @param sourceName
|
* @param sourceName
|
||||||
* @param destName
|
* @param destName
|
||||||
@ -53,6 +55,9 @@ class PutRequest : public SerializeIF {
|
|||||||
|
|
||||||
[[nodiscard]] bool isMetadataOnly() const;
|
[[nodiscard]] bool isMetadataOnly() const;
|
||||||
|
|
||||||
|
bool getTransmissionMode(TransmissionMode& mode) const;
|
||||||
|
bool getClosureRequested(bool& closureRequested) const;
|
||||||
|
|
||||||
[[nodiscard]] const EntityId& getDestId() const;
|
[[nodiscard]] const EntityId& getDestId() const;
|
||||||
void setDestId(EntityId id);
|
void setDestId(EntityId id);
|
||||||
|
|
||||||
|
@ -138,21 +138,23 @@ ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::putRequest(PutRequestFull& putRequest, RemoteEntityCfg& cfg) {
|
ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
|
||||||
if (state != CfdpState::IDLE) {
|
if (state != CfdpState::IDLE) {
|
||||||
|
|||||||
return SOURCE_TRANSACTION_PENDING;
|
return SOURCE_TRANSACTION_PENDING;
|
||||||
}
|
}
|
||||||
if (putRequest.sourceNameSize > transactionParams.sourceName.size()) {
|
if (cfg.remoteId != putRequest.getDestId()) {
|
||||||
return FAILED;
|
return WRONG_REMOTE_CFG_ENTITY_ID;
|
||||||
}
|
}
|
||||||
if (putRequest.destNameSize > transactionParams.destName.size()) {
|
if (putRequest.getSourceName().getValueLen() == 0) {
|
||||||
return FAILED;
|
return SOURCE_NAME_EMPTY;
|
||||||
}
|
}
|
||||||
std::memcpy(transactionParams.destName.data(), putRequest.destName, putRequest.destNameSize);
|
if (putRequest.getDestName().getValueLen() == 0) {
|
||||||
std::memcpy(transactionParams.sourceName.data(), putRequest.sourceName,
|
return DEST_NAME_EMPTY;
|
||||||
putRequest.sourceNameSize);
|
}
|
||||||
transactionParams.sourceNameSize = putRequest.sourceNameSize;
|
const char* srcNamePtr = putRequest.getSourceName().getString(transactionParams.sourceNameSize);
|
||||||
transactionParams.destNameSize = putRequest.destNameSize;
|
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());
|
FilesystemParams params(transactionParams.sourceName.data());
|
||||||
if (!sourceParams.user.vfs.fileExists(params)) {
|
if (!sourceParams.user.vfs.fileExists(params)) {
|
||||||
return FILE_DOES_NOT_EXIST;
|
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) {
|
if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
|
||||||
return FILE_SEGMENT_LEN_INVALID;
|
return FILE_SEGMENT_LEN_INVALID;
|
||||||
}
|
}
|
||||||
transactionParams.closureRequested = putRequest.closureRequested;
|
// If transmission mode is not set, use default transmission mode for the remote entity.
|
||||||
transactionParams.pduConf.mode = putRequest.transmissionMode;
|
if (not putRequest.getTransmissionMode(transactionParams.pduConf.mode)) {
|
||||||
transactionParams.pduConf.destId = putRequest.destId;
|
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.
|
// Only used for PDU forwarding, file is sent to file receiver regularly here.
|
||||||
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
|
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
|
||||||
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
|
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
|
||||||
@ -304,3 +312,6 @@ ReturnValue_t cfdp::SourceHandler::reset() {
|
|||||||
transactionParams.reset();
|
transactionParams.reset();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
|
||||||
|
|
||||||
|
cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "UserBase.h"
|
#include "UserBase.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "fsfw/cfdp/Fss.h"
|
#include "fsfw/cfdp/Fss.h"
|
||||||
|
#include "fsfw/cfdp/handler/PutRequest.h"
|
||||||
#include "fsfw/cfdp/handler/mib.h"
|
#include "fsfw/cfdp/handler/mib.h"
|
||||||
#include "fsfw/events/EventReportingProxyIF.h"
|
#include "fsfw/events/EventReportingProxyIF.h"
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||||
@ -26,6 +27,17 @@ struct SourceHandlerParams {
|
|||||||
|
|
||||||
class SourceHandler {
|
class SourceHandler {
|
||||||
public:
|
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 {
|
struct FsmResult {
|
||||||
public:
|
public:
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
@ -38,33 +50,25 @@ class SourceHandler {
|
|||||||
|
|
||||||
SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams);
|
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
|
* Pass a put request to the source handler, which might initiate a CFDP transaction and start
|
||||||
* the state machine
|
* the state machine
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t putRequest(PutRequestFull& putRequest, RemoteEntityCfg& cfg);
|
ReturnValue_t transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg);
|
||||||
FsmResult& stateMachine();
|
FsmResult& stateMachine();
|
||||||
|
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
|
|
||||||
private:
|
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 {
|
struct TransactionParams {
|
||||||
uint32_t crc{};
|
uint32_t crc{};
|
||||||
std::array<char, 524> sourceName{};
|
std::array<char, UINT8_MAX + 1> sourceName{};
|
||||||
size_t sourceNameSize = 0;
|
size_t sourceNameSize = 0;
|
||||||
std::array<char, 524> destName{};
|
std::array<char, UINT8_MAX + 1> destName{};
|
||||||
size_t destNameSize = 0;
|
size_t destNameSize = 0;
|
||||||
cfdp::Fss fileSize;
|
cfdp::Fss fileSize;
|
||||||
size_t progress = 0;
|
size_t progress = 0;
|
||||||
@ -72,7 +76,7 @@ class SourceHandler {
|
|||||||
RemoteEntityCfg remoteCfg;
|
RemoteEntityCfg remoteCfg;
|
||||||
PduConfig pduConf;
|
PduConfig pduConf;
|
||||||
cfdp::TransactionId id{};
|
cfdp::TransactionId id{};
|
||||||
cfdp::WidthInBytes seqCountWidth;
|
cfdp::WidthInBytes seqCountWidth{};
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
sourceNameSize = 0;
|
sourceNameSize = 0;
|
||||||
|
@ -48,18 +48,6 @@ template <size_t SIZE>
|
|||||||
using PacketInfoList = etl::list<PacketInfo, SIZE>;
|
using PacketInfoList = etl::list<PacketInfo, SIZE>;
|
||||||
using PacketInfoListBase = etl::ilist<PacketInfo>;
|
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 };
|
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
|
||||||
|
|
||||||
namespace events {
|
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 SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0);
|
||||||
static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = returnvalue::makeCode(CID, 1);
|
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
|
} // namespace cfdp
|
||||||
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
||||||
|
@ -93,3 +93,5 @@ cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
|
|||||||
other.value = SerialBufferAdapter<uint8_t>();
|
other.value = SerialBufferAdapter<uint8_t>();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }
|
||||||
|
@ -40,6 +40,8 @@ class Lv : public SerializeIF {
|
|||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
|
size_t getValueLen() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get value field and its size.
|
* Get value field and its size.
|
||||||
* @param size Optionally retrieve size. Size will be the size of the actual value field
|
* @param size Optionally retrieve size. Size will be the size of the actual value field
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "fsfw/cfdp.h"
|
#include "fsfw/cfdp.h"
|
||||||
|
#include "fsfw/cfdp/handler/PutRequest.h"
|
||||||
#include "fsfw/cfdp/handler/SourceHandler.h"
|
#include "fsfw/cfdp/handler/SourceHandler.h"
|
||||||
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
||||||
@ -18,6 +20,7 @@
|
|||||||
TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||||
using namespace cfdp;
|
using namespace cfdp;
|
||||||
using namespace returnvalue;
|
using namespace returnvalue;
|
||||||
|
using namespace std::filesystem;
|
||||||
MessageQueueId_t destQueueId = 2;
|
MessageQueueId_t destQueueId = 2;
|
||||||
AcceptsTmMock tmReceiver(destQueueId);
|
AcceptsTmMock tmReceiver(destQueueId);
|
||||||
MessageQueueMock mqMock(destQueueId);
|
MessageQueueMock mqMock(destQueueId);
|
||||||
@ -36,4 +39,22 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
|||||||
StorageManagerMock tmStore(3, storeCfg);
|
StorageManagerMock tmStore(3, storeCfg);
|
||||||
FsfwParams fp(tmReceiver, &mqMock, &eventReporterMock);
|
FsfwParams fp(tmReceiver, &mqMock, &eventReporterMock);
|
||||||
auto sourceHandler = SourceHandler(dp, fp);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user
boop
Will be added when fault declaration works properly