Added CFDP packet stack

This PR adds the packet stack for the CCSDS File Delivery Protocol.
It also refactors the existing TMTC infastructure to allow sending
of CFDP packets to the CCSDS handlers.

This includes the whole PDU (Protocol Data Unit) stack:

- File Data PDUs

and all file directive PDUs

- ACK PDU
- NAK PDU
- Metadata PDU
- Finished PDU
- Prompt PDU
- Keep Alive PDU
- EOF PDU

The PR includes a full set of unittests for the packet stack
with a coverage of 90+ %.

The refactoring of the existing TMTC infastructure includes non-ideal
solutions like diamond inheritance.
Avoiding this solution would require refactoring the packet stack.
This would be a good idea anyway because the existing stack is tightly
coupled to the FSFW, making reuse more difficult if only the stack is
planned to be used without the store functionalities etc.

The PDU implementation provided here is only weakly coupled to the FSFW,
only using components like returnvalues or the Serialization modules.
There are dedicated serializers and deserializers, which also helps in
creating small focused modules which are easy to test.

Some of the modules here were provied by Matthias Tompert.
This commit is contained in:
Robin Müller 2021-12-03 15:37:49 +01:00
parent bf31248a50
commit 5907f8ee9d
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
167 changed files with 7801 additions and 1121 deletions

View File

@ -189,13 +189,13 @@ if(FSFW_BUILD_UNITTESTS)
"--exclude-unreachable-branches" "--exclude-unreachable-branches"
) )
set(COVERAGE_EXCLUDES set(COVERAGE_EXCLUDES
"/c/msys64/mingw64/*" "/c/msys64/mingw64/*" "*/fsfw_hal/*"
) )
elseif(UNIX) elseif(UNIX)
set(COVERAGE_EXCLUDES set(COVERAGE_EXCLUDES
"/usr/include/*" "/usr/bin/*" "Catch2/*" "/usr/include/*" "/usr/bin/*" "Catch2/*"
"/usr/local/include/*" "*/fsfw_tests/*" "/usr/local/include/*" "*/fsfw_tests/*"
"*/catch2-src/*" "*/catch2-src/*" "*/fsfw_hal/*"
) )
endif() endif()

View File

@ -91,7 +91,7 @@ You can use the following commands inside the `fsfw` folder to set up the build
```sh ```sh
mkdir build-Unittest && cd build-Unittest mkdir build-Unittest && cd build-Unittest
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host .. cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
``` ```
You can also use `-DFSFW_OSAL=linux` on Linux systems. You can also use `-DFSFW_OSAL=linux` on Linux systems.

View File

@ -10,7 +10,7 @@
*/ */
namespace addresses { namespace addresses {
/* Logical addresses have uint32_t datatype */ /* Logical addresses have uint32_t datatype */
enum logicalAddresses: address_t { enum LogAddr: address_t {
}; };
} }

View File

@ -1,6 +1,7 @@
# Core # Core
add_subdirectory(action) add_subdirectory(action)
add_subdirectory(cfdp)
add_subdirectory(container) add_subdirectory(container)
add_subdirectory(controller) add_subdirectory(controller)
add_subdirectory(datapool) add_subdirectory(datapool)

View File

@ -42,6 +42,10 @@
#define FSFW_USE_PUS_C_TELECOMMANDS 1 #define FSFW_USE_PUS_C_TELECOMMANDS 1
#endif #endif
#ifndef FSFW_TCP_RECV_WIRETAPPING_ENABLED
#define FSFW_TCP_RECV_WIRETAPPING_ENABLED 0
#endif
// FSFW HAL defines // FSFW HAL defines
// Can be used for low-level debugging of the SPI bus // Can be used for low-level debugging of the SPI bus

View File

@ -0,0 +1,60 @@
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/cfdp/CFDPHandler.h"
#include "fsfw/cfdp/CFDPMessage.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
object_id_t CFDPHandler::packetSource = 0;
object_id_t CFDPHandler::packetDestination = 0;
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist) : SystemObject(setObjectId) {
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
distributor = dist;
}
CFDPHandler::~CFDPHandler() {}
ReturnValue_t CFDPHandler::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
this->distributor->registerHandler(this);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t CFDPHandler::handleRequest(store_address_t storeId) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "CFDPHandler::handleRequest" << std::endl;
#else
sif::printDebug("CFDPHandler::handleRequest\n");
#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif
//TODO read out packet from store using storeId
return RETURN_OK;
}
ReturnValue_t CFDPHandler::performOperation(uint8_t opCode) {
ReturnValue_t status = RETURN_OK;
CommandMessage currentMessage;
for (status = this->requestQueue->receiveMessage(&currentMessage); status == RETURN_OK;
status = this->requestQueue->receiveMessage(&currentMessage)) {
store_address_t storeId = CFDPMessage::getStoreId(&currentMessage);
this->handleRequest(storeId);
}
return RETURN_OK;
}
uint16_t CFDPHandler::getIdentifier() {
return 0;
}
MessageQueueId_t CFDPHandler::getRequestQueue() {
return this->requestQueue->getId();
}

View File

@ -0,0 +1,62 @@
#ifndef FSFW_CFDP_CFDPHANDLER_H_
#define FSFW_CFDP_CFDPHANDLER_H_
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tcdistribution/CFDPDistributor.h"
#include "fsfw/ipc/MessageQueueIF.h"
namespace Factory{
void setStaticFrameworkObjectIds();
}
class CFDPHandler :
public ExecutableObjectIF,
public AcceptsTelecommandsIF,
public SystemObject,
public HasReturnvaluesIF {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
CFDPHandler(object_id_t setObjectId, CFDPDistributor* distributor);
/**
* The destructor is empty.
*/
virtual ~CFDPHandler();
virtual ReturnValue_t handleRequest(store_address_t storeId);
virtual ReturnValue_t initialize() override;
virtual uint16_t getIdentifier() override;
MessageQueueId_t getRequestQueue() override;
ReturnValue_t performOperation(uint8_t opCode) override;
protected:
/**
* This is a complete instance of the telecommand reception queue
* of the class. It is initialized on construction of the class.
*/
MessageQueueIF* requestQueue = nullptr;
CFDPDistributor* distributor = nullptr;
/**
* The current CFDP packet to be processed.
* It is deleted after handleRequest was executed.
*/
CFDPPacketStored currentPacket;
static object_id_t packetSource;
static object_id_t packetDestination;
private:
/**
* This constant sets the maximum number of packets accepted per call.
* Remember that one packet must be completely handled in one
* #handleRequest call.
*/
static const uint8_t CFDP_HANDLER_MAX_RECEPTION = 100;
};
#endif /* FSFW_CFDP_CFDPHANDLER_H_ */

View File

@ -0,0 +1,21 @@
#include "CFDPMessage.h"
CFDPMessage::CFDPMessage() {
}
CFDPMessage::~CFDPMessage() {
}
void CFDPMessage::setCommand(CommandMessage *message,
store_address_t cfdpPacket) {
message->setParameter(cfdpPacket.raw);
}
store_address_t CFDPMessage::getStoreId(const CommandMessage *message) {
store_address_t storeAddressCFDPPacket;
storeAddressCFDPPacket = message->getParameter();
return storeAddressCFDPPacket;
}
void CFDPMessage::clear(CommandMessage *message) {
}

View File

@ -0,0 +1,23 @@
#ifndef FSFW_CFDP_CFDPMESSAGE_H_
#define FSFW_CFDP_CFDPMESSAGE_H_
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
class CFDPMessage {
private:
CFDPMessage();
public:
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
virtual ~CFDPMessage();
static void setCommand(CommandMessage* message,
store_address_t cfdpPacket);
static store_address_t getStoreId(const CommandMessage* message);
static void clear(CommandMessage* message);
};
#endif /* FSFW_CFDP_CFDPMESSAGE_H_ */

View File

@ -0,0 +1,7 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
CFDPHandler.cpp
CFDPMessage.cpp
)
add_subdirectory(pdu)
add_subdirectory(tlv)

83
src/fsfw/cfdp/FileSize.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef FSFW_SRC_FSFW_CFDP_FILESIZE_H_
#define FSFW_SRC_FSFW_CFDP_FILESIZE_H_
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serialize/SerializeIF.h"
namespace cfdp {
struct FileSize: public SerializeIF {
public:
FileSize(): largeFile(false) {};
FileSize(uint64_t fileSize, bool isLarge = false) {
setFileSize(fileSize, isLarge);
};
ReturnValue_t serialize(bool isLarge, uint8_t **buffer, size_t *size,size_t maxSize,
Endianness streamEndianness) {
this->largeFile = isLarge;
return serialize(buffer, size, maxSize, streamEndianness);
}
ReturnValue_t serialize(uint8_t **buffer, size_t *size,size_t maxSize,
Endianness streamEndianness) const override {
if(not largeFile) {
uint32_t fileSizeTyped = fileSize;
return SerializeAdapter::serialize(&fileSizeTyped, buffer, size, maxSize,
streamEndianness);
}
return SerializeAdapter::serialize(&fileSize, buffer, size, maxSize, streamEndianness);
}
size_t getSerializedSize() const override {
if (largeFile) {
return 8;
} else {
return 4;
}
}
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override {
if(largeFile) {
return SerializeAdapter::deSerialize(&size, buffer, size, streamEndianness);
} else {
uint32_t sizeTmp = 0;
ReturnValue_t result = SerializeAdapter::deSerialize(&sizeTmp, buffer, size,
streamEndianness);
if(result == HasReturnvaluesIF::RETURN_OK) {
fileSize = sizeTmp;
}
return result;
}
}
ReturnValue_t setFileSize(uint64_t fileSize, bool largeFile) {
if (not largeFile and fileSize > UINT32_MAX) {
// TODO: emit warning here
return HasReturnvaluesIF::RETURN_FAILED;
}
this->fileSize = fileSize;
this->largeFile = largeFile;
return HasReturnvaluesIF::RETURN_OK;
}
bool isLargeFile() const {
return largeFile;
}
uint64_t getSize(bool* largeFile = nullptr) const {
if(largeFile != nullptr) {
*largeFile = this->largeFile;
}
return fileSize;
}
private:
uint64_t fileSize = 0;
bool largeFile = false;
};
}
#endif /* FSFW_SRC_FSFW_CFDP_FILESIZE_H_ */

153
src/fsfw/cfdp/definitions.h Normal file
View File

@ -0,0 +1,153 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_
#define FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_
#include <fsfw/serialize/SerializeIF.h>
#include <cstdint>
#include <cstddef>
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/returnvalues/FwClassIds.h"
namespace cfdp {
static constexpr uint8_t VERSION_BITS = 0b00100000;
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP;
static constexpr ReturnValue_t INVALID_TLV_TYPE =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 1);
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELDS =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 2);
static constexpr ReturnValue_t INVALID_PDU_DATAFIELD_LEN =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 3);
static constexpr ReturnValue_t INVALID_ACK_DIRECTIVE_FIELDS =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 4);
//! Can not parse options. This can also occur because there are options
//! available but the user did not pass a valid options array
static constexpr ReturnValue_t METADATA_CANT_PARSE_OPTIONS =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 5);
static constexpr ReturnValue_t NAK_CANT_PARSE_OPTIONS =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 6);
static constexpr ReturnValue_t FINISHED_CANT_PARSE_FS_RESPONSES =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 6);
static constexpr ReturnValue_t FILESTORE_REQUIRES_SECOND_FILE =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 8);
//! Can not parse filestore response because user did not pass a valid instance
//! or remaining size is invalid
static constexpr ReturnValue_t FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE =
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 9);
//! Checksum types according to the SANA Checksum Types registry
//! https://sanaregistry.org/r/checksum_identifiers/
enum ChecksumType {
// Modular legacy checksum
MODULAR = 0,
CRC_32_PROXIMITY_1 = 1,
CRC_32C = 2,
CRC_32 = 3,
NULL_CHECKSUM = 15
};
enum PduType: bool {
FILE_DIRECTIVE = 0,
FILE_DATA = 1
};
enum TransmissionModes: bool {
ACKNOWLEDGED = 0,
UNACKNOWLEDGED = 1
};
enum SegmentMetadataFlag: bool {
NOT_PRESENT = 0,
PRESENT = 1
};
enum Direction: bool {
TOWARDS_RECEIVER = 0,
TOWARDS_SENDER = 1
};
enum SegmentationControl: bool {
NO_RECORD_BOUNDARIES_PRESERVATION = 0,
RECORD_BOUNDARIES_PRESERVATION = 1
};
enum WidthInBytes: uint8_t {
// Only those are supported for now
ONE_BYTE = 1,
TWO_BYTES = 2,
FOUR_BYTES = 4,
};
enum FileDirectives: uint8_t {
INVALID_DIRECTIVE = 0x0f,
EOF_DIRECTIVE = 0x04,
FINISH = 0x05,
ACK = 0x06,
METADATA = 0x07,
NAK = 0x08,
PROMPT = 0x09,
KEEP_ALIVE = 0x0c
};
enum ConditionCode: uint8_t {
NO_CONDITION_FIELD = 0xff,
NO_ERROR = 0b0000,
POSITIVE_ACK_LIMIT_REACHED = 0b0001,
KEEP_ALIVE_LIMIT_REACHED = 0b0010,
INVALID_TRANSMISSION_MODE = 0b0011,
FILESTORE_REJECTION = 0b0100,
FILE_CHECKSUM_FAILURE = 0b0101,
FILE_SIZE_ERROR = 0b0110,
NAK_LIMIT_REACHED = 0b0111,
INACTIVITY_DETECTED = 0b1000,
CHECK_LIMIT_REACHED = 0b1010,
UNSUPPORTED_CHECKSUM_TYPE = 0b1011,
SUSPEND_REQUEST_RECEIVED = 0b1110,
CANCEL_REQUEST_RECEIVED = 0b1111
};
enum AckTransactionStatus {
UNDEFINED = 0b00,
ACTIVE = 0b01,
TERMINATED = 0b10,
UNRECOGNIZED = 0b11
};
enum FinishedDeliveryCode {
DATA_COMPLETE = 0,
DATA_INCOMPLETE = 1
};
enum FinishedFileStatus {
DISCARDED_DELIBERATELY = 0,
DISCARDED_FILESTORE_REJECTION = 1,
RETAINED_IN_FILESTORE = 2,
FILE_STATUS_UNREPORTED = 3
};
enum PromptResponseRequired: bool {
PROMPT_NAK = 0,
PROMPT_KEEP_ALIVE = 1
};
enum TlvTypes: uint8_t {
FILESTORE_REQUEST = 0x00,
FILESTORE_RESPONSE = 0x01,
MSG_TO_USER = 0x02,
FAULT_HANDLER = 0x04,
FLOW_LABEL = 0x05,
ENTITY_ID = 0x06,
INVALID_TLV = 0xff,
};
enum RecordContinuationState {
NO_START_NO_END = 0b00,
CONTAINS_START_NO_END = 0b01,
CONTAINS_END_NO_START = 0b10,
CONTAINS_START_AND_END = 0b11
};
}
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */

View File

@ -0,0 +1,52 @@
#include "AckInfo.h"
AckInfo::AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode):
ackedDirective(ackedDirective), ackedConditionCode(ackedConditionCode),
transactionStatus(transactionStatus), directiveSubtypeCode(directiveSubtypeCode) {
if (ackedDirective == cfdp::FileDirectives::FINISH) {
this->directiveSubtypeCode = 0b0001;
} else {
this->directiveSubtypeCode = 0b0000;
}
}
cfdp::ConditionCode AckInfo::getAckedConditionCode() const {
return ackedConditionCode;
}
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) {
this->ackedConditionCode = ackedConditionCode;
if (ackedDirective == cfdp::FileDirectives::FINISH) {
this->directiveSubtypeCode = 0b0001;
} else {
this->directiveSubtypeCode = 0b0000;
}
}
cfdp::FileDirectives AckInfo::getAckedDirective() const {
return ackedDirective;
}
void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective) {
this->ackedDirective = ackedDirective;
}
uint8_t AckInfo::getDirectiveSubtypeCode() const {
return directiveSubtypeCode;
}
void AckInfo::setDirectiveSubtypeCode(uint8_t directiveSubtypeCode) {
this->directiveSubtypeCode = directiveSubtypeCode;
}
cfdp::AckTransactionStatus AckInfo::getTransactionStatus() const {
return transactionStatus;
}
AckInfo::AckInfo() {
}
void AckInfo::setTransactionStatus(cfdp::AckTransactionStatus transactionStatus) {
this->transactionStatus = transactionStatus;
}

