Bump FSFW #31
@ -32,6 +32,7 @@ add_subdirectory(timemanager)
|
|||||||
add_subdirectory(tmtcpacket)
|
add_subdirectory(tmtcpacket)
|
||||||
add_subdirectory(tmtcservices)
|
add_subdirectory(tmtcservices)
|
||||||
add_subdirectory(filesystem)
|
add_subdirectory(filesystem)
|
||||||
|
add_subdirectory(util)
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#include "fsfw/serialize/SerializeAdapter.h"
|
#include "fsfw/serialize/SerializeAdapter.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() {
|
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
|
||||||
ReturnValue_t result = this->setValue(width, value);
|
ReturnValue_t result = this->setValueAndWidth(width, value);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
#if FSFW_DISABLE_PRINTOUT == 0
|
#if FSFW_DISABLE_PRINTOUT == 0
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -20,8 +20,8 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
|
|||||||
|
|
||||||
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
|
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
|
||||||
|
|
||||||
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) {
|
ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) {
|
||||||
switch (widthInBytes) {
|
switch (width_) {
|
||||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||||
if (value_ > UINT8_MAX) {
|
if (value_ > UINT8_MAX) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
@ -43,15 +43,18 @@ ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_
|
|||||||
this->value.fourBytes = value_;
|
this->value.fourBytes = value_;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||||
|
this->value.eightBytes = value_;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->width = widthInBytes;
|
this->width = width_;
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cfdp::VarLenField::getValue() const {
|
uint64_t cfdp::VarLenField::getValue() const {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||||
return value.oneByte;
|
return value.oneByte;
|
||||||
@ -62,6 +65,9 @@ size_t cfdp::VarLenField::getValue() const {
|
|||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
return value.fourBytes;
|
return value.fourBytes;
|
||||||
}
|
}
|
||||||
|
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||||
|
return value.eightBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -84,6 +90,10 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
|
|||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
|
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
|
||||||
}
|
}
|
||||||
|
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||||
|
return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize,
|
||||||
|
streamEndianness);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
@ -98,6 +108,10 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui
|
|||||||
return deSerialize(buffer, size, streamEndianness);
|
return deSerialize(buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t cfdp::VarLenField::setValue(uint64_t value_) {
|
||||||
|
return setValueAndWidth(getWidth(), value_);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
|
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
Endianness streamEndianness) {
|
Endianness streamEndianness) {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
@ -112,6 +126,9 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
|
|||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
|
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||||
|
return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ class VarLenField : public SerializeIF {
|
|||||||
bool operator!=(const VarLenField &other) const;
|
bool operator!=(const VarLenField &other) const;
|
||||||
bool operator<(const VarLenField &other) const;
|
bool operator<(const VarLenField &other) const;
|
||||||
|
|
||||||
ReturnValue_t setValue(cfdp::WidthInBytes, size_t value);
|
ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value);
|
||||||
|
ReturnValue_t setValue(uint64_t value);
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
@ -64,7 +65,7 @@ template <typename T>
|
|||||||
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
|
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
|
||||||
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
|
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
|
||||||
static_assert((sizeof(T) % 2) == 0);
|
static_assert((sizeof(T) % 2) == 0);
|
||||||
setValue(width, byteField.getValue());
|
setValueAndWidth(width, byteField.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EntityId : public VarLenField {
|
struct EntityId : public VarLenField {
|
||||||
|
@ -68,6 +68,7 @@ enum WidthInBytes : uint8_t {
|
|||||||
ONE_BYTE = 1,
|
ONE_BYTE = 1,
|
||||||
TWO_BYTES = 2,
|
TWO_BYTES = 2,
|
||||||
FOUR_BYTES = 4,
|
FOUR_BYTES = 4,
|
||||||
|
EIGHT_BYTES = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileDirective : uint8_t {
|
enum FileDirective : uint8_t {
|
||||||
|
@ -9,12 +9,33 @@
|
|||||||
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
||||||
#include "fsfw/filesystem/HasFileSystemIF.h"
|
#include "fsfw/filesystem/HasFileSystemIF.h"
|
||||||
#include "fsfw/objectmanager.h"
|
#include "fsfw/objectmanager.h"
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||||
|
|
||||||
using namespace returnvalue;
|
using namespace returnvalue;
|
||||||
|
|
||||||
cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
|
cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
|
||||||
: sourceParams(std::move(params)), fsfwParams(fsfwParams) {}
|
: sourceParams(std::move(params)), fsfwParams(fsfwParams) {
|
||||||
|
// The entity ID portion of the transaction ID will always remain fixed.
|
||||||
|
transactionParams.id.entityId = sourceParams.cfg.localId;
|
||||||
|
if (sourceParams.seqCountProvider.bitWidth() == 8) {
|
||||||
|
transactionParams.seqCountWidth = cfdp::WidthInBytes::ONE_BYTE;
|
||||||
|
} else if (sourceParams.seqCountProvider.bitWidth() == 16) {
|
||||||
|
transactionParams.seqCountWidth = cfdp::WidthInBytes::TWO_BYTES;
|
||||||
|
} else if (sourceParams.seqCountProvider.bitWidth() == 32) {
|
||||||
|
transactionParams.seqCountWidth = cfdp::WidthInBytes::FOUR_BYTES;
|
||||||
|
} else {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "cfdp::SourceHandler: Seq count provider bit width "
|
||||||
|
<< sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n",
|
||||||
|
sourceParams.seqCountProvider.bitWidth());
|
||||||
|
#endif
|
||||||
|
// Yeah, what am I supposed to do here? Can't throw an exception in the FSFW..
|
||||||
|
transactionParams.seqCountWidth = cfdp::WidthInBytes::ONE_BYTE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
@ -22,6 +43,7 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
|||||||
step = TransactionStep::TRANSACTION_START;
|
step = TransactionStep::TRANSACTION_START;
|
||||||
}
|
}
|
||||||
if (step == TransactionStep::TRANSACTION_START) {
|
if (step == TransactionStep::TRANSACTION_START) {
|
||||||
|
sourceParams.user.transactionIndication(transactionParams.id);
|
||||||
step = TransactionStep::CRC_PROCEDURE;
|
step = TransactionStep::CRC_PROCEDURE;
|
||||||
}
|
}
|
||||||
if (step == TransactionStep::CRC_PROCEDURE) {
|
if (step == TransactionStep::CRC_PROCEDURE) {
|
||||||
@ -50,7 +72,14 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
|||||||
if (result != OK) {
|
if (result != OK) {
|
||||||
// TODO: Error handling
|
// TODO: Error handling
|
||||||
}
|
}
|
||||||
return fsmResult;
|
if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
|
||||||
|
sourceParams.user.eofSentIndication(transactionParams.id);
|
||||||
|
}
|
||||||
|
if (transactionParams.closureRequested) {
|
||||||
|
step = TransactionStep::WAIT_FOR_FINISH;
|
||||||
|
return fsmResult;
|
||||||
|
}
|
||||||
|
step = TransactionStep::NOTICE_OF_COMPLETION;
|
||||||
}
|
}
|
||||||
if (step == TransactionStep::WAIT_FOR_FINISH) {
|
if (step == TransactionStep::WAIT_FOR_FINISH) {
|
||||||
// TODO: In case this is a request with closure, wait for finish.
|
// TODO: In case this is a request with closure, wait for finish.
|
||||||
@ -58,11 +87,8 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
|||||||
step = TransactionStep::NOTICE_OF_COMPLETION;
|
step = TransactionStep::NOTICE_OF_COMPLETION;
|
||||||
}
|
}
|
||||||
if (step == TransactionStep::NOTICE_OF_COMPLETION) {
|
if (step == TransactionStep::NOTICE_OF_COMPLETION) {
|
||||||
// TODO: Notice of completion
|
noticeOfCompletion();
|
||||||
// We are done, go back to idle state.
|
reset();
|
||||||
// TODO: Possible reset state?
|
|
||||||
step = TransactionStep::IDLE;
|
|
||||||
state = CfdpState::IDLE;
|
|
||||||
}
|
}
|
||||||
return fsmResult;
|
return fsmResult;
|
||||||
}
|
}
|
||||||
@ -78,6 +104,11 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
|
ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
|
||||||
|
if (transactionParams.fileSize.value() == 0) {
|
||||||
|
// NULL checksum for empty file.
|
||||||
|
transactionParams.crc = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
std::array<uint8_t, 1024> buf{};
|
std::array<uint8_t, 1024> buf{};
|
||||||
etl::crc32 crcCalc;
|
etl::crc32 crcCalc;
|
||||||
uint64_t currentOffset = 0;
|
uint64_t currentOffset = 0;
|
||||||
@ -135,6 +166,7 @@ ReturnValue_t cfdp::SourceHandler::putRequest(PutRequestFull& putRequest, Remote
|
|||||||
// 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;
|
||||||
|
transactionParams.id.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement());
|
||||||
|
|
||||||
if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) {
|
if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) {
|
||||||
state = cfdp::CfdpState::BUSY_CLASS_2_ACKED;
|
state = cfdp::CfdpState::BUSY_CLASS_2_ACKED;
|
||||||
@ -206,14 +238,13 @@ ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
|
ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
|
||||||
// TODO: Checksum
|
auto eofInfo =
|
||||||
auto eofInfo = EofInfo(ConditionCode::NO_ERROR, 0, transactionParams.fileSize);
|
EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize);
|
||||||
auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
|
auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
|
||||||
ReturnValue_t result = sendGenericPdu(eofPdu);
|
ReturnValue_t result = sendGenericPdu(eofPdu);
|
||||||
if (result != OK) {
|
if (result != OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
step = TransactionStep::WAIT_FOR_FINISH;
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,3 +286,20 @@ ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) const
|
|||||||
TmTcMessage tcMsg(storeId);
|
TmTcMessage tcMsg(storeId);
|
||||||
return fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tcMsg);
|
return fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tcMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
transactionParams.reset();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
@ -11,15 +11,17 @@
|
|||||||
#include "fsfw/events/EventReportingProxyIF.h"
|
#include "fsfw/events/EventReportingProxyIF.h"
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||||
|
#include "fsfw/util/ProvidesSeqCountIF.h"
|
||||||
|
|
||||||
namespace cfdp {
|
namespace cfdp {
|
||||||
|
|
||||||
struct SourceHandlerParams {
|
struct SourceHandlerParams {
|
||||||
SourceHandlerParams(LocalEntityCfg cfg, UserBase& user) : cfg(std::move(cfg)), user(user) {}
|
SourceHandlerParams(LocalEntityCfg cfg, UserBase& user, ProvidesSeqCountIF& seqCountProvider)
|
||||||
|
: cfg(std::move(cfg)), user(user), seqCountProvider(seqCountProvider) {}
|
||||||
|
|
||||||
LocalEntityCfg cfg;
|
LocalEntityCfg cfg;
|
||||||
UserBase& user;
|
UserBase& user;
|
||||||
size_t maxFilePathSize = 256;
|
ProvidesSeqCountIF& seqCountProvider;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SourceHandler {
|
class SourceHandler {
|
||||||
@ -69,7 +71,18 @@ class SourceHandler {
|
|||||||
bool closureRequested = false;
|
bool closureRequested = false;
|
||||||
RemoteEntityCfg remoteCfg;
|
RemoteEntityCfg remoteCfg;
|
||||||
PduConfig pduConf;
|
PduConfig pduConf;
|
||||||
|
cfdp::TransactionId id{};
|
||||||
|
cfdp::WidthInBytes seqCountWidth;
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
sourceNameSize = 0;
|
||||||
|
destNameSize = 0;
|
||||||
|
fileSize.setFileSize(0, false);
|
||||||
|
progress = 0;
|
||||||
|
closureRequested = false;
|
||||||
|
}
|
||||||
} transactionParams;
|
} transactionParams;
|
||||||
|
|
||||||
cfdp::CfdpState state = cfdp::CfdpState::IDLE;
|
cfdp::CfdpState state = cfdp::CfdpState::IDLE;
|
||||||
TransactionStep step = TransactionStep::IDLE;
|
TransactionStep step = TransactionStep::IDLE;
|
||||||
std::array<uint8_t, 4096> fileBuf{};
|
std::array<uint8_t, 4096> fileBuf{};
|
||||||
@ -82,8 +95,10 @@ class SourceHandler {
|
|||||||
ReturnValue_t prepareAndSendMetadataPdu();
|
ReturnValue_t prepareAndSendMetadataPdu();
|
||||||
ReturnValue_t prepareAndSendNextFileDataPdu();
|
ReturnValue_t prepareAndSendNextFileDataPdu();
|
||||||
ReturnValue_t prepareAndSendEofPdu();
|
ReturnValue_t prepareAndSendEofPdu();
|
||||||
|
ReturnValue_t noticeOfCompletion();
|
||||||
|
ReturnValue_t reset();
|
||||||
|
|
||||||
ReturnValue_t sendGenericPdu(const SerializeIF& pdu) const;
|
[[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
@ -103,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
|
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
|
||||||
void *sourcePtr) const {
|
void *sourcePtr) {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||||
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
|
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
|
||||||
field->setValue(width, *fieldTyped);
|
field->setValueAndWidth(width, *fieldTyped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::TWO_BYTES): {
|
case (cfdp::WidthInBytes::TWO_BYTES): {
|
||||||
@ -115,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
|
|||||||
size_t deserSize = 0;
|
size_t deserSize = 0;
|
||||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||||
SerializeIF::Endianness::NETWORK);
|
SerializeIF::Endianness::NETWORK);
|
||||||
field->setValue(width, fieldTyped);
|
field->setValueAndWidth(width, fieldTyped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||||
@ -123,7 +123,15 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
|
|||||||
size_t deserSize = 0;
|
size_t deserSize = 0;
|
||||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||||
SerializeIF::Endianness::NETWORK);
|
SerializeIF::Endianness::NETWORK);
|
||||||
field->setValue(width, fieldTyped);
|
field->setValueAndWidth(width, fieldTyped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||||
|
uint64_t fieldTyped = 0;
|
||||||
|
size_t deserSize = 0;
|
||||||
|
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||||
|
SerializeIF::Endianness::NETWORK);
|
||||||
|
field->setValueAndWidth(width, fieldTyped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,8 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
|
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
|
||||||
void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const;
|
static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
|
||||||
|
void* sourcePtr);
|
||||||
void* sourceIdRaw = nullptr;
|
void* sourceIdRaw = nullptr;
|
||||||
void* seqNumRaw = nullptr;
|
void* seqNumRaw = nullptr;
|
||||||
void* destIdRaw = nullptr;
|
void* destIdRaw = nullptr;
|
||||||
|
1
src/fsfw/util/CMakeLists.txt
Normal file
1
src/fsfw/util/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME} PRIVATE)
|
19
src/fsfw/util/ProvidesSeqCountIF.h
Normal file
19
src/fsfw/util/ProvidesSeqCountIF.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class ProvidesSeqCountIF {
|
||||||
|
public:
|
||||||
|
virtual ~ProvidesSeqCountIF() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual unsigned int bitWidth() const = 0;
|
||||||
|
|
||||||
|
virtual uint64_t get() = 0;
|
||||||
|
virtual void increment() = 0;
|
||||||
|
|
||||||
|
virtual uint64_t getAndIncrement() {
|
||||||
|
uint64_t val = get();
|
||||||
|
increment();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
25
src/fsfw/util/SeqCountProvider.h
Normal file
25
src/fsfw/util/SeqCountProvider.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "ProvidesSeqCountIF.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class SeqCountProvider : public ProvidesSeqCountIF {
|
||||||
|
static_assert(std::is_same<T, uint8_t>::value || std::is_same<T, uint16_t>::value ||
|
||||||
|
std::is_same<T, uint32_t>::value,
|
||||||
|
"Only uint8_t, uint16_t, and uint32_t are allowed.");
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] unsigned int bitWidth() const override { return sizeof(T) * 8; }
|
||||||
|
uint64_t get() override { return counter; }
|
||||||
|
// I'm also abusing the primitive C variable overflow wrap around here.
|
||||||
|
void increment() override { counter++; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T counter{};
|
||||||
|
};
|
||||||
|
|
||||||
|
using SeqCountProviderU8 = SeqCountProvider<uint8_t>;
|
||||||
|
using SeqCountProviderU16 = SeqCountProvider<uint16_t>;
|
||||||
|
using SeqCountProviderU32 = SeqCountProvider<uint32_t>;
|
@ -5,6 +5,7 @@
|
|||||||
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
||||||
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
||||||
|
#include "fsfw/util/SeqCountProvider.h"
|
||||||
#include "mocks/AcceptsTmMock.h"
|
#include "mocks/AcceptsTmMock.h"
|
||||||
#include "mocks/EventReportingProxyMock.h"
|
#include "mocks/EventReportingProxyMock.h"
|
||||||
#include "mocks/FilesystemMock.h"
|
#include "mocks/FilesystemMock.h"
|
||||||
@ -26,7 +27,8 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
|||||||
LocalEntityCfg localEntityCfg(localId, IndicationCfg(), fhMock);
|
LocalEntityCfg localEntityCfg(localId, IndicationCfg(), fhMock);
|
||||||
FilesystemMock fsMock;
|
FilesystemMock fsMock;
|
||||||
UserMock userMock(fsMock);
|
UserMock userMock(fsMock);
|
||||||
SourceHandlerParams dp(localEntityCfg, userMock);
|
SeqCountProviderU16 seqCountProvider;
|
||||||
|
SourceHandlerParams dp(localEntityCfg, userMock, seqCountProvider);
|
||||||
|
|
||||||
EventReportingProxyMock eventReporterMock;
|
EventReportingProxyMock eventReporterMock;
|
||||||
LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}};
|
LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}};
|
||||||
|
@ -110,9 +110,9 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Other variable sized fields") {
|
SECTION("Other variable sized fields") {
|
||||||
pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||||
pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||||
REQUIRE(pduConf.sourceId.getSerializedSize() == 4);
|
REQUIRE(pduConf.sourceId.getSerializedSize() == 4);
|
||||||
REQUIRE(creator.getSerializedSize() == 14);
|
REQUIRE(creator.getSerializedSize() == 14);
|
||||||
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
|
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
|
||||||
@ -146,9 +146,9 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Buffer Too Short") {
|
SECTION("Buffer Too Short") {
|
||||||
pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||||
pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||||
for (uint8_t idx = 0; idx < 14; idx++) {
|
for (uint8_t idx = 0; idx < 14; idx++) {
|
||||||
REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) ==
|
REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) ==
|
||||||
SerializeIF::BUFFER_TOO_SHORT);
|
SerializeIF::BUFFER_TOO_SHORT);
|
||||||
@ -157,11 +157,11 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Invalid Variable Sized Fields") {
|
SECTION("Invalid Variable Sized Fields") {
|
||||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
|
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
|
||||||
REQUIRE(result == returnvalue::FAILED);
|
REQUIRE(result == returnvalue::FAILED);
|
||||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
|
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
|
||||||
REQUIRE(result == returnvalue::FAILED);
|
REQUIRE(result == returnvalue::FAILED);
|
||||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
|
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
|
||||||
REQUIRE(result == returnvalue::FAILED);
|
REQUIRE(result == returnvalue::FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
SerializeIF::Endianness::MACHINE);
|
SerializeIF::Endianness::MACHINE);
|
||||||
REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0);
|
REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0);
|
||||||
|
|
||||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 1);
|
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 1);
|
||||||
serTarget = serBuf.data();
|
serTarget = serBuf.data();
|
||||||
serSize = 1;
|
serSize = 1;
|
||||||
result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE);
|
result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE);
|
||||||
@ -257,11 +257,11 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||||||
creator.setPduType(cfdp::PduType::FILE_DATA);
|
creator.setPduType(cfdp::PduType::FILE_DATA);
|
||||||
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
|
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
|
||||||
result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
result = pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||||
REQUIRE(result == returnvalue::OK);
|
REQUIRE(result == returnvalue::OK);
|
||||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||||
REQUIRE(result == returnvalue::OK);
|
REQUIRE(result == returnvalue::OK);
|
||||||
result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
result = pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||||
REQUIRE(result == returnvalue::OK);
|
REQUIRE(result == returnvalue::OK);
|
||||||
serTarget = serBuf.data();
|
serTarget = serBuf.data();
|
||||||
serSize = 0;
|
serSize = 0;
|
||||||
@ -302,8 +302,8 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
SECTION("Manipulate Source Dest ID") {
|
SECTION("Manipulate Source Dest ID") {
|
||||||
serTarget = serBuf.data();
|
serTarget = serBuf.data();
|
||||||
serSize = 0;
|
serSize = 0;
|
||||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22);
|
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 22);
|
||||||
pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48);
|
pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 48);
|
||||||
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
|
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
|
||||||
reader.getSourceId(sourceDestId);
|
reader.getSourceId(sourceDestId);
|
||||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||||
|
@ -40,7 +40,7 @@ TEST_CASE("CFDP TLV", "[cfdp][tlv]") {
|
|||||||
SECTION("TLV Other Value") {
|
SECTION("TLV Other Value") {
|
||||||
auto tlv = Tlv(TlvType::ENTITY_ID, rawBuf.data(), deserSize);
|
auto tlv = Tlv(TlvType::ENTITY_ID, rawBuf.data(), deserSize);
|
||||||
// Set new value
|
// Set new value
|
||||||
sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12);
|
sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 12);
|
||||||
REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(),
|
REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||||
tlv.setValue(rawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES);
|
tlv.setValue(rawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES);
|
||||||
|
@ -1 +1,2 @@
|
|||||||
target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp)
|
target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp
|
||||||
|
testSeqCountProvider.cpp)
|
||||||
|
35
unittests/util/testSeqCountProvider.cpp
Normal file
35
unittests/util/testSeqCountProvider.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "fsfw/util/SeqCountProvider.h"
|
||||||
|
|
||||||
|
TEST_CASE("Seq Count Providers", "[util]") {
|
||||||
|
auto genericProviderTest = [](ProvidesSeqCountIF& provider, unsigned expectedWidth) {
|
||||||
|
CHECK(provider.get() == 0);
|
||||||
|
CHECK(provider.bitWidth() == expectedWidth);
|
||||||
|
CHECK(provider.getAndIncrement() == 0);
|
||||||
|
CHECK(provider.getAndIncrement() == 1);
|
||||||
|
CHECK(provider.get() == 2);
|
||||||
|
provider.increment();
|
||||||
|
provider.increment();
|
||||||
|
CHECK(provider.get() == 4);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
SeqCountProviderU16 provider;
|
||||||
|
genericProviderTest(provider, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SeqCountProviderU32 provider;
|
||||||
|
genericProviderTest(provider, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SeqCountProviderU8 provider;
|
||||||
|
genericProviderTest(provider, 8);
|
||||||
|
for (unsigned i = 4; i < UINT8_MAX + 1; i++) {
|
||||||
|
provider.increment();
|
||||||
|
}
|
||||||
|
// Verify wrap-around.
|
||||||
|
CHECK(provider.get() == 0);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user