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:
parent
bf31248a50
commit
5907f8ee9d
@ -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()
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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 {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
60
src/fsfw/cfdp/CFDPHandler.cpp
Normal file
60
src/fsfw/cfdp/CFDPHandler.cpp
Normal 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(¤tMessage); status == RETURN_OK;
|
||||||
|
status = this->requestQueue->receiveMessage(¤tMessage)) {
|
||||||
|
store_address_t storeId = CFDPMessage::getStoreId(¤tMessage);
|
||||||
|
this->handleRequest(storeId);
|
||||||
|
}
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CFDPHandler::getIdentifier() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t CFDPHandler::getRequestQueue() {
|
||||||
|
return this->requestQueue->getId();
|
||||||
|
}
|
62
src/fsfw/cfdp/CFDPHandler.h
Normal file
62
src/fsfw/cfdp/CFDPHandler.h
Normal 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_ */
|
21
src/fsfw/cfdp/CFDPMessage.cpp
Normal file
21
src/fsfw/cfdp/CFDPMessage.cpp
Normal 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) {
|
||||||
|
}
|
23
src/fsfw/cfdp/CFDPMessage.h
Normal file
23
src/fsfw/cfdp/CFDPMessage.h
Normal 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_ */
|
7
src/fsfw/cfdp/CMakeLists.txt
Normal file
7
src/fsfw/cfdp/CMakeLists.txt
Normal 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
83
src/fsfw/cfdp/FileSize.h
Normal 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
153
src/fsfw/cfdp/definitions.h
Normal 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_ */
|
52
src/fsfw/cfdp/pdu/AckInfo.cpp
Normal file
52
src/fsfw/cfdp/pdu/AckInfo.cpp
Normal 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;
|
||||||
|
}
|
33
src/fsfw/cfdp/pdu/AckInfo.h
Normal file
33
src/fsfw/cfdp/pdu/AckInfo.h
Normal 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_ */
|
38
src/fsfw/cfdp/pdu/AckPduDeserializer.cpp
Normal file
38
src/fsfw/cfdp/pdu/AckPduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
26
src/fsfw/cfdp/pdu/AckPduDeserializer.h
Normal file
26
src/fsfw/cfdp/pdu/AckPduDeserializer.h
Normal 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_ */
|
38
src/fsfw/cfdp/pdu/AckPduSerializer.cpp
Normal file
38
src/fsfw/cfdp/pdu/AckPduSerializer.cpp
Normal 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;
|
||||||
|
}
|
30
src/fsfw/cfdp/pdu/AckPduSerializer.h
Normal file
30
src/fsfw/cfdp/pdu/AckPduSerializer.h
Normal 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_ */
|
32
src/fsfw/cfdp/pdu/CMakeLists.txt
Normal file
32
src/fsfw/cfdp/pdu/CMakeLists.txt
Normal 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
|
||||||
|
)
|
58
src/fsfw/cfdp/pdu/EofInfo.cpp
Normal file
58
src/fsfw/cfdp/pdu/EofInfo.cpp
Normal 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);
|
||||||
|
}
|
33
src/fsfw/cfdp/pdu/EofInfo.h
Normal file
33
src/fsfw/cfdp/pdu/EofInfo.h
Normal 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_ */
|
68
src/fsfw/cfdp/pdu/EofPduDeserializer.cpp
Normal file
68
src/fsfw/cfdp/pdu/EofPduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
18
src/fsfw/cfdp/pdu/EofPduDeserializer.h
Normal file
18
src/fsfw/cfdp/pdu/EofPduDeserializer.h
Normal 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_ */
|
46
src/fsfw/cfdp/pdu/EofPduSerializer.cpp
Normal file
46
src/fsfw/cfdp/pdu/EofPduSerializer.cpp
Normal 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;
|
||||||
|
}
|
22
src/fsfw/cfdp/pdu/EofPduSerializer.h
Normal file
22
src/fsfw/cfdp/pdu/EofPduSerializer.h
Normal 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_ */
|
52
src/fsfw/cfdp/pdu/FileDataDeserializer.cpp
Normal file
52
src/fsfw/cfdp/pdu/FileDataDeserializer.cpp
Normal 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;
|
||||||
|
}
|
22
src/fsfw/cfdp/pdu/FileDataDeserializer.h
Normal file
22
src/fsfw/cfdp/pdu/FileDataDeserializer.h
Normal 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_ */
|
104
src/fsfw/cfdp/pdu/FileDataInfo.cpp
Normal file
104
src/fsfw/cfdp/pdu/FileDataInfo.cpp
Normal 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;
|
||||||
|
}
|
45
src/fsfw/cfdp/pdu/FileDataInfo.h
Normal file
45
src/fsfw/cfdp/pdu/FileDataInfo.h
Normal 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_ */
|
54
src/fsfw/cfdp/pdu/FileDataSerializer.cpp
Normal file
54
src/fsfw/cfdp/pdu/FileDataSerializer.cpp
Normal 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());
|
||||||
|
}
|
23
src/fsfw/cfdp/pdu/FileDataSerializer.h
Normal file
23
src/fsfw/cfdp/pdu/FileDataSerializer.h
Normal 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_ */
|
55
src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp
Normal file
55
src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp
Normal 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;
|
||||||
|
}
|
41
src/fsfw/cfdp/pdu/FileDirectiveDeserializer.h
Normal file
41
src/fsfw/cfdp/pdu/FileDirectiveDeserializer.h
Normal 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_ */
|
39
src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp
Normal file
39
src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp
Normal 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);
|
||||||
|
}
|
28
src/fsfw/cfdp/pdu/FileDirectiveSerializer.h
Normal file
28
src/fsfw/cfdp/pdu/FileDirectiveSerializer.h
Normal 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_ */
|
111
src/fsfw/cfdp/pdu/FinishedInfo.cpp
Normal file
111
src/fsfw/cfdp/pdu/FinishedInfo.cpp
Normal 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;
|
||||||
|
}
|
45
src/fsfw/cfdp/pdu/FinishedInfo.h
Normal file
45
src/fsfw/cfdp/pdu/FinishedInfo.h
Normal 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_ */
|
90
src/fsfw/cfdp/pdu/FinishedPduDeserializer.cpp
Normal file
90
src/fsfw/cfdp/pdu/FinishedPduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
21
src/fsfw/cfdp/pdu/FinishedPduDeserializer.h
Normal file
21
src/fsfw/cfdp/pdu/FinishedPduDeserializer.h
Normal 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_ */
|
47
src/fsfw/cfdp/pdu/FinishedPduSerializer.cpp
Normal file
47
src/fsfw/cfdp/pdu/FinishedPduSerializer.cpp
Normal 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;
|
||||||
|
}
|
22
src/fsfw/cfdp/pdu/FinishedPduSerializer.h
Normal file
22
src/fsfw/cfdp/pdu/FinishedPduSerializer.h
Normal 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_ */
|
136
src/fsfw/cfdp/pdu/HeaderDeserializer.cpp
Normal file
136
src/fsfw/cfdp/pdu/HeaderDeserializer.cpp
Normal 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;
|
||||||
|
}
|
93
src/fsfw/cfdp/pdu/HeaderDeserializer.h
Normal file
93
src/fsfw/cfdp/pdu/HeaderDeserializer.h
Normal 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_ */
|
135
src/fsfw/cfdp/pdu/HeaderSerializer.cpp
Normal file
135
src/fsfw/cfdp/pdu/HeaderSerializer.cpp
Normal 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;
|
||||||
|
}
|
64
src/fsfw/cfdp/pdu/HeaderSerializer.h
Normal file
64
src/fsfw/cfdp/pdu/HeaderSerializer.h
Normal 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_ */
|
20
src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.cpp
Normal file
20
src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
18
src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.h
Normal file
18
src/fsfw/cfdp/pdu/KeepAlivePduDeserializer.h
Normal 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_ */
|
26
src/fsfw/cfdp/pdu/KeepAlivePduSerializer.cpp
Normal file
26
src/fsfw/cfdp/pdu/KeepAlivePduSerializer.cpp
Normal 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);
|
||||||
|
}
|
21
src/fsfw/cfdp/pdu/KeepAlivePduSerializer.h
Normal file
21
src/fsfw/cfdp/pdu/KeepAlivePduSerializer.h
Normal 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_ */
|
115
src/fsfw/cfdp/pdu/MetadataInfo.cpp
Normal file
115
src/fsfw/cfdp/pdu/MetadataInfo.cpp
Normal 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;
|
||||||
|
}
|
49
src/fsfw/cfdp/pdu/MetadataInfo.h
Normal file
49
src/fsfw/cfdp/pdu/MetadataInfo.h
Normal 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_ */
|
58
src/fsfw/cfdp/pdu/MetadataPduDeserializer.cpp
Normal file
58
src/fsfw/cfdp/pdu/MetadataPduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
18
src/fsfw/cfdp/pdu/MetadataPduDeserializer.h
Normal file
18
src/fsfw/cfdp/pdu/MetadataPduDeserializer.h
Normal 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_ */
|
54
src/fsfw/cfdp/pdu/MetadataPduSerializer.cpp
Normal file
54
src/fsfw/cfdp/pdu/MetadataPduSerializer.cpp
Normal 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;
|
||||||
|
}
|
23
src/fsfw/cfdp/pdu/MetadataPduSerializer.h
Normal file
23
src/fsfw/cfdp/pdu/MetadataPduSerializer.h
Normal 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_ */
|
83
src/fsfw/cfdp/pdu/NakInfo.cpp
Normal file
83
src/fsfw/cfdp/pdu/NakInfo.cpp
Normal 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;
|
||||||
|
}
|
40
src/fsfw/cfdp/pdu/NakInfo.h
Normal file
40
src/fsfw/cfdp/pdu/NakInfo.h
Normal 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_ */
|
58
src/fsfw/cfdp/pdu/NakPduDeserializer.cpp
Normal file
58
src/fsfw/cfdp/pdu/NakPduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
22
src/fsfw/cfdp/pdu/NakPduDeserializer.h
Normal file
22
src/fsfw/cfdp/pdu/NakPduDeserializer.h
Normal 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_ */
|
49
src/fsfw/cfdp/pdu/NakPduSerializer.cpp
Normal file
49
src/fsfw/cfdp/pdu/NakPduSerializer.cpp
Normal 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;
|
||||||
|
}
|
41
src/fsfw/cfdp/pdu/NakPduSerializer.h
Normal file
41
src/fsfw/cfdp/pdu/NakPduSerializer.h
Normal 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_ */
|
8
src/fsfw/cfdp/pdu/PduConfig.cpp
Normal file
8
src/fsfw/cfdp/pdu/PduConfig.cpp
Normal 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) {
|
||||||
|
}
|
36
src/fsfw/cfdp/pdu/PduConfig.h
Normal file
36
src/fsfw/cfdp/pdu/PduConfig.h
Normal 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_ */
|
37
src/fsfw/cfdp/pdu/PduHeaderIF.h
Normal file
37
src/fsfw/cfdp/pdu/PduHeaderIF.h
Normal 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_ */
|
22
src/fsfw/cfdp/pdu/PromptPduDeserializer.cpp
Normal file
22
src/fsfw/cfdp/pdu/PromptPduDeserializer.cpp
Normal 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;
|
||||||
|
}
|
18
src/fsfw/cfdp/pdu/PromptPduDeserializer.h
Normal file
18
src/fsfw/cfdp/pdu/PromptPduDeserializer.h
Normal 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_ */
|
27
src/fsfw/cfdp/pdu/PromptPduSerializer.cpp
Normal file
27
src/fsfw/cfdp/pdu/PromptPduSerializer.cpp
Normal 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;
|
||||||
|
}
|
18
src/fsfw/cfdp/pdu/PromptPduSerializer.h
Normal file
18
src/fsfw/cfdp/pdu/PromptPduSerializer.h
Normal 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_ */
|
127
src/fsfw/cfdp/pdu/VarLenField.cpp
Normal file
127
src/fsfw/cfdp/pdu/VarLenField.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
src/fsfw/cfdp/pdu/VarLenField.h
Normal file
45
src/fsfw/cfdp/pdu/VarLenField.h
Normal 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_ */
|
10
src/fsfw/cfdp/tlv/CMakeLists.txt
Normal file
10
src/fsfw/cfdp/tlv/CMakeLists.txt
Normal 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
|
||||||
|
)
|
68
src/fsfw/cfdp/tlv/EntityIdTlv.cpp
Normal file
68
src/fsfw/cfdp/tlv/EntityIdTlv.cpp
Normal 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;
|
||||||
|
}
|
39
src/fsfw/cfdp/tlv/EntityIdTlv.h
Normal file
39
src/fsfw/cfdp/tlv/EntityIdTlv.h
Normal 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_ */
|
64
src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.cpp
Normal file
64
src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.cpp
Normal 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;
|
||||||
|
}
|
39
src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h
Normal file
39
src/fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h
Normal 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_ */
|
83
src/fsfw/cfdp/tlv/FilestoreRequestTlv.cpp
Normal file
83
src/fsfw/cfdp/tlv/FilestoreRequestTlv.cpp
Normal 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;
|
||||||
|
}
|
45
src/fsfw/cfdp/tlv/FilestoreRequestTlv.h
Normal file
45
src/fsfw/cfdp/tlv/FilestoreRequestTlv.h
Normal 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_ */
|
124
src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp
Normal file
124
src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp
Normal 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;
|
||||||
|
}
|
50
src/fsfw/cfdp/tlv/FilestoreResponseTlv.h
Normal file
50
src/fsfw/cfdp/tlv/FilestoreResponseTlv.h
Normal 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_ */
|
176
src/fsfw/cfdp/tlv/FilestoreTlvBase.h
Normal file
176
src/fsfw/cfdp/tlv/FilestoreTlvBase.h
Normal 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_ */
|
5
src/fsfw/cfdp/tlv/FlowLabelTlv.cpp
Normal file
5
src/fsfw/cfdp/tlv/FlowLabelTlv.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "FlowLabelTlv.h"
|
||||||
|
|
||||||
|
FlowLabelTlv::FlowLabelTlv(uint8_t* value, size_t size):
|
||||||
|
Tlv(cfdp::TlvTypes::FLOW_LABEL, value, size) {
|
||||||
|
}
|
13
src/fsfw/cfdp/tlv/FlowLabelTlv.h
Normal file
13
src/fsfw/cfdp/tlv/FlowLabelTlv.h
Normal 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
88
src/fsfw/cfdp/tlv/Lv.cpp
Normal 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
53
src/fsfw/cfdp/tlv/Lv.h
Normal 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_ */
|
8
src/fsfw/cfdp/tlv/MessageToUserTlv.cpp
Normal file
8
src/fsfw/cfdp/tlv/MessageToUserTlv.cpp
Normal 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() {
|
||||||
|
}
|
13
src/fsfw/cfdp/tlv/MessageToUserTlv.h
Normal file
13
src/fsfw/cfdp/tlv/MessageToUserTlv.h
Normal 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
114
src/fsfw/cfdp/tlv/Tlv.cpp
Normal 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
64
src/fsfw/cfdp/tlv/Tlv.h
Normal 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
16
src/fsfw/cfdp/tlv/TlvIF.h
Normal 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_ */
|
@ -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,
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user