View File

@ -0,0 +1,33 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_ACKINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_ACKINFO_H_
#include "../definitions.h"
class AckInfo {
public:
AckInfo();
AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0);
cfdp::ConditionCode getAckedConditionCode() const;
void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode);
cfdp::FileDirectives getAckedDirective() const;
void setAckedDirective(cfdp::FileDirectives ackedDirective);
uint8_t getDirectiveSubtypeCode() const;
void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode);
cfdp::AckTransactionStatus getTransactionStatus() const;
void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus);
private:
cfdp::FileDirectives ackedDirective = cfdp::FileDirectives::INVALID_DIRECTIVE;
cfdp::ConditionCode ackedConditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
cfdp::AckTransactionStatus transactionStatus = cfdp::AckTransactionStatus::UNDEFINED;
uint8_t directiveSubtypeCode = 0;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_ACKINFO_H_ */

View File

@ -0,0 +1,38 @@
#include "AckPduDeserializer.h"
AckPduDeserializer::AckPduDeserializer(const uint8_t *pduBuf, size_t maxSize, AckInfo& info):
FileDirectiveDeserializer(pduBuf, maxSize), info(info) {
}
ReturnValue_t AckPduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
if (currentIdx + 2 > this->maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
if(not checkAndSetCodes(rawPtr[currentIdx], rawPtr[currentIdx + 1])) {
return cfdp::INVALID_ACK_DIRECTIVE_FIELDS;
}
return HasReturnvaluesIF::RETURN_OK;
}
bool AckPduDeserializer::checkAndSetCodes(uint8_t firstByte, uint8_t secondByte) {
uint8_t ackedDirective = static_cast<cfdp::FileDirectives>(firstByte >> 4);
if(ackedDirective != cfdp::FileDirectives::EOF_DIRECTIVE and
ackedDirective != cfdp::FileDirectives::FINISH) {
return false;
}
this->info.setAckedDirective(static_cast<cfdp::FileDirectives>(ackedDirective));
uint8_t directiveSubtypeCode = firstByte & 0x0f;
if(directiveSubtypeCode != 0b0000 and directiveSubtypeCode != 0b0001) {
return false;
}
this->info.setDirectiveSubtypeCode(directiveSubtypeCode);
this->info.setAckedConditionCode(static_cast<cfdp::ConditionCode>(secondByte >> 4));
this->info.setTransactionStatus(static_cast<cfdp::AckTransactionStatus>(secondByte & 0x0f));
return true;
}

View File

@ -0,0 +1,26 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
#include "AckInfo.h"
class AckPduDeserializer: public FileDirectiveDeserializer {
public:
AckPduDeserializer(const uint8_t* pduBuf, size_t maxSize, AckInfo& info);
/**
*
* @return
* - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields
*/
ReturnValue_t parseData();
private:
bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode);
AckInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,38 @@
#include "AckPduSerializer.h"
AckPduSerializer::AckPduSerializer(AckInfo& ackInfo, PduConfig &pduConf):
FileDirectiveSerializer(pduConf, cfdp::FileDirectives::ACK, 2),
ackInfo(ackInfo) {
}
size_t AckPduSerializer::getSerializedSize() const {
return FileDirectiveSerializer::getWholePduSize();
}
ReturnValue_t AckPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
cfdp::FileDirectives ackedDirective = ackInfo.getAckedDirective();
uint8_t directiveSubtypeCode = ackInfo.getDirectiveSubtypeCode();
cfdp::ConditionCode ackedConditionCode = ackInfo.getAckedConditionCode();
cfdp::AckTransactionStatus transactionStatus = ackInfo.getTransactionStatus();
if(ackedDirective != cfdp::FileDirectives::FINISH and
ackedDirective != cfdp::FileDirectives::EOF_DIRECTIVE) {
// TODO: better returncode
return HasReturnvaluesIF::RETURN_FAILED;
}
if(*size + 2 > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = ackedDirective << 4 | directiveSubtypeCode;
*buffer += 1;
*size += 1;
**buffer = ackedConditionCode << 4 | transactionStatus;
*buffer += 1;
*size += 1;
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,30 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
#include "AckInfo.h"
#include "FileDirectiveDeserializer.h"
#include "FileDirectiveSerializer.h"
class AckPduSerializer: public FileDirectiveSerializer {
public:
/**
* @brief Serializer to pack ACK PDUs
* @details
* Please note that only Finished PDUs and EOF are acknowledged.
* @param ackedDirective
* @param ackedConditionCode
* @param transactionStatus
* @param pduConf
*/
AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf);
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
private:
AckInfo& ackInfo;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */

View File

@ -0,0 +1,32 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
PduConfig.cpp
VarLenField.cpp
HeaderSerializer.cpp
HeaderDeserializer.cpp
FileDirectiveDeserializer.cpp
FileDirectiveSerializer.cpp
AckInfo.cpp
AckPduSerializer.cpp
AckPduDeserializer.cpp
EofInfo.cpp
EofPduSerializer.cpp
EofPduDeserializer.cpp
NakInfo.cpp
NakPduSerializer.cpp
NakPduDeserializer.cpp
FinishedInfo.cpp
FinishedPduSerializer.cpp
FinishedPduDeserializer.cpp
MetadataInfo.cpp
MetadataPduSerializer.cpp
MetadataPduDeserializer.cpp
KeepAlivePduSerializer.cpp
KeepAlivePduDeserializer.cpp
PromptPduSerializer.cpp
PromptPduDeserializer.cpp
FileDataSerializer.cpp
FileDataDeserializer.cpp
FileDataInfo.cpp
)

View File

@ -0,0 +1,58 @@
#include "EofInfo.h"
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
EntityIdTlv* faultLoc): conditionCode(conditionCode), checksum(checksum),
fileSize(fileSize), faultLoc(faultLoc) {
}
EofInfo::EofInfo(EntityIdTlv *faultLoc): conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
checksum(0), fileSize(0), faultLoc(faultLoc) {
}
uint32_t EofInfo::getChecksum() const {
return checksum;
}
cfdp::ConditionCode EofInfo::getConditionCode() const {
return conditionCode;
}
EntityIdTlv* EofInfo::getFaultLoc() const {
return faultLoc;
}
cfdp::FileSize& EofInfo::getFileSize() {
return fileSize;
}
void EofInfo::setChecksum(uint32_t checksum) {
this->checksum = checksum;
}
void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
this->conditionCode = conditionCode;
}
void EofInfo::setFaultLoc(EntityIdTlv *faultLoc) {
this->faultLoc = faultLoc;
}
size_t EofInfo::getSerializedSize(bool fssLarge) {
// Condition code + spare + 4 byte checksum
size_t size = 5;
if(fssLarge) {
size += 8;
} else {
size += 4;
}
// Do not account for fault location if the condition code is NO_ERROR. We assume that
// a serializer will not serialize the fault location here.
if(getFaultLoc() != nullptr and getConditionCode() != cfdp::ConditionCode::NO_ERROR) {
size+= faultLoc->getSerializedSize();
}
return size;
}
ReturnValue_t EofInfo::setFileSize(size_t fileSize, bool isLarge) {
return this->fileSize.setFileSize(fileSize, isLarge);
}

View File

@ -0,0 +1,33 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
#include "../definitions.h"
#include "../FileSize.h"
struct EofInfo {
public:
EofInfo(EntityIdTlv* faultLoc = nullptr);
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
EntityIdTlv* faultLoc = nullptr);
size_t getSerializedSize(bool fssLarge = false);
uint32_t getChecksum() const;
cfdp::ConditionCode getConditionCode() const;
EntityIdTlv* getFaultLoc() const;
cfdp::FileSize& getFileSize();
void setChecksum(uint32_t checksum);
void setConditionCode(cfdp::ConditionCode conditionCode);
void setFaultLoc(EntityIdTlv *faultLoc);
ReturnValue_t setFileSize(size_t size, bool isLarge);
private:
cfdp::ConditionCode conditionCode;
uint32_t checksum;
cfdp::FileSize fileSize;
EntityIdTlv* faultLoc = nullptr;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_ */

View File

@ -0,0 +1,68 @@
#include "EofPduDeserializer.h"
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
EofPduDeserializer::EofPduDeserializer(const uint8_t *pduBuf, size_t maxSize, EofInfo& eofInfo):
FileDirectiveDeserializer(pduBuf, maxSize), info(eofInfo) {
}
ReturnValue_t EofPduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
const uint8_t* bufPtr = rawPtr;
size_t expectedFileFieldLen = 4;
if(this->getLargeFileFlag()) {
expectedFileFieldLen = 8;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
size_t deserLen = maxSize;
if(maxSize < currentIdx + 5 + expectedFileFieldLen) {
return SerializeIF::STREAM_TOO_SHORT;
}
bufPtr += currentIdx;
deserLen -= currentIdx;
info.setConditionCode(static_cast<cfdp::ConditionCode>(*bufPtr >> 4));
bufPtr += 1;
deserLen -= 1;
uint32_t checksum = 0;
auto endianness = getEndianness();
result = SerializeAdapter::deSerialize(&checksum, &bufPtr, &deserLen, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
info.setChecksum(checksum);
if(this->getLargeFileFlag()) {
uint64_t fileSizeValue = 0;
result = SerializeAdapter::deSerialize(&fileSizeValue, &bufPtr, &deserLen, endianness);
info.setFileSize(fileSizeValue, true);
}
else {
uint32_t fileSizeValue = 0;
result = SerializeAdapter::deSerialize(&fileSizeValue, &bufPtr, &deserLen, endianness);
info.setFileSize(fileSizeValue, false);
}
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(info.getConditionCode() != cfdp::ConditionCode::NO_ERROR) {
EntityIdTlv* tlvPtr = info.getFaultLoc();
if(tlvPtr == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "EofPduDeserializer::parseData: Ca not deserialize fault location,"
" given TLV pointer invalid" << std::endl;
#else
sif::printWarning("EofPduDeserializer::parseData: Ca not deserialize fault location,"
" given TLV pointer invalid");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return HasReturnvaluesIF::RETURN_FAILED;
}
result = tlvPtr->deSerialize(&bufPtr, &deserLen, endianness);
}
return result;
}

View File

@ -0,0 +1,18 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
#include "EofInfo.h"
class EofPduDeserializer: public FileDirectiveDeserializer {
public:
EofPduDeserializer(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo);
virtual ReturnValue_t parseData() override;
private:
EofInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,46 @@
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
#include "EofPduSerializer.h"
EofPduSerializer::EofPduSerializer(PduConfig &conf, EofInfo& info):
FileDirectiveSerializer(conf, cfdp::FileDirectives::EOF_DIRECTIVE, 9), info(info) {
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
}
size_t EofPduSerializer::getSerializedSize() const {
return FileDirectiveSerializer::getWholePduSize();
}
ReturnValue_t EofPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(*size + 1 > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = info.getConditionCode() << 4;
*buffer += 1;
*size += 1;
uint32_t checksum = info.getChecksum();
result = SerializeAdapter::serialize(&checksum, buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(info.getFileSize().isLargeFile()) {
uint64_t fileSizeValue = info.getFileSize().getSize();
result = SerializeAdapter::serialize(&fileSizeValue, buffer, size,
maxSize, streamEndianness);
}
else {
uint32_t fileSizeValue = info.getFileSize().getSize();
result = SerializeAdapter::serialize(&fileSizeValue, buffer, size,
maxSize, streamEndianness);
}
if(info.getFaultLoc() != nullptr and info.getConditionCode() != cfdp::ConditionCode::NO_ERROR) {
result = info.getFaultLoc()->serialize(buffer, size, maxSize, streamEndianness);
}
return result;
}

View File

@ -0,0 +1,22 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
#include "EofInfo.h"
class EofPduSerializer: public FileDirectiveSerializer {
public:
EofPduSerializer(PduConfig &conf, EofInfo& info);
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
private:
EofInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_ */

View File

@ -0,0 +1,52 @@
#include "FileDataDeserializer.h"
FileDataDeserializer::FileDataDeserializer(const uint8_t *pduBuf, size_t maxSize,
FileDataInfo& info):
HeaderDeserializer(pduBuf, maxSize), info(info) {
}
ReturnValue_t FileDataDeserializer::parseData() {
ReturnValue_t result = HeaderDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = HeaderDeserializer::getHeaderSize();
const uint8_t* buf = rawPtr + currentIdx;
size_t remSize = HeaderDeserializer::getWholePduSize() - currentIdx;
if (remSize < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
if(hasSegmentMetadataFlag()) {
info.setSegmentMetadataFlag(true);
info.setRecordContinuationState(static_cast<cfdp::RecordContinuationState>(
(*buf >> 6) & 0b11));
size_t segmentMetadataLen = *buf & 0b00111111;
info.setSegmentMetadataLen(segmentMetadataLen);
if(remSize < segmentMetadataLen + 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
if(segmentMetadataLen > 0) {
buf += 1;
remSize -= 1;
info.setSegmentMetadata(buf);
buf += segmentMetadataLen;
remSize -= segmentMetadataLen;
}
}
result = info.getOffset().deSerialize(&buf, &remSize, this->getEndianness());
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(remSize > 0) {
info.setFileData(buf, remSize);
}
return HasReturnvaluesIF::RETURN_OK;
}
SerializeIF::Endianness FileDataDeserializer::getEndianness() const {
return endianness;
}
void FileDataDeserializer::setEndianness(SerializeIF::Endianness endianness) {
this->endianness = endianness;
}

View File

@ -0,0 +1,22 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATADESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATADESERIALIZER_H_
#include "FileDataInfo.h"
#include "HeaderDeserializer.h"
#include "../definitions.h"
class FileDataDeserializer: public HeaderDeserializer {
public:
FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info);
ReturnValue_t parseData();
SerializeIF::Endianness getEndianness() const;
void setEndianness(SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK);
private:
SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK;
FileDataInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDATADESERIALIZER_H_ */

View File

@ -0,0 +1,104 @@
#include "FileDataInfo.h"
FileDataInfo::FileDataInfo(cfdp::FileSize &offset, const uint8_t *fileData, size_t fileSize):
offset(offset), fileData(fileData), fileSize(fileSize) {
}
FileDataInfo::FileDataInfo(cfdp::FileSize &offset): offset(offset) {
}
void FileDataInfo::setSegmentMetadataFlag(bool enable) {
if(enable) {
segmentMetadataFlag = cfdp::SegmentMetadataFlag::PRESENT;
} else {
segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
}
}
size_t FileDataInfo::getSerializedSize(bool largeFile) const {
size_t sz = 0;
if(segmentMetadataFlag == cfdp::SegmentMetadataFlag::PRESENT) {
sz += 1 + segmentMetadataLen;
}
if(largeFile) {
sz += 8;
} else {
sz += 4;
}
sz += fileSize;
return sz;
}
cfdp::SegmentMetadataFlag FileDataInfo::getSegmentMetadataFlag() const {
return this->segmentMetadataFlag;
}
bool FileDataInfo::hasSegmentMetadata() const {
if(segmentMetadataFlag == cfdp::SegmentMetadataFlag::PRESENT) {
return true;
}
return false;
}
cfdp::RecordContinuationState FileDataInfo::getRecordContinuationState() const {
return this->recContState;
}
size_t FileDataInfo::getSegmentMetadataLen() const {
return segmentMetadataLen;
}
ReturnValue_t FileDataInfo::addSegmentMetadataInfo(cfdp::RecordContinuationState recContState,
const uint8_t* segmentMetadata, size_t segmentMetadataLen) {
this->segmentMetadataFlag = cfdp::SegmentMetadataFlag::PRESENT;
this->recContState = recContState;
if(segmentMetadataLen > 63) {
return HasReturnvaluesIF::RETURN_FAILED;
}
this->segmentMetadata = segmentMetadata;
this->segmentMetadataLen = segmentMetadataLen;
return HasReturnvaluesIF::RETURN_OK;
}
const uint8_t* FileDataInfo::getFileData(size_t *fileSize) const {
if(fileSize != nullptr) {
*fileSize = this->fileSize;
}
return fileData;
}
const uint8_t* FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen) {
if(segmentMetadataLen != nullptr) {
*segmentMetadataLen = this->segmentMetadataLen;
}
return segmentMetadata;
}
cfdp::FileSize& FileDataInfo::getOffset() {
return offset;
}
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
this->recContState = recContState;
}
void FileDataInfo::setSegmentMetadataLen(size_t len) {
this->segmentMetadataLen = len;
}
void FileDataInfo::setSegmentMetadata(const uint8_t *ptr) {
this->segmentMetadata = ptr;
}
void FileDataInfo::setFileData(const uint8_t *fileData, size_t fileSize) {
this->fileData = fileData;
this->fileSize = fileSize;
}
cfdp::SegmentationControl FileDataInfo::getSegmentationControl() const {
return segCtrl;
}
void FileDataInfo::setSegmentationControl(cfdp::SegmentationControl segCtrl) {
this->segCtrl = segCtrl;
}

View File

@ -0,0 +1,45 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#include <fsfw/cfdp/definitions.h>
#include <fsfw/cfdp/FileSize.h>
class FileDataInfo {
public:
FileDataInfo(cfdp::FileSize& offset);
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
size_t getSerializedSize(bool largeFile = false) const;
cfdp::FileSize& getOffset();
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
void setFileData(const uint8_t* fileData, size_t fileSize);
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const;
cfdp::SegmentationControl getSegmentationControl() const;
cfdp::RecordContinuationState getRecordContinuationState() const;
void setRecordContinuationState(cfdp::RecordContinuationState recContState);
void setSegmentationControl(cfdp::SegmentationControl segCtrl);
size_t getSegmentMetadataLen() const;
void setSegmentMetadataLen(size_t len);
void setSegmentMetadata(const uint8_t* ptr);
bool hasSegmentMetadata() const;
void setSegmentMetadataFlag(bool enable);
ReturnValue_t addSegmentMetadataInfo(cfdp::RecordContinuationState recContState,
const uint8_t* segmentMetadata, size_t segmentMetadataLen);
const uint8_t* getSegmentMetadata(size_t* segmentMetadataLen = nullptr);
private:
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
cfdp::SegmentationControl segCtrl =
cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
cfdp::FileSize& offset;
const uint8_t* fileData = nullptr;
size_t fileSize = 0;
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;
size_t segmentMetadataLen = 0;
const uint8_t* segmentMetadata = nullptr;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_ */

View File

@ -0,0 +1,54 @@
#include "FileDataSerializer.h"
#include <cstring>
FileDataSerializer::FileDataSerializer(PduConfig& conf, FileDataInfo& info):
HeaderSerializer(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()),
info(info) {
update();
}
void FileDataSerializer::update() {
this->setSegmentMetadataFlag(info.getSegmentMetadataFlag());
this->setSegmentationControl(info.getSegmentationControl());
setPduDataFieldLen(info.getSerializedSize(this->getLargeFileFlag()));
}
ReturnValue_t FileDataSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(*size + this->getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
const uint8_t* readOnlyPtr = nullptr;
if (this->hasSegmentMetadataFlag()) {
size_t segmentMetadataLen = info.getSegmentMetadataLen();
**buffer = info.getRecordContinuationState() << 6 | segmentMetadataLen;
*buffer += 1;
*size += 1;
readOnlyPtr = info.getSegmentMetadata();
std::memcpy(*buffer, readOnlyPtr, segmentMetadataLen);
*buffer += segmentMetadataLen;
*size += segmentMetadataLen;
}
cfdp::FileSize& offset = info.getOffset();
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t fileSize = 0;
readOnlyPtr = info.getFileData(&fileSize);
if(*size + fileSize > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
std::memcpy(*buffer, readOnlyPtr, fileSize);
*buffer += fileSize;
*size += fileSize;
return HasReturnvaluesIF::RETURN_OK;
}
size_t FileDataSerializer::getSerializedSize() const {
return HeaderSerializer::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag());
}

View File

@ -0,0 +1,23 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
#include "FileDataInfo.h"
#include "../definitions.h"
#include "HeaderSerializer.h"
class FileDataSerializer: public HeaderSerializer {
public:
FileDataSerializer(PduConfig& conf, FileDataInfo& info);
void update();
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
private:
FileDataInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDATADESERIALIZER_H_ */

View File

@ -0,0 +1,55 @@
#include "FileDirectiveDeserializer.h"
FileDirectiveDeserializer::FileDirectiveDeserializer(const uint8_t *pduBuf, size_t maxSize):
HeaderDeserializer(pduBuf, maxSize) {
}
cfdp::FileDirectives FileDirectiveDeserializer::getFileDirective() const {
return fileDirective;
}
ReturnValue_t FileDirectiveDeserializer::parseData() {
ReturnValue_t result = HeaderDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(this->getPduDataFieldLen() < 1) {
return cfdp::INVALID_PDU_DATAFIELD_LEN;
}
if(FileDirectiveDeserializer::getWholePduSize() > maxSize) {
return SerializeIF::STREAM_TOO_SHORT;
}
size_t currentIdx = HeaderDeserializer::getHeaderSize();
if(not checkFileDirective(rawPtr[currentIdx])) {
return cfdp::INVALID_DIRECTIVE_FIELDS;
}
setFileDirective(static_cast<cfdp::FileDirectives>(rawPtr[currentIdx]));
return HasReturnvaluesIF::RETURN_OK;
}
size_t FileDirectiveDeserializer::getHeaderSize() const {
// return size of header plus the directive byte
return HeaderDeserializer::getHeaderSize() + 1;
}
bool FileDirectiveDeserializer::checkFileDirective(uint8_t rawByte) {
if(rawByte < cfdp::FileDirectives::EOF_DIRECTIVE or
(rawByte > cfdp::FileDirectives::PROMPT and
rawByte != cfdp::FileDirectives::KEEP_ALIVE)) {
// Invalid directive field. TODO: Custom returnvalue
return false;
}
return true;
}
void FileDirectiveDeserializer::setFileDirective(cfdp::FileDirectives fileDirective) {
this->fileDirective = fileDirective;
}
void FileDirectiveDeserializer::setEndianness(SerializeIF::Endianness endianness) {
this->endianness = endianness;
}
SerializeIF::Endianness FileDirectiveDeserializer::getEndianness() const {
return endianness;
}

View File

@ -0,0 +1,41 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_
#include "../definitions.h"
#include "fsfw/cfdp/pdu/HeaderDeserializer.h"
/**
* @brief This class is used to deserialize a PDU file directive header from raw memory.
* @details
* Base class for other file directives.
* This is a zero-copy implementation and #parseData needs to be called to ensure the data is
* valid.
*/
class FileDirectiveDeserializer: public HeaderDeserializer {
public:
FileDirectiveDeserializer(const uint8_t* pduBuf, size_t maxSize);
/**
* This needs to be called before accessing the PDU fields to avoid segmentation faults.
* @return
*/
virtual ReturnValue_t parseData();
size_t getHeaderSize() const;
cfdp::FileDirectives getFileDirective() const;
void setEndianness(SerializeIF::Endianness endianness);
SerializeIF::Endianness getEndianness() const;
protected:
bool checkFileDirective(uint8_t rawByte);
private:
void setFileDirective(cfdp::FileDirectives fileDirective);
cfdp::FileDirectives fileDirective = cfdp::FileDirectives::INVALID_DIRECTIVE;
SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_ */

View File

@ -0,0 +1,39 @@
#include "FileDirectiveSerializer.h"
FileDirectiveSerializer::FileDirectiveSerializer(PduConfig &pduConf,
cfdp::FileDirectives directiveCode, size_t directiveParamFieldLen):
HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, directiveParamFieldLen + 1),
directiveCode(directiveCode) {
}
size_t FileDirectiveSerializer::getSerializedSize() const {
return HeaderSerializer::getSerializedSize() + 1;
}
ReturnValue_t FileDirectiveSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(FileDirectiveSerializer::getWholePduSize() > maxSize) {
return BUFFER_TOO_SHORT;
}
ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(*size >= maxSize) {
return BUFFER_TOO_SHORT;
}
**buffer = directiveCode;
*buffer += 1;
*size += 1;
return HasReturnvaluesIF::RETURN_OK;
}
void FileDirectiveSerializer::setDirectiveDataFieldLen(size_t len) {
// Set length of data field plus 1 byte for the directive octet
HeaderSerializer::setPduDataFieldLen(len + 1);
}

View File

@ -0,0 +1,28 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_
#include "fsfw/cfdp/pdu/HeaderSerializer.h"
class FileDirectiveSerializer: public HeaderSerializer {
public:
FileDirectiveSerializer(PduConfig& pduConf, cfdp::FileDirectives directiveCode,
size_t directiveParamFieldLen);
/**
* This only returns the size of the PDU header + 1 for the directive code octet.
* Use FileDirectiveSerializer::getWholePduSize to get the full packet length, assuming
* the length fields was set correctly
* @return
*/
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
void setDirectiveDataFieldLen(size_t len);
private:
cfdp::FileDirectives directiveCode = cfdp::FileDirectives::INVALID_DIRECTIVE;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ */

View File

@ -0,0 +1,111 @@
#include "FinishedInfo.h"
FinishedInfo::FinishedInfo() {
}
FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode,
cfdp::FinishedDeliveryCode deliveryCode, cfdp::FinishedFileStatus fileStatus):
conditionCode(conditionCode), deliveryCode(deliveryCode), fileStatus(fileStatus) {
}
size_t FinishedInfo::getSerializedSize() const {
size_t size = 1;
if(hasFsResponses()) {
for(size_t idx = 0; idx < fsResponsesLen; idx++) {
size += fsResponses[idx]->getSerializedSize();
}
}
if(this->faultLocation != nullptr) {
size += faultLocation->getSerializedSize();
}
return size;
}
bool FinishedInfo::hasFsResponses() const {
if(fsResponses != nullptr and fsResponsesLen > 0) {
return true;
}
return false;
}
bool FinishedInfo::canHoldFsResponses() const {
if(fsResponses != nullptr and fsResponsesMaxLen > 0) {
return true;
}
return false;
}
ReturnValue_t FinishedInfo::setFilestoreResponsesArray(FilestoreResponseTlv** fsResponses,
size_t* fsResponsesLen, const size_t* maxFsResponsesLen) {
this->fsResponses = fsResponses;
if(fsResponsesLen != nullptr) {
this->fsResponsesLen = *fsResponsesLen;
if(this->fsResponsesMaxLen < *fsResponsesLen) {
this->fsResponsesMaxLen = this->fsResponsesLen;
}
}
if(maxFsResponsesLen != nullptr) {
this->fsResponsesMaxLen = *maxFsResponsesLen;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FinishedInfo::getFilestoreResonses(FilestoreResponseTlv ***fsResponses,
size_t *fsResponsesLen, size_t* fsResponsesMaxLen) {
if(fsResponses == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
*fsResponses = this->fsResponses;
if(fsResponsesLen != nullptr) {
*fsResponsesLen = this->fsResponsesLen;
}
if(fsResponsesMaxLen != nullptr) {
*fsResponsesMaxLen = this->fsResponsesMaxLen;
}
return HasReturnvaluesIF::RETURN_OK;
}
void FinishedInfo::setFaultLocation(EntityIdTlv *faultLocation) {
this->faultLocation = faultLocation;
}
ReturnValue_t FinishedInfo::getFaultLocation(EntityIdTlv** faultLocation) {
if(this->faultLocation == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
*faultLocation = this->faultLocation;
return HasReturnvaluesIF::RETURN_OK;
}
cfdp::ConditionCode FinishedInfo::getConditionCode() const {
return conditionCode;
}
void FinishedInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
this->conditionCode = conditionCode;
}
cfdp::FinishedDeliveryCode FinishedInfo::getDeliveryCode() const {
return deliveryCode;
}
void FinishedInfo::setDeliveryCode(cfdp::FinishedDeliveryCode deliveryCode) {
this->deliveryCode = deliveryCode;
}
cfdp::FinishedFileStatus FinishedInfo::getFileStatus() const {
return fileStatus;
}
void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) {
this->fsResponsesLen = fsResponsesLen;
}
size_t FinishedInfo::getFsResponsesLen() const {
return fsResponsesLen;
}
void FinishedInfo::setFileStatus(cfdp::FinishedFileStatus fileStatus) {
this->fileStatus = fileStatus;
}

View File

@ -0,0 +1,45 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FINISHINFO_H_
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
#include "../definitions.h"
class FinishedInfo {
public:
FinishedInfo();
FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FinishedDeliveryCode deliveryCode,
cfdp::FinishedFileStatus fileStatus);
size_t getSerializedSize() const;
bool hasFsResponses() const;
bool canHoldFsResponses() const;
ReturnValue_t setFilestoreResponsesArray(FilestoreResponseTlv** fsResponses,
size_t* fsResponsesLen, const size_t* maxFsResponseLen);
void setFaultLocation(EntityIdTlv* entityId);
ReturnValue_t getFilestoreResonses(FilestoreResponseTlv ***fsResponses,
size_t *fsResponsesLen, size_t* fsResponsesMaxLen);
size_t getFsResponsesLen() const;
void setFilestoreResponsesArrayLen(size_t fsResponsesLen);
ReturnValue_t getFaultLocation(EntityIdTlv** entityId);
cfdp::ConditionCode getConditionCode() const;
void setConditionCode(cfdp::ConditionCode conditionCode);
cfdp::FinishedDeliveryCode getDeliveryCode() const;
void setDeliveryCode(cfdp::FinishedDeliveryCode deliveryCode);
cfdp::FinishedFileStatus getFileStatus() const;
void setFileStatus(cfdp::FinishedFileStatus fileStatus);
private:
cfdp::ConditionCode conditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
cfdp::FinishedDeliveryCode deliveryCode = cfdp::FinishedDeliveryCode::DATA_COMPLETE;
cfdp::FinishedFileStatus fileStatus = cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY;
FilestoreResponseTlv** fsResponses = nullptr;
size_t fsResponsesLen = 0;
size_t fsResponsesMaxLen = 0;
EntityIdTlv* faultLocation = nullptr;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FINISHINFO_H_ */

View File

@ -0,0 +1,90 @@
#include "FinishedPduDeserializer.h"
FinishPduDeserializer::FinishPduDeserializer(const uint8_t *pduBuf, size_t maxSize,
FinishedInfo &info): FileDirectiveDeserializer(pduBuf, maxSize), finishedInfo(info) {
}
ReturnValue_t FinishPduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
const uint8_t* buf = rawPtr + currentIdx;
size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
if (remSize < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
uint8_t firstByte = *buf;
cfdp::ConditionCode condCode = static_cast<cfdp::ConditionCode>((firstByte >> 4) & 0x0f);
finishedInfo.setConditionCode(condCode);
finishedInfo.setDeliveryCode(static_cast<cfdp::FinishedDeliveryCode>(firstByte >> 2 & 0b1));
finishedInfo.setFileStatus(static_cast<cfdp::FinishedFileStatus>(firstByte & 0b11));
buf += 1;
remSize -= 1;
currentIdx += 1;
if(remSize > 0) {
result = parseTlvs(remSize, currentIdx, buf, condCode);
}
return result;
}
FinishedInfo& FinishPduDeserializer::getInfo() {
return finishedInfo;
}
ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx,
const uint8_t* buf, cfdp::ConditionCode conditionCode) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
size_t fsResponsesIdx = 0;
auto endianness = getEndianness();
FilestoreResponseTlv** fsResponseArray = nullptr;
size_t fsResponseMaxArrayLen = 0;
EntityIdTlv* faultLocation = nullptr;
cfdp::TlvTypes nextTlv = cfdp::TlvTypes::INVALID_TLV;
while(remLen > 0) {
// Simply forward parse the TLV type. Every TLV type except the last one must be a Filestore
// Response TLV, and even the last one can be a Filestore Response TLV if the fault
// location is omitted
if (currentIdx + 2 > maxSize) {
return SerializeIF::STREAM_TOO_SHORT;
}
nextTlv = static_cast<cfdp::TlvTypes>(*buf);
if (nextTlv == cfdp::TlvTypes::FILESTORE_RESPONSE) {
if(fsResponseArray == nullptr) {
if(not finishedInfo.canHoldFsResponses()) {
return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES;
}
result = finishedInfo.getFilestoreResonses(&fsResponseArray, nullptr,
&fsResponseMaxArrayLen);
}
if(fsResponsesIdx == fsResponseMaxArrayLen) {
return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES;
}
result = fsResponseArray[fsResponsesIdx]->deSerialize(&buf, &remLen, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
fsResponsesIdx += 1;
} else if(nextTlv == cfdp::TlvTypes::ENTITY_ID) {
// This needs to be the last TLV and it should not be here if the condition code
// is "No Error" or "Unsupported Checksum Type"
if(conditionCode == cfdp::ConditionCode::NO_ERROR or
conditionCode == cfdp::ConditionCode::UNSUPPORTED_CHECKSUM_TYPE) {
return cfdp::INVALID_TLV_TYPE;
}
result = finishedInfo.getFaultLocation(&faultLocation);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = faultLocation->deSerialize(&buf, &remLen, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
} else {
return cfdp::INVALID_TLV_TYPE;
}
}
finishedInfo.setFilestoreResponsesArrayLen(fsResponsesIdx);
return result;
}

View File

@ -0,0 +1,21 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_
#include "fsfw/cfdp/pdu/FinishedInfo.h"
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
class FinishPduDeserializer: public FileDirectiveDeserializer {
public:
FinishPduDeserializer(const uint8_t *pduBuf, size_t maxSize, FinishedInfo& info);
ReturnValue_t parseData() override;
FinishedInfo& getInfo();
private:
FinishedInfo& finishedInfo;
ReturnValue_t parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf,
cfdp::ConditionCode conditionCode);
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,47 @@
#include "FinishedPduSerializer.h"
FinishPduSerializer::FinishPduSerializer(PduConfig &conf, FinishedInfo &finishInfo):
FileDirectiveSerializer(conf, cfdp::FileDirectives::FINISH, 0), finishInfo(finishInfo) {
updateDirectiveFieldLen();
}
size_t FinishPduSerializer::getSerializedSize() const {
return FinishPduSerializer::getWholePduSize();
}
void FinishPduSerializer::updateDirectiveFieldLen() {
setDirectiveDataFieldLen(finishInfo.getSerializedSize());
}
ReturnValue_t FinishPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(*size + 1 >= maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = finishInfo.getConditionCode() << 4 | finishInfo.getDeliveryCode() << 2 |
finishInfo.getFileStatus();
*size += 1;
*buffer += 1;
if(finishInfo.hasFsResponses()) {
FilestoreResponseTlv** fsResponsesArray = nullptr;
size_t fsResponsesArrayLen = 0;
finishInfo.getFilestoreResonses(&fsResponsesArray, &fsResponsesArrayLen, nullptr);
for(size_t idx = 0; idx < fsResponsesArrayLen; idx++) {
result = fsResponsesArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
}
EntityIdTlv* entityId = nullptr;
if(finishInfo.getFaultLocation(&entityId) == HasReturnvaluesIF::RETURN_OK) {
result = entityId->serialize(buffer, size, maxSize, streamEndianness);
}
return result;
}

View File

@ -0,0 +1,22 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
#include "fsfw/cfdp/pdu/FileDataSerializer.h"
#include "FinishedInfo.h"
class FinishPduSerializer: public FileDirectiveSerializer {
public:
FinishPduSerializer(PduConfig& pduConf, FinishedInfo& finishInfo);
void updateDirectiveFieldLen();
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
private:
FinishedInfo& finishInfo;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ */

View File

@ -0,0 +1,136 @@
#include <fsfw/serialize/SerializeAdapter.h>
#include "HeaderDeserializer.h"
#include <cstring>
HeaderDeserializer::HeaderDeserializer(const uint8_t *pduBuf, size_t maxSize):
rawPtr(pduBuf), maxSize(maxSize) {
}
ReturnValue_t HeaderDeserializer::parseData() {
if (maxSize < 7) {
return SerializeIF::STREAM_TOO_SHORT;
}
return setData(const_cast<uint8_t*>(rawPtr), maxSize);
}
ReturnValue_t HeaderDeserializer::setData(uint8_t *dataPtr, size_t maxSize,
void* args) {
if(dataPtr == nullptr) {
// Allowed for now
this->fixedHeader = nullptr;
return HasReturnvaluesIF::RETURN_OK;
}
this->fixedHeader = reinterpret_cast<PduHeaderFixedStruct*>(const_cast<uint8_t*>(dataPtr));
sourceIdRaw = static_cast<uint8_t*>(&fixedHeader->variableFieldsStart);
cfdp::WidthInBytes widthEntityIds = getLenEntityIds();
cfdp::WidthInBytes widthSeqNum = getLenSeqNum();
seqNumRaw = static_cast<uint8_t*>(sourceIdRaw) + static_cast<uint8_t>(widthEntityIds);
destIdRaw = static_cast<uint8_t*>(seqNumRaw) + static_cast<uint8_t>(widthSeqNum);
this->maxSize = maxSize;
return HasReturnvaluesIF::RETURN_OK;
}
size_t HeaderDeserializer::getHeaderSize() const {
if(fixedHeader != nullptr) {
return getLenEntityIds() * 2 + getLenSeqNum() + 4;
}
return 0;
}
size_t HeaderDeserializer::getPduDataFieldLen() const {
uint16_t pduFiedlLen = (fixedHeader->pduDataFieldLenH << 8) | fixedHeader->pduDataFieldLenL;
return pduFiedlLen;
}
size_t HeaderDeserializer::getWholePduSize() const {
return getPduDataFieldLen() + getHeaderSize();
}
cfdp::PduType HeaderDeserializer::getPduType() const {
return static_cast<cfdp::PduType>((fixedHeader->firstByte >> 4) & 0x01);
}
cfdp::Direction HeaderDeserializer::getDirection() const {
return static_cast<cfdp::Direction>((fixedHeader->firstByte >> 3) & 0x01);
}
cfdp::TransmissionModes HeaderDeserializer::getTransmissionMode() const {
return static_cast<cfdp::TransmissionModes>((fixedHeader->firstByte >> 2) & 0x01);
}
bool HeaderDeserializer::getCrcFlag() const {
return (fixedHeader->firstByte >> 1) & 0x01;
}
bool HeaderDeserializer::getLargeFileFlag() const {
return fixedHeader->firstByte & 0x01;
}
cfdp::SegmentationControl HeaderDeserializer::getSegmentationControl() const {
return static_cast<cfdp::SegmentationControl>((fixedHeader->fourthByte >> 7) & 0x01);
}
cfdp::WidthInBytes HeaderDeserializer::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>((fixedHeader->fourthByte >> 4) & 0x07);
}
cfdp::WidthInBytes HeaderDeserializer::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>(fixedHeader->fourthByte & 0x07);
}
cfdp::SegmentMetadataFlag HeaderDeserializer::getSegmentMetadataFlag() const {
return static_cast<cfdp::SegmentMetadataFlag>((fixedHeader->fourthByte >> 3) & 0x01);
}
void HeaderDeserializer::getSourceId(cfdp::EntityId &sourceId) const {
assignVarLenField(dynamic_cast<cfdp::VarLenField*>(&sourceId), getLenEntityIds(),
this->sourceIdRaw);
}
void HeaderDeserializer::getDestId(cfdp::EntityId &destId) const {
assignVarLenField(dynamic_cast<cfdp::VarLenField*>(&destId), getLenEntityIds(),
this->destIdRaw);
}
void HeaderDeserializer::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const {
assignVarLenField(dynamic_cast<cfdp::VarLenField*>(&seqNum), getLenSeqNum(),
this->seqNumRaw);
}
void HeaderDeserializer::assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
void *sourcePtr) const {
switch(width) {
case(cfdp::WidthInBytes::ONE_BYTE): {
uint8_t* fieldTyped = static_cast<uint8_t*>(sourcePtr);
field->setValue(width, *fieldTyped);
break;
}
case(cfdp::WidthInBytes::TWO_BYTES): {
uint16_t fieldTyped = 0;
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t*>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
field->setValue(width, fieldTyped);
break;
}
case(cfdp::WidthInBytes::FOUR_BYTES): {
uint32_t fieldTyped = 0;
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t*>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
field->setValue(width, fieldTyped);
break;
}
}
}
size_t HeaderDeserializer::getMaxSize() const {
return maxSize;
}
bool HeaderDeserializer::hasSegmentMetadataFlag() const {
if(this->getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT) {
return true;
}
return false;
}

View File

@ -0,0 +1,93 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_
#include "PduConfig.h"
#include "PduHeaderIF.h"
#include "fsfw/serialize/SerializeIF.h"
#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h"
#include <cstdint>
#include <cstddef>
struct PduHeaderFixedStruct {
uint8_t firstByte;
uint8_t pduDataFieldLenH;
uint8_t pduDataFieldLenL;
uint8_t fourthByte;
uint8_t variableFieldsStart;
};
/**
* @brief This class is used to deserialize a PDU header from raw memory.
* @details
* This is a zero-copy implementation and #parseData needs to be called to ensure the data is
* valid.
*/
class HeaderDeserializer:
public RedirectableDataPointerIF,
public PduHeaderIF {
public:
/**
* Initialize a PDU header from raw data. This is a zero-copy implementation and #parseData
* needs to be called to ensure the data is valid
* @param pduBuf
* @param maxSize
*/
HeaderDeserializer(const uint8_t* pduBuf, size_t maxSize);
/**
* This needs to be called before accessing the PDU fields to avoid segmentation faults.
* @return
* - RETURN_OK on parse success
* - RETURN_FAILED Invalid raw data
* - SerializeIF::BUFFER_TOO_SHORT if buffer is shorter than expected
*/
virtual ReturnValue_t parseData();
size_t getHeaderSize() const;
size_t getPduDataFieldLen() const override;
size_t getWholePduSize() const override;
cfdp::PduType getPduType() const override;
cfdp::Direction getDirection() const override;
cfdp::TransmissionModes getTransmissionMode() const override;
bool getCrcFlag() const override;
bool getLargeFileFlag() const override;
cfdp::SegmentationControl getSegmentationControl() const override;
cfdp::WidthInBytes getLenEntityIds() const override;
cfdp::WidthInBytes getLenSeqNum() const override;
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
bool hasSegmentMetadataFlag() const override;
void getSourceId(cfdp::EntityId& sourceId) const override;
void getDestId(cfdp::EntityId& destId) const override;
void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const override;
ReturnValue_t deserResult = HasReturnvaluesIF::RETURN_OK;
/**
* Can also be used to reset the pointer to a nullptr, but the getter functions will not
* perform nullptr checks!
* @param dataPtr
* @param maxSize
* @param args
* @return
*/
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize,
void* args = nullptr) override;
size_t getMaxSize() const;
protected:
PduHeaderFixedStruct* fixedHeader = nullptr;
const uint8_t* rawPtr = nullptr;
size_t maxSize = 0;
private:
void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
void* sourcePtr) const;
void* sourceIdRaw = nullptr;
void* seqNumRaw = nullptr;
void* destIdRaw = nullptr;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_HEADERDESERIALIZER_H_ */

View File

@ -0,0 +1,135 @@
#include "HeaderSerializer.h"
#include "HeaderDeserializer.h"
HeaderSerializer::HeaderSerializer(PduConfig& pduConf, cfdp::PduType pduType,
size_t initPduDataFieldLen, cfdp::SegmentMetadataFlag segmentMetadataFlag,
cfdp::SegmentationControl segCtrl):
pduType(pduType), segmentMetadataFlag(segmentMetadataFlag), segmentationCtrl(segCtrl),
pduDataFieldLen(initPduDataFieldLen), pduConf(pduConf) {
}
ReturnValue_t HeaderSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(maxSize < this->getSerializedSize()) {
return BUFFER_TOO_SHORT;
}
**buffer = cfdp::VERSION_BITS | this->pduType << 4 | pduConf.direction << 3 |
pduConf.mode << 2 | pduConf.crcFlag << 1 | pduConf.largeFile;
*buffer += 1;
**buffer = (pduDataFieldLen & 0xff00) >> 8;
*buffer += 1;
**buffer = pduDataFieldLen & 0x00ff;
*buffer += 1;
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 |
segmentMetadataFlag << 3 | pduConf.seqNum.getWidth();
*buffer += 1;
*size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = pduConf.seqNum.serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = pduConf.destId.serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
size_t HeaderSerializer::getSerializedSize() const {
size_t shit = pduConf.seqNum.getWidth() + pduConf.sourceId.getWidth() * 2 + 4;
return shit;
}
ReturnValue_t HeaderSerializer::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
// We could implement this, but I prefer dedicated classes
return HasReturnvaluesIF::RETURN_FAILED;
}
size_t HeaderSerializer::getWholePduSize() const {
// Return size of header plus the PDU data field length
return pduDataFieldLen + HeaderSerializer::getSerializedSize();
}
size_t HeaderSerializer::getPduDataFieldLen() const {
return pduDataFieldLen;
}
void HeaderSerializer::setPduDataFieldLen(size_t pduDataFieldLen) {
this->pduDataFieldLen = pduDataFieldLen;
}
void HeaderSerializer::setPduType(cfdp::PduType pduType) {
this->pduType = pduType;
}
void HeaderSerializer::setSegmentMetadataFlag(cfdp::SegmentMetadataFlag segmentMetadataFlag) {
this->segmentMetadataFlag = segmentMetadataFlag;
}
cfdp::PduType HeaderSerializer::getPduType() const {
return pduType;
}
cfdp::Direction HeaderSerializer::getDirection() const {
return pduConf.direction;
}
cfdp::TransmissionModes HeaderSerializer::getTransmissionMode() const {
return pduConf.mode;
}
bool HeaderSerializer::getCrcFlag() const {
return pduConf.crcFlag;
}
bool HeaderSerializer::getLargeFileFlag() const {
return pduConf.largeFile;
}
cfdp::SegmentationControl HeaderSerializer::getSegmentationControl() const {
return segmentationCtrl;
}
cfdp::WidthInBytes HeaderSerializer::getLenEntityIds() const {
return pduConf.sourceId.getWidth();
}
cfdp::WidthInBytes HeaderSerializer::getLenSeqNum() const {
return pduConf.seqNum.getWidth();
}
cfdp::SegmentMetadataFlag HeaderSerializer::getSegmentMetadataFlag() const {
return segmentMetadataFlag;
}
void HeaderSerializer::getSourceId(cfdp::EntityId &sourceId) const {
sourceId = pduConf.sourceId;
}
void HeaderSerializer::getDestId(cfdp::EntityId &destId) const {
destId = pduConf.destId;
}
void HeaderSerializer::setSegmentationControl(cfdp::SegmentationControl segmentationControl) {
this->segmentationCtrl = segmentationControl;
}
void HeaderSerializer::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const {
seqNum = pduConf.seqNum;
}
bool HeaderSerializer::hasSegmentMetadataFlag() const {
if(this->segmentMetadataFlag == cfdp::SegmentMetadataFlag::PRESENT) {
return true;
}
return false;
}

View File

@ -0,0 +1,64 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_
#include "PduHeaderIF.h"
#include "fsfw/serialize/SerializeIF.h"
#include "../definitions.h"
#include "PduConfig.h"
class HeaderSerializer: public SerializeIF, public PduHeaderIF {
public:
HeaderSerializer(PduConfig& pduConf, cfdp::PduType pduType,
size_t initPduDataFieldLen,
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT,
cfdp::SegmentationControl segCtrl =
cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION);
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
/**
* This only returns the length of the serialized hader.
* Use #getWholePduSize to get the length of the full packet, assuming that the PDU
* data field length was not properly.
* @return
*/
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
void setPduDataFieldLen(size_t pduDataFieldLen);
void setPduType(cfdp::PduType pduType);
void setSegmentMetadataFlag(cfdp::SegmentMetadataFlag);
size_t getPduDataFieldLen() const override;
size_t getWholePduSize() const override;
cfdp::PduType getPduType() const override;
cfdp::Direction getDirection() const override;
cfdp::TransmissionModes getTransmissionMode() const override;
bool getCrcFlag() const override;
bool getLargeFileFlag() const override;
cfdp::SegmentationControl getSegmentationControl() const override;
cfdp::WidthInBytes getLenEntityIds() const override;
cfdp::WidthInBytes getLenSeqNum() const override;
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
bool hasSegmentMetadataFlag() const;
void setSegmentationControl(cfdp::SegmentationControl);
void getSourceId(cfdp::EntityId& sourceId) const override;
void getDestId(cfdp::EntityId& destId) const override;
void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const override;
private:
cfdp::PduType pduType;
cfdp::SegmentMetadataFlag segmentMetadataFlag;
cfdp::SegmentationControl segmentationCtrl;
size_t pduDataFieldLen;
PduConfig& pduConf;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_ */

View File

@ -0,0 +1,20 @@
#include "KeepAlivePduDeserializer.h"
KeepAlivePduDeserializer::KeepAlivePduDeserializer(const uint8_t *pduBuf, size_t maxSize,
cfdp::FileSize &progress): FileDirectiveDeserializer(pduBuf, maxSize), progress(progress) {
}
ReturnValue_t KeepAlivePduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
size_t remLen = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
const uint8_t* buffer = rawPtr + currentIdx;
return progress.deSerialize(&buffer, &remLen, getEndianness());
}
cfdp::FileSize& KeepAlivePduDeserializer::getProgress() {
return progress;
}

View File

@ -0,0 +1,18 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUDESERIALIZER_H_
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
class KeepAlivePduDeserializer: public FileDirectiveDeserializer {
public:
KeepAlivePduDeserializer(const uint8_t *pduBuf, size_t maxSize, cfdp::FileSize& progress);
ReturnValue_t parseData() override;
cfdp::FileSize& getProgress();
private:
cfdp::FileSize& progress;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,26 @@
#include "KeepAlivePduSerializer.h"
KeepAlivePduSerializer::KeepAlivePduSerializer(PduConfig &conf, cfdp::FileSize& progress):
FileDirectiveSerializer(conf, cfdp::FileDirectives::KEEP_ALIVE, 4), progress(progress) {
updateDirectiveFieldLen();
}
size_t KeepAlivePduSerializer::getSerializedSize() const {
return FileDirectiveSerializer::getWholePduSize();
}
void KeepAlivePduSerializer::updateDirectiveFieldLen() {
if(this->getLargeFileFlag()) {
this->setDirectiveDataFieldLen(8);
}
}
ReturnValue_t KeepAlivePduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
}

View File

@ -0,0 +1,21 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
class KeepAlivePduSerializer: public FileDirectiveSerializer {
public:
KeepAlivePduSerializer(PduConfig& conf, cfdp::FileSize& progress);
void updateDirectiveFieldLen();
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
private:
cfdp::FileSize& progress;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */

View File

@ -0,0 +1,115 @@
#include "MetadataInfo.h"
MetadataInfo::MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType,
cfdp::FileSize& fileSize, cfdp::Lv& sourceFileName, cfdp::Lv& destFileName):
closureRequested(closureRequested), checksumType(checksumType), fileSize(fileSize),
sourceFileName(sourceFileName), destFileName(destFileName) {
}
void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray, size_t* optionsLen,
size_t* maxOptionsLen) {
this->optionsArray = optionsArray;
if(maxOptionsLen != nullptr) {
this->maxOptionsLen = *maxOptionsLen;
}
if(optionsLen != nullptr) {
this->optionsLen = *optionsLen;
}
}
cfdp::ChecksumType MetadataInfo::getChecksumType() const {
return checksumType;
}
void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType) {
this->checksumType = checksumType;
}
bool MetadataInfo::isClosureRequested() const {
return closureRequested;
}
void MetadataInfo::setClosureRequested(bool closureRequested) {
this->closureRequested = closureRequested;
}
cfdp::Lv& MetadataInfo::getDestFileName() {
return destFileName;
}
cfdp::FileSize& MetadataInfo::getFileSize() {
return fileSize;
}
ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray, size_t *optionsLen,
size_t* maxOptsLen) {
if(optionsArray == nullptr or this->optionsArray == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
*optionsArray = this->optionsArray;
if(optionsLen != nullptr) {
*optionsLen = this->optionsLen;
}
if(maxOptsLen != nullptr) {
*maxOptsLen = this->maxOptionsLen;
}
return HasReturnvaluesIF::RETURN_OK;
}
bool MetadataInfo::hasOptions() const {
if (optionsArray != nullptr and optionsLen > 0) {
return true;
}
return false;
}
bool MetadataInfo::canHoldOptions() const {
if (optionsArray != nullptr and maxOptionsLen > 0) {
return true;
}
return false;
}
size_t MetadataInfo::getSerializedSize(bool fssLarge) {
// 1 byte + minimal FSS 4 bytes
size_t size = 5;
if(fssLarge) {
size += 4;
}
size += sourceFileName.getSerializedSize();
size += destFileName.getSerializedSize();
if(hasOptions()) {
for(size_t idx = 0; idx < optionsLen; idx++) {
size += optionsArray[idx]->getSerializedSize();
}
}
return size;
}
void MetadataInfo::setDestFileName(cfdp::Lv &destFileName) {
this->destFileName = destFileName;
}
void MetadataInfo::setSourceFileName(cfdp::Lv &sourceFileName) {
this->sourceFileName = sourceFileName;
}
size_t MetadataInfo::getMaxOptionsLen() const {
return maxOptionsLen;
}
void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen) {
this->maxOptionsLen = maxOptionsLen;
}
size_t MetadataInfo::getOptionsLen() const {
return optionsLen;
}
void MetadataInfo::setOptionsLen(size_t optionsLen) {
this->optionsLen = optionsLen;
}
cfdp::Lv& MetadataInfo::getSourceFileName() {
return sourceFileName;
}

View File

@ -0,0 +1,49 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#include "fsfw/cfdp/tlv/Tlv.h"
#include "fsfw/cfdp/tlv/Lv.h"
#include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/definitions.h"
class MetadataInfo {
public:
MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::FileSize& fileSize,
cfdp::Lv& sourceFileName, cfdp::Lv& destFileName);
size_t getSerializedSize(bool fssLarge = false);
void setOptionsArray(cfdp::Tlv** optionsArray, size_t* optionsLen, size_t* maxOptionsLen);
cfdp::ChecksumType getChecksumType() const;
void setChecksumType(cfdp::ChecksumType checksumType);
bool isClosureRequested() const;
void setClosureRequested(bool closureRequested = false);
void setDestFileName(cfdp::Lv& destFileName);
void setSourceFileName(cfdp::Lv& sourceFileName);
cfdp::Lv& getDestFileName();
cfdp::Lv& getSourceFileName();
cfdp::FileSize& getFileSize();
bool hasOptions() const;
bool canHoldOptions() const;
ReturnValue_t getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, size_t* maxOptsLen);
void setOptionsLen(size_t optionsLen);
size_t getOptionsLen() const;
void setMaxOptionsLen(size_t maxOptionsLen);
size_t getMaxOptionsLen() const;
private:
bool closureRequested = false;
cfdp::ChecksumType checksumType;
cfdp::FileSize& fileSize;
cfdp::Lv& sourceFileName;
cfdp::Lv& destFileName;
cfdp::Tlv** optionsArray = nullptr;
size_t optionsLen = 0;
size_t maxOptionsLen = 0;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */

View File

@ -0,0 +1,58 @@
#include "MetadataPduDeserializer.h"
MetadataPduDeserializer::MetadataPduDeserializer(const uint8_t *pduBuf, size_t maxSize,
MetadataInfo &info): FileDirectiveDeserializer(pduBuf, maxSize), info(info) {
}
ReturnValue_t MetadataPduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
const uint8_t* buf = rawPtr + currentIdx;
size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
if (remSize < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
info.setClosureRequested((*buf >> 6) & 0x01);
info.setChecksumType(static_cast<cfdp::ChecksumType>(*buf & 0x0f));
remSize -= 1;
buf += 1;
auto endianness = getEndianness();
result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = info.getDestFileName().deSerialize(&buf, &remSize, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
info.setOptionsLen(0);
if (remSize > 0) {
if(not info.canHoldOptions()) {
return cfdp::METADATA_CANT_PARSE_OPTIONS;
}
cfdp::Tlv** optionsArray = nullptr;
size_t optsMaxLen = 0;
size_t optsIdx = 0;
info.getOptions(&optionsArray, nullptr, &optsMaxLen);
while(remSize > 0) {
if(optsIdx > optsMaxLen) {
return cfdp::METADATA_CANT_PARSE_OPTIONS;
}
result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
optsIdx++;
}
info.setOptionsLen(optsIdx);
}
return result;
}

View File

@ -0,0 +1,18 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUDESERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
#include "fsfw/cfdp/pdu/MetadataInfo.h"
class MetadataPduDeserializer: public FileDirectiveDeserializer {
public:
MetadataPduDeserializer(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
ReturnValue_t parseData() override;
private:
MetadataInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,54 @@
#include "MetadataPduSerializer.h"
MetadataPduSerializer::MetadataPduSerializer(PduConfig &conf, MetadataInfo &info):
FileDirectiveSerializer(conf, cfdp::FileDirectives::METADATA, 5), info(info) {
updateDirectiveFieldLen();
}
void MetadataPduSerializer::updateDirectiveFieldLen() {
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
}
size_t MetadataPduSerializer::getSerializedSize() const {
return FileDirectiveSerializer::getWholePduSize();
}
ReturnValue_t MetadataPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(*size + 1 >= maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = info.isClosureRequested() << 6 | info.getChecksumType();
*buffer += 1;
*size += 1;
result = info.getFileSize().serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(info.hasOptions()) {
cfdp::Tlv** optsArray = nullptr;
size_t optsLen = 0;
info.getOptions(&optsArray, &optsLen, nullptr);
for(size_t idx = 0; idx < optsLen; idx++) {
result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
}
return result;
}

View File

@ -0,0 +1,23 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_
#include "fsfw/cfdp/pdu/MetadataInfo.h"
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
class MetadataPduSerializer: public FileDirectiveSerializer {
public:
MetadataPduSerializer(PduConfig &conf, MetadataInfo& info);
void updateDirectiveFieldLen();
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
private:
MetadataInfo& info;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_ */

View File

@ -0,0 +1,83 @@
#include "NakInfo.h"
NakInfo::NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope):
startOfScope(startOfScope), endOfScope(endOfScope) {
}
size_t NakInfo::getSerializedSize(bool fssLarge) {
size_t size = 8;
if(fssLarge) {
size += 8;
}
if(hasSegmentRequests()) {
if(fssLarge) {
size += segmentRequestsLen * 16;
} else {
size += segmentRequestsLen * 8;
}
}
return size;
}
bool NakInfo::hasSegmentRequests() const {
if(this->segmentRequests != nullptr and segmentRequestsLen > 0) {
return true;
}
return false;
}
bool NakInfo::canHoldSegmentRequests() const {
if(this->segmentRequests != nullptr and maxSegmentRequestsLen > 0) {
return true;
}
return false;
}
bool NakInfo::getSegmentRequests(SegmentRequest **segmentRequestPtr,
size_t *segmentRequestLen, size_t* maxSegmentRequestsLen) {
if(this->segmentRequests != nullptr) {
*segmentRequestPtr = this->segmentRequests;
}
if(segmentRequestLen != nullptr) {
*segmentRequestLen = this->segmentRequestsLen;
}
if(maxSegmentRequestsLen != nullptr) {
*maxSegmentRequestsLen = this->maxSegmentRequestsLen;
}
return true;
}
void NakInfo::setSegmentRequests(SegmentRequest *segmentRequests, size_t* segmentRequestLen,
size_t* maxSegmentRequestLen) {
this->segmentRequests = segmentRequests;
if(segmentRequestLen != nullptr) {
this->segmentRequestsLen = *segmentRequestLen;
}
if(maxSegmentRequestLen != nullptr) {
this->maxSegmentRequestsLen = *maxSegmentRequestLen;
}
}
cfdp::FileSize& NakInfo::getStartOfScope() {
return startOfScope;
}
cfdp::FileSize& NakInfo::getEndOfScope() {
return endOfScope;
}
size_t NakInfo::getSegmentRequestsLen() const {
return segmentRequestsLen;
}
size_t NakInfo::getSegmentRequestsMaxLen() const {
return maxSegmentRequestsLen;
}
void NakInfo::setSegmentRequestLen(size_t readLen) {
this->segmentRequestsLen = readLen;
}
void NakInfo::setMaxSegmentRequestLen(size_t maxSize) {
this->maxSegmentRequestsLen = maxSize;
}

View File

@ -0,0 +1,40 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_NAKINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_NAKINFO_H_
#include "fsfw/cfdp/FileSize.h"
#include <utility>
class NakInfo {
public:
using SegmentRequest = std::pair<cfdp::FileSize, cfdp::FileSize>;
NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope);
void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen,
size_t* maxSegmentRequestLen);
size_t getSerializedSize(bool fssLarge = false);
cfdp::FileSize& getStartOfScope();
cfdp::FileSize& getEndOfScope();
bool hasSegmentRequests() const;
bool canHoldSegmentRequests() const;
void setMaxSegmentRequestLen(size_t maxSize);
bool getSegmentRequests(SegmentRequest** segmentRequestPtr, size_t* segmentRequestLen,
size_t* maxSegmentRequestsLen);
size_t getSegmentRequestsLen() const;
size_t getSegmentRequestsMaxLen() const;
//! This functions is more relevant for deserializers
void setSegmentRequestLen(size_t readLen);
private:
cfdp::FileSize startOfScope;
cfdp::FileSize endOfScope;
SegmentRequest* segmentRequests = nullptr;
size_t segmentRequestsLen = 0;
size_t maxSegmentRequestsLen = 0;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_NAKINFO_H_ */

View File

@ -0,0 +1,58 @@
#include "NakPduDeserializer.h"
NakPduDeserializer::NakPduDeserializer(const uint8_t *pduBuf, size_t maxSize, NakInfo &info):
FileDirectiveDeserializer(pduBuf, maxSize), nakInfo(info) {
}
ReturnValue_t NakPduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
const uint8_t* buffer = rawPtr + currentIdx;
size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
if (remSize < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
result = nakInfo.getStartOfScope().deSerialize(&buffer, &remSize,
SerializeIF::Endianness::NETWORK);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = nakInfo.getEndOfScope().deSerialize(&buffer, &remSize,
SerializeIF::Endianness::NETWORK);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
nakInfo.setSegmentRequestLen(0);
if(remSize > 0) {
if(not nakInfo.canHoldSegmentRequests()) {
return cfdp::NAK_CANT_PARSE_OPTIONS;
}
NakInfo::SegmentRequest* segReqs = nullptr;
size_t maxSegReqs = 0;
nakInfo.getSegmentRequests(&segReqs, nullptr, &maxSegReqs);
if(segReqs != nullptr) {
size_t idx = 0;
while(remSize > 0) {
if(idx == maxSegReqs) {
return cfdp::NAK_CANT_PARSE_OPTIONS;
}
result = segReqs[idx].first.deSerialize(&buffer, &remSize,
SerializeIF::Endianness::NETWORK);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = segReqs[idx].second.deSerialize(&buffer, &remSize,
SerializeIF::Endianness::NETWORK);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
idx++;
}
nakInfo.setSegmentRequestLen(idx);
}
}
return result;
}

View File

@ -0,0 +1,22 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
#include "fsfw/cfdp/pdu/NakInfo.h"
class NakPduDeserializer: public FileDirectiveDeserializer {
public:
NakPduDeserializer(const uint8_t* pduBuf, size_t maxSize, NakInfo& info);
/**
* This needs to be called before accessing the PDU fields to avoid segmentation faults.
* @return
*/
virtual ReturnValue_t parseData() override;
private:
NakInfo& nakInfo;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_NAKPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,49 @@
#include "NakPduSerializer.h"
NakPduSerializer::NakPduSerializer(PduConfig& pduConf, NakInfo& nakInfo):
FileDirectiveSerializer(pduConf, cfdp::FileDirectives::NAK, 0), nakInfo(nakInfo) {
updateDirectiveFieldLen();
}
void NakPduSerializer::updateDirectiveFieldLen() {
this->setDirectiveDataFieldLen(nakInfo.getSerializedSize(getLargeFileFlag()));
}
size_t NakPduSerializer::getSerializedSize() const {
return FileDirectiveSerializer::getWholePduSize();
}
ReturnValue_t NakPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = nakInfo.getStartOfScope().serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = nakInfo.getEndOfScope().serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(nakInfo.hasSegmentRequests()) {
NakInfo::SegmentRequest *segmentRequests = nullptr;
size_t segmentRequestLen = 0;
nakInfo.getSegmentRequests(&segmentRequests, &segmentRequestLen, nullptr);
for(size_t idx = 0; idx < segmentRequestLen; idx++) {
result = segmentRequests[idx].first.serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = segmentRequests[idx].second.serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
}
return result;
}

View File

@ -0,0 +1,41 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
#include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/FileSize.h"
#include "NakInfo.h"
#include <vector>
class NakPduSerializer: public FileDirectiveSerializer {
public:
/**
*
* @param PduConf
* @param startOfScope
* @param endOfScope
* @param [in] segmentRequests Pointer to the start of a list of segment requests
* @param segmentRequestLen Length of the segment request list to be serialized
*/
NakPduSerializer(PduConfig& PduConf, NakInfo& nakInfo);
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
/**
* If you change the info struct, you might need to update the directive field length
* manually
*/
void updateDirectiveFieldLen();
private:
NakInfo& nakInfo;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ */

View File

@ -0,0 +1,8 @@
#include "PduConfig.h"
PduConfig::PduConfig(cfdp::TransmissionModes mode, cfdp::TransactionSeqNum seqNum,
cfdp::EntityId sourceId, cfdp::EntityId destId, bool crcFlag,
bool largeFile, cfdp::Direction direction):
mode(mode), seqNum(seqNum), sourceId(sourceId), destId(destId),
crcFlag(crcFlag), largeFile(largeFile), direction(direction) {
}

View File

@ -0,0 +1,36 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_PDUCONFIG_H_
#define FSFW_SRC_FSFW_CFDP_PDU_PDUCONFIG_H_
#include "VarLenField.h"
namespace cfdp {
struct EntityId: public VarLenField {
public:
EntityId(): VarLenField() {}
EntityId(cfdp::WidthInBytes width, size_t entityId): VarLenField(width, entityId) {}
};
struct TransactionSeqNum: public VarLenField {
public:
TransactionSeqNum(): VarLenField() {}
TransactionSeqNum(cfdp::WidthInBytes width, size_t seqNum): VarLenField(width, seqNum) {}
};
}
class PduConfig {
public:
PduConfig(cfdp::TransmissionModes mode, cfdp::TransactionSeqNum seqNum,
cfdp::EntityId sourceId, cfdp::EntityId destId, bool crcFlag = false,
bool largeFile = false, cfdp::Direction direction = cfdp::Direction::TOWARDS_RECEIVER);
cfdp::TransmissionModes mode;
cfdp::TransactionSeqNum seqNum;
cfdp::EntityId sourceId;
cfdp::EntityId destId;
bool crcFlag;
bool largeFile;
cfdp::Direction direction;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_PDUCONFIG_H_ */

View File

@ -0,0 +1,37 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_PDUHEADERIF_H_
#define FSFW_SRC_FSFW_CFDP_PDU_PDUHEADERIF_H_
#include "PduConfig.h"
#include "../definitions.h"
#include <cstddef>
/**
* @brief Generic interface to access all fields of a PDU header
* @details
* See CCSDS 727.0-B-5 pp.75 for more information about these fields
*/
class PduHeaderIF {
public:
virtual~ PduHeaderIF() {};
virtual size_t getWholePduSize() const = 0;
virtual size_t getPduDataFieldLen() const = 0;
virtual cfdp::PduType getPduType() const = 0;
virtual cfdp::Direction getDirection() const = 0;
virtual cfdp::TransmissionModes getTransmissionMode() const = 0;
virtual bool getCrcFlag() const = 0;
virtual bool getLargeFileFlag() const = 0;
virtual cfdp::SegmentationControl getSegmentationControl() const = 0;
virtual cfdp::WidthInBytes getLenEntityIds() const = 0;
virtual cfdp::WidthInBytes getLenSeqNum() const = 0;
virtual cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const = 0;
virtual bool hasSegmentMetadataFlag() const = 0;
virtual void getSourceId(cfdp::EntityId& sourceId) const = 0;
virtual void getDestId(cfdp::EntityId& destId) const = 0;
virtual void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const = 0;
private:
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_PDUHEADERIF_H_ */

View File

@ -0,0 +1,22 @@
#include "PromptPduDeserializer.h"
PromptPduDeserializer::PromptPduDeserializer(const uint8_t *pduBuf, size_t maxSize):
FileDirectiveDeserializer(pduBuf, maxSize) {
}
cfdp::PromptResponseRequired PromptPduDeserializer::getPromptResponseRequired() const {
return responseRequired;
}
ReturnValue_t PromptPduDeserializer::parseData() {
ReturnValue_t result = FileDirectiveDeserializer::parseData();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
if (FileDirectiveDeserializer::getWholePduSize() - currentIdx < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
responseRequired = static_cast<cfdp::PromptResponseRequired>((rawPtr[currentIdx] >> 7) & 0x01);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,18 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUDESERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUDESERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
class PromptPduDeserializer: public FileDirectiveDeserializer {
public:
PromptPduDeserializer(const uint8_t *pduBuf, size_t maxSize);
cfdp::PromptResponseRequired getPromptResponseRequired() const;
ReturnValue_t parseData() override;
private:
cfdp::PromptResponseRequired responseRequired = cfdp::PromptResponseRequired::PROMPT_NAK;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUDESERIALIZER_H_ */

View File

@ -0,0 +1,27 @@
#include "PromptPduSerializer.h"
PromptPduSerializer::PromptPduSerializer(PduConfig &conf,
cfdp::PromptResponseRequired responseRequired):
FileDirectiveSerializer(conf, cfdp::FileDirectives::PROMPT, 1),
responseRequired(responseRequired) {
}
size_t PromptPduSerializer::getSerializedSize() const {
return FileDirectiveSerializer::getWholePduSize();
}
ReturnValue_t PromptPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = FileDirectiveSerializer::serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(*size + 1 > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = this->responseRequired << 7;
*buffer += 1;
*size += 1;
return result;
}

View File

@ -0,0 +1,18 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUSERIALIZER_H_
#define FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUSERIALIZER_H_
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
class PromptPduSerializer: public FileDirectiveSerializer {
public:
PromptPduSerializer(PduConfig& conf, cfdp::PromptResponseRequired responseRequired);
size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
private:
cfdp::PromptResponseRequired responseRequired;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_PROMPTPDUSERIALIZER_H_ */

View File

@ -0,0 +1,127 @@
#include "VarLenField.h"
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/serialize/SerializeAdapter.h"
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value): VarLenField() {
ReturnValue_t result = this->setValue(width, value);
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_DISABLE_PRINTOUT == 0
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::VarLenField: Setting value failed" << std::endl;
#else
sif::printWarning("cfdp::VarLenField: Setting value failed\n");
#endif
#endif
}
}
cfdp::VarLenField::VarLenField(): width(cfdp::WidthInBytes::ONE_BYTE) {
value.oneByte = 0;
}
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const {
return width;
}
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value) {
switch(widthInBytes) {
case(cfdp::WidthInBytes::ONE_BYTE): {
if(value > UINT8_MAX) {
return HasReturnvaluesIF::RETURN_FAILED;
}
this->value.oneByte = value;
break;
}
case(cfdp::WidthInBytes::TWO_BYTES): {
if(value > UINT16_MAX) {
return HasReturnvaluesIF::RETURN_FAILED;
}
this->value.twoBytes = value;
break;
}
case(cfdp::WidthInBytes::FOUR_BYTES): {
if(value > UINT32_MAX) {
return HasReturnvaluesIF::RETURN_FAILED;
}
this->value.fourBytes = value;
break;
}
default: {
break;
}
}
this->width = widthInBytes;
return HasReturnvaluesIF::RETURN_OK;
}
size_t cfdp::VarLenField::getValue() const {
switch(width) {
case(cfdp::WidthInBytes::ONE_BYTE): {
return value.oneByte;
}
case(cfdp::WidthInBytes::TWO_BYTES): {
return value.twoBytes;
}
case(cfdp::WidthInBytes::FOUR_BYTES): {
return value.fourBytes;
}
}
return 0;
}
ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
switch(width) {
case(cfdp::WidthInBytes::ONE_BYTE): {
if (*size + 1 > maxSize) {
return BUFFER_TOO_SHORT;
}
**buffer = value.oneByte;
*size += 1;
*buffer += 1;
return HasReturnvaluesIF::RETURN_OK;
}
case(cfdp::WidthInBytes::TWO_BYTES): {
return SerializeAdapter::serialize(&value.twoBytes, buffer, size, maxSize,
streamEndianness);
}
case(cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize,
streamEndianness);
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
}
size_t cfdp::VarLenField::getSerializedSize() const {
return width;
}
ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer,
size_t *size, Endianness streamEndianness) {
this->width = width;
return deSerialize(buffer, size, streamEndianness);
}
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
switch(width) {
case(cfdp::WidthInBytes::ONE_BYTE): {
value.oneByte = **buffer;
*size += 1;
return HasReturnvaluesIF::RETURN_OK;
}
case(cfdp::WidthInBytes::TWO_BYTES): {
return SerializeAdapter::deSerialize(&value.twoBytes, buffer, size, streamEndianness);
}
case(cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
}

View File

@ -0,0 +1,45 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_VARLENFIELD_H_
#define FSFW_SRC_FSFW_CFDP_PDU_VARLENFIELD_H_
#include "../definitions.h"
#include "fsfw/serialize/SerializeIF.h"
#include <cstddef>
#include <cstdint>
namespace cfdp {
class VarLenField: public SerializeIF {
public:
union LengthFieldLen {
uint8_t oneByte;
uint16_t twoBytes;
uint32_t fourBytes;
uint64_t eightBytes;
};
VarLenField();
VarLenField(cfdp::WidthInBytes width, size_t value);
ReturnValue_t setValue(cfdp::WidthInBytes, size_t value);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer, size_t *size,
Endianness streamEndianness);
cfdp::WidthInBytes getWidth() const;
size_t getValue() const;
private:
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
cfdp::WidthInBytes width;
LengthFieldLen value;
};
}
#endif /* FSFW_SRC_FSFW_CFDP_PDU_VARLENFIELD_H_ */

View File

@ -0,0 +1,10 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
EntityIdTlv.cpp
FilestoreRequestTlv.cpp
FilestoreResponseTlv.cpp
Lv.cpp
Tlv.cpp
FlowLabelTlv.cpp
MessageToUserTlv.cpp
FaultHandlerOverrideTlv.cpp
)

View File

@ -0,0 +1,68 @@
#include "EntityIdTlv.h"
#include <array>
EntityIdTlv::EntityIdTlv(cfdp::EntityId& entityId): entityId(entityId) {
}
EntityIdTlv::~EntityIdTlv() {
}
ReturnValue_t EntityIdTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
if(maxSize < this->getSerializedSize()) {
return BUFFER_TOO_SHORT;
}
**buffer = cfdp::TlvTypes::ENTITY_ID;
*size += 1;
*buffer += 1;
size_t serLen = entityId.getSerializedSize();
**buffer = serLen;
*size += 1;
*buffer += 1;
return entityId.serialize(buffer, size, maxSize, streamEndianness);
}
size_t EntityIdTlv::getSerializedSize() const {
return getLengthField() + 1;
}
ReturnValue_t EntityIdTlv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if(*size < 3) {
return STREAM_TOO_SHORT;
}
cfdp::TlvTypes type = static_cast<cfdp::TlvTypes>(**buffer);
if(type != cfdp::TlvTypes::ENTITY_ID) {
return cfdp::INVALID_TLV_TYPE;
}
*buffer += 1;
*size -= 1;
cfdp::WidthInBytes width = static_cast<cfdp::WidthInBytes>(**buffer);
if (*size < static_cast<size_t>(1 + width)) {
return STREAM_TOO_SHORT;
}
*buffer += 1;
*size -= 1;
return entityId.deSerialize(width, buffer, size, streamEndianness);
}
ReturnValue_t EntityIdTlv::deSerialize(cfdp::Tlv &tlv, Endianness endianness) {
const uint8_t* ptr = tlv.getValue() + 2;
size_t remSz = tlv.getSerializedSize() - 2;
cfdp::WidthInBytes width = static_cast<cfdp::WidthInBytes>(remSz);
return entityId.deSerialize(width, &ptr, &remSz, endianness);
}
uint8_t EntityIdTlv::getLengthField() const {
return 1 + entityId.getSerializedSize();
}
cfdp::TlvTypes EntityIdTlv::getType() const {
return cfdp::TlvTypes::ENTITY_ID;
}
cfdp::EntityId& EntityIdTlv::getEntityId() {
return entityId;
}

View File

@ -0,0 +1,39 @@
#ifndef FSFW_SRC_FSFW_CFDP_ENTITYIDTLV_H_
#define FSFW_SRC_FSFW_CFDP_ENTITYIDTLV_H_
#include "fsfw/cfdp/tlv/Tlv.h"
#include "fsfw/cfdp/pdu/PduConfig.h"
#include "TlvIF.h"
class EntityIdTlv: public TlvIF {
public:
EntityIdTlv(cfdp::EntityId& entityId);
virtual~ EntityIdTlv();
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
/**
* Deserialize an entity ID from a raw TLV object
* @param tlv
* @param endianness
* @return
*/
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
uint8_t getLengthField() const override;
cfdp::TlvTypes getType() const override;
cfdp::EntityId& getEntityId();
private:
cfdp::EntityId& entityId;
};
#endif /* FSFW_SRC_FSFW_CFDP_ENTITYIDTLV_H_ */

View File

@ -0,0 +1,64 @@
#include "FaultHandlerOverrideTlv.h"
FaultHandlerOverrideTlv::FaultHandlerOverrideTlv(cfdp::ConditionCode conditionCode,
cfdp::FaultHandlerCode handlerCode):
conditionCode(conditionCode), handlerCode(handlerCode) {
}
FaultHandlerOverrideTlv::FaultHandlerOverrideTlv() {
}
uint8_t FaultHandlerOverrideTlv::getLengthField() const {
return 1;
}
ReturnValue_t FaultHandlerOverrideTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
if((maxSize < 3) or ((*size + 3) > maxSize)) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = getType();
*size += 1;
*buffer += 1;
**buffer = getLengthField();
*size += 1;
*buffer += 1;
**buffer = this->conditionCode << 4 | this->handlerCode;
*buffer += 1;
*size += 1;
return HasReturnvaluesIF::RETURN_OK;
}
size_t FaultHandlerOverrideTlv::getSerializedSize() const {
return getLengthField() + 2;
}
ReturnValue_t FaultHandlerOverrideTlv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if(*size < 3) {
return SerializeIF::STREAM_TOO_SHORT;
}
auto detectedType = static_cast<cfdp::TlvTypes>(**buffer);
if(detectedType != cfdp::TlvTypes::FAULT_HANDLER) {
return cfdp::INVALID_TLV_TYPE;
}
*buffer += 1;
*size -= 1;
size_t detectedSize = **buffer;
if(detectedSize != getLengthField()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
*buffer += 1;
*size += 1;
this->conditionCode = static_cast<cfdp::ConditionCode>((**buffer >> 4) & 0x0f);
this->handlerCode = static_cast<cfdp::FaultHandlerCode>(**buffer & 0x0f);
*buffer += 1;
*size += 1;
return HasReturnvaluesIF::RETURN_OK;
}
cfdp::TlvTypes FaultHandlerOverrideTlv::getType() const {
return cfdp::TlvTypes::FAULT_HANDLER;
}

View File

@ -0,0 +1,39 @@
#ifndef FSFW_SRC_FSFW_CFDP_TLV_FAULTHANDLEROVERRIDETLV_H_
#define FSFW_SRC_FSFW_CFDP_TLV_FAULTHANDLEROVERRIDETLV_H_
#include "TlvIF.h"
namespace cfdp {
enum FaultHandlerCode {
RESERVED = 0b0000,
NOTICE_OF_CANCELLATION = 0b0001,
NOTICE_OF_SUSPENSION = 0b0010,
IGNORE_ERROR = 0b0011,
ABANDON_TRANSACTION = 0b0100
};
}
class FaultHandlerOverrideTlv: public TlvIF {
public:
FaultHandlerOverrideTlv();
FaultHandlerOverrideTlv(cfdp::ConditionCode conditionCode, cfdp::FaultHandlerCode handlerCode);
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
uint8_t getLengthField() const override;
cfdp::TlvTypes getType() const override;
private:
cfdp::ConditionCode conditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
cfdp::FaultHandlerCode handlerCode = cfdp::FaultHandlerCode::RESERVED;
};
#endif /* FSFW_SRC_FSFW_CFDP_TLV_FAULTHANDLEROVERRIDETLV_H_ */

View File

@ -0,0 +1,83 @@
#include "fsfw/cfdp/tlv/FilestoreRequestTlv.h"
#include "fsfw/FSFW.h"
FilestoreRequestTlv::FilestoreRequestTlv(cfdp::FilestoreActionCode actionCode,
cfdp::Lv& firstFileName): FilestoreTlvBase(actionCode, firstFileName) {
}
FilestoreRequestTlv::FilestoreRequestTlv(cfdp::Lv &firstFileName):
FilestoreTlvBase(cfdp::FilestoreActionCode::INVALID, firstFileName) {
}
void FilestoreRequestTlv::setSecondFileName(cfdp::Lv *secondFileName) {
this->secondFileName = secondFileName;
}
ReturnValue_t FilestoreRequestTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = commonSerialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = firstFileName.serialize(buffer, size, maxSize,
streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(requiresSecondFileName()) {
if(secondFileName == nullptr) {
secondFileNameMissing();
return cfdp::FILESTORE_REQUIRES_SECOND_FILE;
}
secondFileName->serialize(buffer, size, maxSize, streamEndianness);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FilestoreRequestTlv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
ReturnValue_t result = commonDeserialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return deSerializeFromValue(buffer, size, streamEndianness);
}
ReturnValue_t FilestoreRequestTlv::deSerialize(cfdp::Tlv &tlv,
SerializeIF::Endianness endianness) {
const uint8_t* ptr = tlv.getValue();
size_t remSz = tlv.getSerializedSize();
return deSerializeFromValue(&ptr, &remSz, endianness);
}
uint8_t FilestoreRequestTlv::getLengthField() const {
size_t secondFileNameLen = 0;
if(secondFileName != nullptr and requiresSecondFileName()) {
secondFileNameLen = secondFileName->getSerializedSize();
}
return 1 + firstFileName.getSerializedSize() + secondFileNameLen;
}
ReturnValue_t FilestoreRequestTlv::deSerializeFromValue(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
this->actionCode = static_cast<cfdp::FilestoreActionCode>((**buffer >> 4) & 0x0f);
*buffer += 1;
*size -= 1;
ReturnValue_t result = firstFileName.deSerialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(requiresSecondFileName()) {
if(secondFileName == nullptr) {
secondFileNameMissing();
return HasReturnvaluesIF::RETURN_FAILED;
}
result = secondFileName->deSerialize(buffer, size, streamEndianness);
}
return result;
}
cfdp::TlvTypes FilestoreRequestTlv::getType() const {
return cfdp::TlvTypes::FILESTORE_REQUEST;
}

View File

@ -0,0 +1,45 @@
#ifndef FSFW_SRC_FSFW_CFDP_FILESTOREREQUESTTLV_H_
#define FSFW_SRC_FSFW_CFDP_FILESTOREREQUESTTLV_H_
#include "fsfw/cfdp/tlv/FilestoreTlvBase.h"
#include "fsfw/cfdp/tlv/Tlv.h"
#include "TlvIF.h"
#include "Lv.h"
#include "../definitions.h"
class FilestoreRequestTlv:
public cfdp::FilestoreTlvBase {
public:
FilestoreRequestTlv(cfdp::FilestoreActionCode actionCode, cfdp::Lv& firstFileName);
FilestoreRequestTlv(cfdp::Lv& firstFileName);
void setSecondFileName(cfdp::Lv* secondFileName);
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
/**
* Deserialize a FS request from a raw TLV object
* @param tlv
* @param endianness
* @return
*/
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
uint8_t getLengthField() const override;
cfdp::TlvTypes getType() const override;
private:
cfdp::Lv* secondFileName = nullptr;
ReturnValue_t deSerializeFromValue(const uint8_t **buffer, size_t *size,
Endianness streamEndianness);
};
#endif /* FSFW_SRC_FSFW_CFDP_FILESTOREREQUESTTLV_H_ */

View File

@ -0,0 +1,124 @@
#include "FilestoreResponseTlv.h"
FilestoreResponseTlv::FilestoreResponseTlv(cfdp::FilestoreActionCode actionCode, uint8_t statusCode,
cfdp::Lv& firstFileName, cfdp::Lv* fsMsg): FilestoreTlvBase(actionCode, firstFileName),
statusCode(statusCode), filestoreMsg(fsMsg) {
}
FilestoreResponseTlv::FilestoreResponseTlv(cfdp::Lv &firstFileName, cfdp::Lv* fsMsg):
FilestoreTlvBase(firstFileName), statusCode(0), filestoreMsg(fsMsg) {
}
uint8_t FilestoreResponseTlv::getLengthField() const {
size_t optFieldsLen = 0;
if(secondFileName != nullptr) {
optFieldsLen += secondFileName->getSerializedSize();
}
if(filestoreMsg != nullptr) {
optFieldsLen += filestoreMsg->getSerializedSize();
} else {
optFieldsLen += 1;
}
return 1 + firstFileName.getSerializedSize() + optFieldsLen;
}
void FilestoreResponseTlv::setSecondFileName(cfdp::Lv *secondFileName) {
this->secondFileName = secondFileName;
}
void FilestoreResponseTlv::setFilestoreMessage(cfdp::Lv *filestoreMsg) {
this->filestoreMsg = filestoreMsg;
}
ReturnValue_t FilestoreResponseTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = commonSerialize(buffer, size, maxSize, streamEndianness,
true, this->statusCode);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = firstFileName.serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(requiresSecondFileName()) {
if(secondFileName == nullptr) {
secondFileNameMissing();
return cfdp::FILESTORE_REQUIRES_SECOND_FILE;
}
}
if(filestoreMsg != nullptr) {
result = filestoreMsg->serialize(buffer, size, maxSize, streamEndianness);
}
else {
if(*size == maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = 0;
*buffer += 1;
*size +=1;
}
return result;
}
ReturnValue_t FilestoreResponseTlv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
ReturnValue_t result = commonDeserialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return deSerializeFromValue(buffer, size, streamEndianness);
}
ReturnValue_t FilestoreResponseTlv::deSerializeFromValue(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
// The common function above checks whether at least one byte is remaining
this->actionCode = static_cast<cfdp::FilestoreActionCode>((**buffer >> 4) & 0x0f);
this->statusCode = **buffer & 0x0f;
*buffer += 1;
*size -= 1;
ReturnValue_t result = firstFileName.deSerialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(requiresSecondFileName()) {
if(secondFileName == nullptr) {
return cfdp::FILESTORE_REQUIRES_SECOND_FILE;
}
result = secondFileName->deSerialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
// If the filestore message is not empty, the deserialization is only considered successfully
// if the filestore message can be parsed. Also, if data follows after the FS response,
// the FS msg needs to be set as well.
if(*size == 0 or (*size > 1 and filestoreMsg == nullptr)) {
// Filestore message missing or can't parse it
return cfdp::FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE;
}
if(filestoreMsg == nullptr) {
*size -= 1;
*buffer += 1;
// Ignore empty filestore message
return HasReturnvaluesIF::RETURN_OK;
}
return filestoreMsg->deSerialize(buffer, size, streamEndianness);
}
ReturnValue_t FilestoreResponseTlv::deSerialize(const cfdp::Tlv &tlv, Endianness endianness) {
const uint8_t* ptr = tlv.getValue();
size_t remSz = tlv.getSerializedSize();
return deSerializeFromValue(&ptr, &remSz, endianness);
}
uint8_t FilestoreResponseTlv::getStatusCode() const {
return statusCode;
}
cfdp::TlvTypes FilestoreResponseTlv::getType() const {
return cfdp::TlvTypes::FILESTORE_RESPONSE;
}

View File

@ -0,0 +1,50 @@
#ifndef FSFW_SRC_FSFW_CFDP_FILESTORERESPONSETLV_H_
#define FSFW_SRC_FSFW_CFDP_FILESTORERESPONSETLV_H_
#include "fsfw/cfdp/tlv/FilestoreTlvBase.h"
#include "fsfw/cfdp/tlv/Tlv.h"
#include "TlvIF.h"
#include "Lv.h"
class FilestoreResponseTlv:
public cfdp::FilestoreTlvBase {
public:
FilestoreResponseTlv(cfdp::Lv& firstFileName, cfdp::Lv* fsMsg);
FilestoreResponseTlv(cfdp::FilestoreActionCode actionCode, uint8_t statusCode,
cfdp::Lv& firstFileName, cfdp::Lv* fsMsg);
uint8_t getStatusCode() const;
void setSecondFileName(cfdp::Lv* secondFileName);
void setFilestoreMessage(cfdp::Lv* filestoreMsg);
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
/**
* Deserialize a filestore response from a raw TLV object
* @param tlv
* @param endianness
* @return
*/
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
uint8_t getLengthField() const override;
cfdp::TlvTypes getType() const override;
private:
uint8_t statusCode;
cfdp::Lv* secondFileName = nullptr;
cfdp::Lv* filestoreMsg = nullptr;
ReturnValue_t deSerializeFromValue(const uint8_t **buffer, size_t *size,
Endianness streamEndianness);
};
#endif /* FSFW_SRC_FSFW_CFDP_FILESTORERESPONSETLV_H_ */

View File

@ -0,0 +1,176 @@
#ifndef FSFW_SRC_FSFW_CFDP_FILESTOREREQUESTBASE_H_
#define FSFW_SRC_FSFW_CFDP_FILESTOREREQUESTBASE_H_
#include <fsfw/cfdp/definitions.h>
#include <fsfw/cfdp/tlv/Lv.h>
#include <fsfw/cfdp/tlv/Tlv.h>
#include <fsfw/cfdp/tlv/TlvIF.h>
#include <fsfw/serialize/SerializeIF.h>
#include <cstddef>
#include <cstdint>
namespace cfdp {
enum FilestoreActionCode {
CREATE_FILE = 0b0000,
DELETE_FILE = 0b0001,
// Second file name present
RENAME_FILE = 0b0010,
// Second file name present
APPEND_FILE = 0b0011,
// Second file name present
REPLACE_FILE = 0b0100,
CREATE_DIRECTORY = 0b0101,
REMOVE_DIRECTORY = 0b0110,
// Delete file if present
DENY_FILE = 0b0111,
// Remove directory if present
DNEY_DIRECTORY = 0b1000,
INVALID = 0b1111
};
// FSR = Filestore Response
static constexpr uint8_t FSR_SUCCESS = 0b0000;
static constexpr uint8_t FSR_NOT_PERFORMED = 0b1111;
static constexpr uint8_t FSR_CREATE_NOT_ALLOWED = 0b0001;
static constexpr uint8_t FSR_DEL_FILE_NOT_EXISTS = 0b0001;
static constexpr uint8_t FSR_DEL_NOT_ALLOWED = 0b0010;
static constexpr uint8_t FSR_RENAME_OLD_FILE_NOT_EXISTS = 0b0001;
static constexpr uint8_t FSR_RENAME_NEW_FILE_ALREADY_EXISTS = 0b0010;
static constexpr uint8_t FSR_RENAME_NOT_ALLOWED = 0b0011;
static constexpr uint8_t FSR_APPEND_FILE_1_NOT_EXISTS = 0b0001;
static constexpr uint8_t FSR_APPEND_FILE_2_NOT_EXISTS = 0b0010;
static constexpr uint8_t FSR_APPEND_NOT_ALLOWED = 0b0011;
static constexpr uint8_t FSR_REPLACE_FILE_1_NOT_EXISTS = 0b0001;
static constexpr uint8_t FSR_REPLACE_FILE_2_NOT_EXISTS = 0b0010;
static constexpr uint8_t FSR_REPLACE_REPLACE_NOT_ALLOWED = 0b0011;
static constexpr uint8_t FSR_CREATE_DIR_NOT_POSSIBLE = 0b0001;
static constexpr uint8_t FSR_DELDIR_NOT_EXISTS = 0b0001;
static constexpr uint8_t FSR_DELDIR_NOT_ALLOWED = 0b0010;
static constexpr uint8_t FSR_DENY_FILE_NOT_ALLOWED = 0b0010;
static constexpr uint8_t FSR_DENY_DIR_NOT_ALLOWED = 0b0010;
class FilestoreTlvBase: public TlvIF {
public:
FilestoreTlvBase(cfdp::Lv& firstFileName): firstFileName(firstFileName) {};
FilestoreTlvBase(FilestoreActionCode actionCode, cfdp::Lv& firstFileName):
actionCode(actionCode), firstFileName(firstFileName) {};
ReturnValue_t commonSerialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness,
bool isResponse = false, uint8_t responseStatusCode = 0) const {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(maxSize < 3) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = getType();
*buffer += 1;
*size += 1;
**buffer = getLengthField();
*buffer += 1;
*size += 1;
**buffer = this->actionCode << 4;
if(isResponse) {
**buffer |= responseStatusCode;
}
*buffer += 1;
*size += 1;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t commonDeserialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(*size < 3) {
return SerializeIF::STREAM_TOO_SHORT;
}
cfdp::TlvTypes type = static_cast<cfdp::TlvTypes>(**buffer);
if(type != getType()) {
return cfdp::INVALID_TLV_TYPE;
}
*size -= 1;
*buffer += 1;
size_t remainingLength = **buffer;
*size -= 1;
*buffer += 1;
if(remainingLength == 0) {
return SerializeIF::STREAM_TOO_SHORT;
}
return HasReturnvaluesIF::RETURN_OK;
}
bool requiresSecondFileName() const {
using namespace cfdp;
if(actionCode == FilestoreActionCode::RENAME_FILE or
actionCode == FilestoreActionCode::APPEND_FILE or
actionCode == FilestoreActionCode::REPLACE_FILE) {
return true;
}
return false;
}
void secondFileNameMissing() const {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "FilestoreRequestTlv::deSerialize: Second file name required"
" but TLV pointer not set" << std::endl;
#else
sif::printWarning("FilestoreRequestTlv::deSerialize: Second file name required"
" but TLV pointer not set\n");
#endif
#endif
}
FilestoreActionCode getActionCode() const {
return actionCode;
}
void setActionCode(FilestoreActionCode actionCode) {
this->actionCode = actionCode;
}
cfdp::Lv& getFirstFileName() {
return firstFileName;
}
ReturnValue_t convertToTlv(cfdp::Tlv& tlv, uint8_t *buffer, size_t maxSize,
Endianness streamEndianness) {
size_t serSize = 0;
uint8_t* valueStart = buffer + 2;
ReturnValue_t result = this->serialize(&buffer, &serSize, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
tlv.setValue(valueStart, serSize - 2);
tlv.setType(getType());
return result;
}
size_t getSerializedSize() const override {
return getLengthField() + 2;
}
protected:
FilestoreActionCode actionCode = FilestoreActionCode::INVALID;
cfdp::Lv& firstFileName;
};
}
#endif /* FSFW_SRC_FSFW_CFDP_FILESTOREREQUESTBASE_H_ */

View File

@ -0,0 +1,5 @@
#include "FlowLabelTlv.h"
FlowLabelTlv::FlowLabelTlv(uint8_t* value, size_t size):
Tlv(cfdp::TlvTypes::FLOW_LABEL, value, size) {
}

View File

@ -0,0 +1,13 @@
#ifndef FSFW_SRC_FSFW_CFDP_TLV_FLOWLABELTLV_H_
#define FSFW_SRC_FSFW_CFDP_TLV_FLOWLABELTLV_H_
#include "Tlv.h"
class FlowLabelTlv: public cfdp::Tlv {
public:
FlowLabelTlv(uint8_t* value, size_t size);
private:
};
#endif /* FSFW_SRC_FSFW_CFDP_TLV_FLOWLABELTLV_H_ */

88
src/fsfw/cfdp/tlv/Lv.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "Lv.h"
cfdp::Lv::Lv(const uint8_t *value, size_t size): value(value, size, true) {
if(size > 0) {
zeroLen = false;
}
}
cfdp::Lv::Lv(): value(static_cast<uint8_t*>(nullptr), 0, true) {
}
cfdp::Lv::Lv(const Lv& other):
value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
if(other.value.getSerializedSize() - 1 > 0) {
zeroLen = false;
}
}
cfdp::Lv& cfdp::Lv::operator =(const Lv& other) {
size_t otherSize = 0;
uint8_t* value = const_cast<uint8_t*>(other.getValue(&otherSize));
if (value == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setBuffer(value, otherSize);
return *this;
}
ReturnValue_t cfdp::Lv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
if(maxSize < 1) {
return BUFFER_TOO_SHORT;
}
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(zeroLen) {
**buffer = 0;
*size += 1;
*buffer += 1;
return HasReturnvaluesIF::RETURN_OK;
}
return value.serialize(buffer, size, maxSize, streamEndianness);
}
size_t cfdp::Lv::getSerializedSize() const {
if(zeroLen) {
return 1;
}
else if(value.getConstBuffer() == nullptr) {
return 0;
}
return value.getSerializedSize();
}
ReturnValue_t cfdp::Lv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(*size < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
size_t lengthField = **buffer;
if(lengthField == 0) {
zeroLen = true;
*buffer += 1;
*size -= 1;
return HasReturnvaluesIF::RETURN_OK;
} else if(*size < lengthField + 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
zeroLen = false;
// Zero-copy implementation
value.setBuffer(const_cast<uint8_t*>(*buffer + 1), lengthField);
*buffer += 1 + lengthField;
*size -= 1 + lengthField;
return HasReturnvaluesIF::RETURN_OK;
}
const uint8_t* cfdp::Lv::getValue(size_t* size) const {
if(size != nullptr) {
// Length without length field
*size = value.getSerializedSize() - 1;
}
return value.getConstBuffer();
}

53
src/fsfw/cfdp/tlv/Lv.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef FSFW_SRC_FSFW_CFDP_LV_H_
#define FSFW_SRC_FSFW_CFDP_LV_H_
#include "fsfw/serialize/SerialBufferAdapter.h"
namespace cfdp {
/**
* @brief Length-Value field implementation
* @details
* Thin abstraction layer around a serial buffer adapter
*/
class Lv: public SerializeIF {
public:
Lv(const uint8_t* value, size_t size);
Lv();
// Delete copy ctor and assingment ctor for now because this class contains a reference to
// data
Lv (const Lv&);
Lv& operator= (const Lv&);
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
/**
* @brief Deserialize a LV field from a raw buffer
* @param buffer Raw buffer including the size field
* @param size
* @param streamEndianness
* @return
*/
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
/**
* Get value field and its size.
* @param size Optionally retrieve size. Size will be the size of the actual value field
* without the length field of the LV
* @return
*/
const uint8_t* getValue(size_t* size) const;
private:
bool zeroLen = true;
SerialBufferAdapter<uint8_t> value;
};
}
#endif /* FSFW_SRC_FSFW_CFDP_LV_H_ */

View File

@ -0,0 +1,8 @@
#include "MessageToUserTlv.h"
MessageToUserTlv::MessageToUserTlv(uint8_t *value, size_t size):
Tlv(cfdp::TlvTypes::MSG_TO_USER, value, size) {
}
MessageToUserTlv::MessageToUserTlv(): Tlv() {
}

View File

@ -0,0 +1,13 @@
#ifndef FSFW_SRC_FSFW_CFDP_TLV_MESSAGETOUSERTLV_H_
#define FSFW_SRC_FSFW_CFDP_TLV_MESSAGETOUSERTLV_H_
#include "Tlv.h"
class MessageToUserTlv: public cfdp::Tlv {
public:
MessageToUserTlv();
MessageToUserTlv(uint8_t* value, size_t size);
private:
};
#endif /* FSFW_SRC_FSFW_CFDP_TLV_MESSAGETOUSERTLV_H_ */

114
src/fsfw/cfdp/tlv/Tlv.cpp Normal file
View File

@ -0,0 +1,114 @@
#include "Tlv.h"
cfdp::Tlv::Tlv(TlvTypes type, const uint8_t *value, size_t size): type(type),
value(value, size, true) {
if(size > 0) {
zeroLen = false;
}
}
cfdp::Tlv::Tlv(): value(static_cast<uint8_t*>(nullptr), 0, true) {
}
ReturnValue_t cfdp::Tlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(*size + 2 > maxSize) {
return BUFFER_TOO_SHORT;
}
if(type == TlvTypes::INVALID_TLV) {
return INVALID_TLV_TYPE;
}
**buffer = type;
*size += 1;
*buffer += 1;
if(zeroLen) {
**buffer = 0;
*size += 1;
*buffer += 1;
return HasReturnvaluesIF::RETURN_OK;
}
if(value.getConstBuffer() == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return value.serialize(buffer, size, maxSize, streamEndianness);
}
size_t cfdp::Tlv::getSerializedSize() const {
if(zeroLen) {
return 2;
}
else if (value.getConstBuffer() == nullptr) {
return 0;
}
return value.getSerializedSize() + 1;
}
ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if(buffer == nullptr or size == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(*size < 2) {
return STREAM_TOO_SHORT;
}
uint8_t rawType = **buffer;
if(not checkType(rawType)) {
return INVALID_TLV_TYPE;
}
type = static_cast<TlvTypes>(rawType);
*buffer += 1;
*size -= 1;
size_t lengthField = **buffer;
if(lengthField == 0) {
zeroLen = true;
*buffer += 1;
*size -= 1;
return HasReturnvaluesIF::RETURN_OK;
}
if(lengthField + 1 > *size) {
return SerializeIF::STREAM_TOO_SHORT;
}
zeroLen = false;
// Zero-copy implementation
value.setBuffer(const_cast<uint8_t*>(*buffer + 1), lengthField);
*buffer += 1 + lengthField;
*size -= 1 + lengthField;
return HasReturnvaluesIF::RETURN_OK;
}
const uint8_t* cfdp::Tlv::getValue() const {
return value.getConstBuffer();
}
cfdp::TlvTypes cfdp::Tlv::getType() const {
return type;
}
bool cfdp::Tlv::checkType(uint8_t rawType) {
if (rawType != 0x03 and rawType <= 6) {
return true;
}
return false;
}
void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
if(len > 0) {
zeroLen = false;
}
this->value.setBuffer(value, len);
}
uint8_t cfdp::Tlv::getLengthField() const {
return this->value.getSerializedSize() - 1;
}
void cfdp::Tlv::setType(TlvTypes type) {
this->type = type;
}

64
src/fsfw/cfdp/tlv/Tlv.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef FSFW_SRC_FSFW_CFDP_TLV_H_
#define FSFW_SRC_FSFW_CFDP_TLV_H_
#include "TlvIF.h"
#include "fsfw/serialize/SerialBufferAdapter.h"
namespace cfdp {
/**
* @brief Type-Length-Value field implementation
* @details
* Thin abstraction layer around a serial buffer adapter
*/
class Tlv: public TlvIF {
public:
Tlv(TlvTypes type, const uint8_t *value, size_t size);
Tlv();
/**
* Serialize a TLV into a given buffer
* @param buffer
* @param size
* @param maxSize
* @param streamEndianness
* @return
* - RETURN_OK on success
* - INVALID_TLV_TYPE
* - SerializeIF returncode on wrong serialization parameters
*/
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
/**
* @brief Deserialize a LV field from a raw buffer. Zero-copy implementation
* @param buffer Raw buffer including the size field
* @param size
* @param streamEndianness
* - RETURN_OK on success
* - INVALID_TLV_TYPE
* - SerializeIF returncode on wrong deserialization parameters
*/
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
void setValue(uint8_t *value, size_t len);
const uint8_t* getValue() const;
void setType(TlvTypes type);
TlvTypes getType() const override;
uint8_t getLengthField() const override;
private:
bool checkType(uint8_t rawType);
bool zeroLen = true;
TlvTypes type = TlvTypes::INVALID_TLV;
SerialBufferAdapter<uint8_t> value;
};
}
#endif /* FSFW_SRC_FSFW_CFDP_TLV_H_ */

16
src/fsfw/cfdp/tlv/TlvIF.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef FSFW_SRC_FSFW_CFDP_TLVIF_H_
#define FSFW_SRC_FSFW_CFDP_TLVIF_H_
#include "../definitions.h"
class TlvIF: public SerializeIF {
public:
virtual~ TlvIF() {};
virtual uint8_t getLengthField() const = 0;
virtual cfdp::TlvTypes getType() const = 0;
};
#endif /* FSFW_SRC_FSFW_CFDP_TLVIF_H_ */

View File

@ -8,11 +8,10 @@
#include "fsfw/datapoollocal/LocalDataPoolManager.h" #include "fsfw/datapoollocal/LocalDataPoolManager.h"
/** /**
* @brief Extendes the basic ControllerBase with the common components * @brief Extends the basic ControllerBase with commonly used components
* HasActionsIF for commandability and HasLocalDataPoolIF to keep
* a pool of local data pool variables.
* @details * @details
* Default implementations required for the interfaces will be empty and have * HasActionsIF for commandability and HasLocalDataPoolIF to keep a pool of local data pool
* variables. Default implementations required for the interfaces will be empty and have
* to be implemented by child class. * to be implemented by child class.
*/ */
class ExtendedControllerBase: public ControllerBase, class ExtendedControllerBase: public ControllerBase,

View File

@ -7,7 +7,7 @@
/** /**
* @brief Base class to implement reconfiguration and failure handling for * @brief Base class to implement reconfiguration and failure handling for
* redundant devices by monitoring their modes health states. * redundant devices by monitoring their modes and health states.
* @details * @details
* Documentation: Dissertation Baetz p.156, 157. * Documentation: Dissertation Baetz p.156, 157.
* *

View File

@ -85,9 +85,10 @@ public:
* Called by DHB in the GET_WRITE doGetWrite(). * Called by DHB in the GET_WRITE doGetWrite().
* Get send confirmation that the data in sendMessage() was sent successfully. * Get send confirmation that the data in sendMessage() was sent successfully.
* @param cookie * @param cookie
* @return - @c RETURN_OK if data was sent successfull * @return
* - Everything else triggers falure event with * - @c RETURN_OK if data was sent successfully but a reply is expected
* returnvalue as parameter 1 * - NO_REPLY_EXPECTED if data was sent successfully and no reply is expected
* - Everything else to indicate failure
*/ */
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0;

View File

@ -78,15 +78,16 @@ class StorageManagerIF;
* *
* @ingroup devices * @ingroup devices
*/ */
class DeviceHandlerBase: public DeviceHandlerIF, class DeviceHandlerBase:
public HasReturnvaluesIF, public DeviceHandlerIF,
public ExecutableObjectIF, public HasReturnvaluesIF,
public SystemObject, public ExecutableObjectIF,
public HasModesIF, public SystemObject,
public HasHealthIF, public HasModesIF,
public HasActionsIF, public HasHealthIF,
public ReceivesParameterMessagesIF, public HasActionsIF,
public HasLocalDataPoolIF { public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
friend void (Factory::setStaticFrameworkObjectIds)(); friend void (Factory::setStaticFrameworkObjectIds)();
public: public:
/** /**
@ -334,8 +335,7 @@ protected:
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen * - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
* have been set. * have been set.
* - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can * - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can
* be used if no reply is expected. Otherwise, the developer can call #actionHelper.finish * be used if no reply is expected
* to finish the command handling.
* - Anything else triggers an event with the return code as a parameter as well as a * - Anything else triggers an event with the return code as a parameter as well as a
* step reply failed with the return code * step reply failed with the return code
*/ */

View File

@ -120,7 +120,8 @@ public:
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7); static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command. //!< Used to indicate that this is a command-only command.
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8);
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9); static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA); static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);

View File

@ -9,6 +9,7 @@ enum FsfwMessageTypes {
HEALTH_COMMAND, HEALTH_COMMAND,
MODE_SEQUENCE, MODE_SEQUENCE,
ACTION, ACTION,
CFDP,
TM_STORE, TM_STORE,
DEVICE_HANDLER_COMMAND, DEVICE_HANDLER_COMMAND,
MONITORING, MONITORING,

View File

@ -19,6 +19,9 @@ enum framework_objects: object_id_t {
PUS_SERVICE_200_MODE_MGMT = 0x53000200, PUS_SERVICE_200_MODE_MGMT = 0x53000200,
PUS_SERVICE_201_HEALTH = 0x53000201, PUS_SERVICE_201_HEALTH = 0x53000201,
/* CFDP Distributer */
CFDP_PACKET_DISTRIBUTOR = 0x53001000,
//Generic IDs for IPC, modes, health, events //Generic IDs for IPC, modes, health, events
HEALTH_TABLE = 0x53010000, HEALTH_TABLE = 0x53010000,
// MODE_STORE = 0x53010100, // MODE_STORE = 0x53010100,

View File

@ -15,6 +15,7 @@ target_sources(${LIB_FSFW_NAME}
TaskFactory.cpp TaskFactory.cpp
tcpipHelpers.cpp tcpipHelpers.cpp
unixUtility.cpp unixUtility.cpp
CommandExecutor.cpp
) )
find_package(Threads REQUIRED) find_package(Threads REQUIRED)

View File

@ -285,10 +285,10 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
utility::printUnixErrorGeneric(CLASS_NAME, "sendMessageFromMessageQueue", "EBADF"); utility::printUnixErrorGeneric(CLASS_NAME, "sendMessageFromMessageQueue", "EBADF");
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "mq_send to: " << sendTo << " sent from " sif::warning << "mq_send to " << sendTo << " sent from "
<< sentFrom << "failed" << std::endl; << sentFrom << " failed" << std::endl;
#else #else
sif::printWarning("mq_send to: %d sent from %d failed\n", sendTo, sentFrom); sif::printWarning("mq_send to %d sent from %d failed\n", sendTo, sentFrom);
#endif #endif
return DESTINATION_INVALID; return DESTINATION_INVALID;
} }

View File

@ -60,6 +60,7 @@ enum: uint8_t {
HAS_ACTIONS_IF, //HF HAS_ACTIONS_IF, //HF
DEVICE_COMMUNICATION_IF, //DC DEVICE_COMMUNICATION_IF, //DC
BSP, //BSP BSP, //BSP
CFDP, //CFDP
TIME_STAMPER_IF, //TSI TIME_STAMPER_IF, //TSI
SGP4PROPAGATOR_CLASS, //SGP4 SGP4PROPAGATOR_CLASS, //SGP4
MUTEX_IF, //MUX MUTEX_IF, //MUX

View File

@ -105,7 +105,7 @@ uint8_t * SerialBufferAdapter<count_t>::getBuffer() {
} }
template<typename count_t> template<typename count_t>
const uint8_t * SerialBufferAdapter<count_t>::getConstBuffer() { const uint8_t * SerialBufferAdapter<count_t>::getConstBuffer() const {
if(constBuffer == nullptr) { if(constBuffer == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SerialBufferAdapter::getConstBuffer:" sif::error << "SerialBufferAdapter::getConstBuffer:"

Some files were not shown because too many files have changed in this diff Show More