CFDP FSFW Integration #111
26
CHANGELOG.md
26
CHANGELOG.md
@ -58,6 +58,32 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
||||
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
||||
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
||||
- Make functions `const` where it makes sense
|
||||
- Add `const char* getName const` abstract function
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
|
||||
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||
interface itself so it can be re-used more easily. Also add new
|
||||
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||
|
||||
## CFDP
|
||||
|
||||
- Refactoring of CFDP stack which was done during implementation of the CFDP source and destination
|
||||
handlers.
|
||||
- New filesystem module, changes for filesystem abstraction `HasFileSystemIF` to better
|
||||
fit requirements of CFDP
|
||||
- New `HostFilesystem` implementation of the `HasFileSystemIF`
|
||||
- New `cfdp::UserBase` class which is the abstraction for the CFDP user in an OBSW context.
|
||||
- mib module for the CFDP stack
|
||||
- PDU classes renamed from `...Serializer`/`...Deserializer` to `...Creator`/`...Reader`
|
||||
respetively
|
||||
- Renamed `TcDistributor` to `TcDistributorBase` to prevent confusion
|
||||
- Refactored `TcDisitributorBase` to be more flexible and usable for CFDP distribution
|
||||
- Renamed `CCSDSDistributor` to `CcsdsDistributor` and add feature which allows it
|
||||
to remove the CCSDS header when routing a packet. This allows CCSDS agnostic receiver
|
||||
implementation without an extra component
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
||||
|
||||
# [v5.0.0] 25.07.2022
|
||||
|
||||
|
@ -104,7 +104,8 @@ if(FSFW_GENERATE_SECTIONS)
|
||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||
endif()
|
||||
|
||||
option(FSFW_BUILD_TESTS "Build unittest binary in addition to static library"
|
||||
option(FSFW_BUILD_TESTS
|
||||
"Build unittest binary in addition to static library. Requires Catch2"
|
||||
OFF)
|
||||
option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF)
|
||||
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
||||
@ -115,7 +116,6 @@ endif()
|
||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||
# Options to exclude parts of the FSFW from compilation.
|
||||
option(FSFW_ADD_INTERNAL_TESTS "Add internal unit tests" ON)
|
||||
option(FSFW_ADD_UNITTESTS "Add regular unittests. Requires Catch2" OFF)
|
||||
option(FSFW_ADD_HAL "Add Hardware Abstraction Layer" ON)
|
||||
|
||||
if(UNIX)
|
||||
|
@ -4,6 +4,7 @@ API
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
api/cfdp
|
||||
api/objectmanager
|
||||
api/task
|
||||
api/ipc
|
||||
|
8
docs/api/cfdp.rst
Normal file
8
docs/api/cfdp.rst
Normal file
@ -0,0 +1,8 @@
|
||||
CFDP API
|
||||
=================
|
||||
|
||||
``UserBase``
|
||||
-----------------
|
||||
|
||||
.. doxygenclass:: cfdp::UserBase
|
||||
:members:
|
16
docs/conf.py
16
docs/conf.py
@ -17,12 +17,12 @@
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Flight Software Framework'
|
||||
copyright = '2021, Institute of Space Systems (IRS)'
|
||||
author = 'Institute of Space Systems (IRS)'
|
||||
project = "Flight Software Framework"
|
||||
copyright = "2021, Institute of Space Systems (IRS)"
|
||||
author = "Institute of Space Systems (IRS)"
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '2.0.1'
|
||||
release = "5.0.0"
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
@ -30,17 +30,17 @@ release = '2.0.1'
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [ "breathe" ]
|
||||
extensions = ["breathe"]
|
||||
|
||||
breathe_default_project = "fsfw"
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
@ -48,7 +48,7 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'alabaster'
|
||||
html_theme = "alabaster"
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
|
@ -7,12 +7,14 @@ Structure
|
||||
----------
|
||||
|
||||
The general structure is driven by the usage of interfaces provided by objects.
|
||||
The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be
|
||||
widely available, even with older compilers.
|
||||
The FSFW uses dynamic allocation during the initialization but provides static containers during runtime.
|
||||
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
||||
Dynamic Allocation after initialization is discouraged and different solutions are provided in the
|
||||
FSFW to achieve that. The fsfw uses run-time type information but exceptions are not allowed.
|
||||
The FSFW uses C++17 as baseline.
|
||||
It also uses dynamic allocation during the initialization but provides
|
||||
static containers during runtime.
|
||||
This simplifies the instantiation of objects and allows the usage of some
|
||||
standard containers.
|
||||
Dynamic Allocation after initialization is discouraged and different solutions
|
||||
are provided in the FSFW to achieve that. The fsfw uses run-time type
|
||||
information but will not throw exceptions.
|
||||
|
||||
Failure Handling
|
||||
-----------------
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <fsfw/events/EventManager.h>
|
||||
#include <fsfw/health/HealthTable.h>
|
||||
#include <fsfw/tmtcpacket/pus/tm/TmPacketStored.h>
|
||||
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||
#include <fsfw/tmtcservices/PusServiceBase.h>
|
||||
#include <fsfw/internalerror/InternalErrorReporter.h>
|
||||
@ -41,13 +40,9 @@ void Factory::setStaticFrameworkObjectIds() {
|
||||
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
|
||||
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
|
||||
|
||||
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
|
||||
|
||||
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||
DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS;
|
||||
|
||||
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
||||
|
||||
TmPacketBase::timeStamperId = objects::NO_OBJECT;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ file_selectors="-iname CMakeLists.txt"
|
||||
if command -v ${cmake_fmt} &> /dev/null; then
|
||||
${cmake_fmt} -i CMakeLists.txt
|
||||
find ./src ${file_selectors} | xargs ${cmake_fmt} -i
|
||||
find ./unittests ${file_selectors} | xargs ${cmake_fmt} -i
|
||||
else
|
||||
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
||||
fi
|
||||
|
@ -51,7 +51,7 @@ def main():
|
||||
parser.add_argument(
|
||||
"-g",
|
||||
"--generators",
|
||||
default = "Ninja",
|
||||
default="Ninja",
|
||||
action="store",
|
||||
help="CMake generators",
|
||||
)
|
||||
@ -165,10 +165,18 @@ def create_tests_build_cfg(args):
|
||||
os.mkdir(UNITTEST_FOLDER_NAME)
|
||||
os.chdir(UNITTEST_FOLDER_NAME)
|
||||
if args.windows:
|
||||
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \
|
||||
cmake_cmd = (
|
||||
'cmake -G "'
|
||||
+ args.generators
|
||||
+ '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \
|
||||
-DGCOVR_PATH="py -m gcovr" ..'
|
||||
)
|
||||
else:
|
||||
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..'
|
||||
cmake_cmd = (
|
||||
'cmake -G "'
|
||||
+ args.generators
|
||||
+ '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..'
|
||||
)
|
||||
cmd_runner(cmake_cmd)
|
||||
os.chdir("..")
|
||||
|
||||
|
@ -31,6 +31,7 @@ add_subdirectory(thermal)
|
||||
add_subdirectory(timemanager)
|
||||
add_subdirectory(tmtcpacket)
|
||||
add_subdirectory(tmtcservices)
|
||||
add_subdirectory(filesystem)
|
||||
|
||||
# Optional
|
||||
|
||||
|
13
src/fsfw/cfdp.h
Normal file
13
src/fsfw/cfdp.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef FSFW_CFDP_H
|
||||
#define FSFW_CFDP_H
|
||||
|
||||
#include "cfdp/definitions.h"
|
||||
#include "cfdp/handler/CfdpHandler.h"
|
||||
#include "cfdp/handler/DestHandler.h"
|
||||
#include "cfdp/handler/FaultHandlerBase.h"
|
||||
#include "cfdp/helpers.h"
|
||||
#include "cfdp/tlv/Lv.h"
|
||||
#include "cfdp/tlv/StringLv.h"
|
||||
#include "cfdp/tlv/Tlv.h"
|
||||
|
||||
#endif // FSFW_CFDP_H
|
@ -1,4 +1,6 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE CfdpHandler.cpp CfdpMessage.cpp)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE CfdpMessage.cpp CfdpDistributor.cpp
|
||||
VarLenFields.cpp helpers.cpp)
|
||||
|
||||
add_subdirectory(pdu)
|
||||
add_subdirectory(tlv)
|
||||
add_subdirectory(handler)
|
||||
|
55
src/fsfw/cfdp/CfdpDistributor.cpp
Normal file
55
src/fsfw/cfdp/CfdpDistributor.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "CfdpDistributor.h"
|
||||
|
||||
#include "fsfw/tcdistribution/definitions.h"
|
||||
|
||||
CfdpDistributor::CfdpDistributor(CfdpDistribCfg cfg)
|
||||
: TcDistributorBase(cfg.objectId, cfg.tcQueue), cfg(cfg) {}
|
||||
|
||||
ReturnValue_t CfdpDistributor::registerTcDestination(const cfdp::EntityId& address,
|
||||
AcceptsTelecommandsIF& tcDest) {
|
||||
for (const auto& dest : tcDestinations) {
|
||||
if (dest.id == address) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
tcDestinations.emplace_back(address, tcDest.getName(), tcDest.getRequestQueue());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CfdpDistributor::selectDestination(MessageQueueId_t& destId) {
|
||||
auto accessorPair = cfg.tcStore.getData(currentMessage.getStorageId());
|
||||
if (accessorPair.first != returnvalue::OK) {
|
||||
return accessorPair.first;
|
||||
}
|
||||
ReturnValue_t result =
|
||||
pduReader.setReadOnlyData(accessorPair.second.data(), accessorPair.second.size());
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = pduReader.parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
cfdp::EntityId foundId;
|
||||
pduReader.getDestId(foundId);
|
||||
bool destFound = false;
|
||||
for (const auto& dest : tcDestinations) {
|
||||
if (dest.id == foundId) {
|
||||
destId = dest.queueId;
|
||||
destFound = true;
|
||||
}
|
||||
}
|
||||
if (not destFound) {
|
||||
// TODO: Warning and event?
|
||||
return tmtcdistrib::NO_DESTINATION_FOUND;
|
||||
}
|
||||
// Packet was forwarded successfully, so do not delete it.
|
||||
accessorPair.second.release();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
const char* CfdpDistributor::getName() const { return "CFDP Distributor"; }
|
||||
|
||||
uint32_t CfdpDistributor::getIdentifier() const { return 0; }
|
||||
|
||||
MessageQueueId_t CfdpDistributor::getRequestQueue() const { return tcQueue->getId(); }
|
76
src/fsfw/cfdp/CfdpDistributor.h
Normal file
76
src/fsfw/cfdp/CfdpDistributor.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_
|
||||
#define FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tcdistribution/CfdpPacketChecker.h"
|
||||
#include "fsfw/tcdistribution/TcDistributorBase.h"
|
||||
#include "fsfw/tmtcpacket/cfdp/CfdpPacketStored.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "fsfw/tmtcservices/VerificationReporter.h"
|
||||
|
||||
struct CfdpDistribCfg {
|
||||
CfdpDistribCfg(object_id_t objectId, StorageManagerIF& tcStore, MessageQueueIF* tcQueue)
|
||||
: objectId(objectId), tcStore(tcStore), tcQueue(tcQueue) {}
|
||||
|
||||
object_id_t objectId;
|
||||
StorageManagerIF& tcStore;
|
||||
MessageQueueIF* tcQueue;
|
||||
};
|
||||
|
||||
/**
|
||||
* This will be the primary component to perform PDU forwading procedures. This includes forwarding
|
||||
* CFDP TC packets to registered source or destination handlers, and forwarding all telemetry
|
||||
* generated by them to registered TM sinks.
|
||||
* @ingroup tc_distribution
|
||||
*/
|
||||
class CfdpDistributor : public TcDistributorBase, public AcceptsTelecommandsIF {
|
||||
public:
|
||||
/**
|
||||
* The ctor passes @c set_apid to the checker class and calls the
|
||||
* TcDistribution ctor with a certain object id.
|
||||
* @param setApid The APID of this receiving Application.
|
||||
* @param setObjectId Object ID of the distributor itself
|
||||
* @param setPacketSource Object ID of the source of TC packets.
|
||||
* Must implement CcsdsDistributorIF.
|
||||
*/
|
||||
explicit CfdpDistributor(CfdpDistribCfg cfg);
|
||||
|
||||
[[nodiscard]] const char* getName() const override;
|
||||
[[nodiscard]] uint32_t getIdentifier() const override;
|
||||
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
|
||||
|
||||
/**
|
||||
* Register a new CFDP entity which can receive PDUs.
|
||||
* @param address
|
||||
* @param tcDest
|
||||
* @return
|
||||
* - @c RETURN_FAILED: Entry already exists for the given address
|
||||
*/
|
||||
ReturnValue_t registerTcDestination(const cfdp::EntityId& address, AcceptsTelecommandsIF& tcDest);
|
||||
|
||||
protected:
|
||||
struct EntityInfo {
|
||||
EntityInfo(cfdp::EntityId id, const char* name, MessageQueueId_t queueId)
|
||||
: id(std::move(id)), name(name), queueId(queueId) {}
|
||||
cfdp::EntityId id;
|
||||
const char* name;
|
||||
MessageQueueId_t queueId;
|
||||
};
|
||||
PduHeaderReader pduReader;
|
||||
ReturnValue_t lastTcError = returnvalue::OK;
|
||||
ReturnValue_t lastTmError = returnvalue::OK;
|
||||
// I don't think a regular OBSW will have more than 1 or 2 of these destinations, so I think
|
||||
// it is okay to accept the overhead here
|
||||
std::vector<EntityInfo> tcDestinations;
|
||||
CfdpDistribCfg cfg;
|
||||
|
||||
ReturnValue_t selectDestination(MessageQueueId_t& destId) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif /* FSFW_TCDISTRIBUTION_CFDPDISTRIBUTOR_H_ */
|
@ -1,58 +0,0 @@
|
||||
#include "fsfw/cfdp/CfdpHandler.h"
|
||||
|
||||
#include "fsfw/cfdp/CfdpMessage.h"
|
||||
#include "fsfw/ipc/CommandMessage.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/storagemanager/storeAddress.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||
|
||||
object_id_t CfdpHandler::packetSource = 0;
|
||||
object_id_t CfdpHandler::packetDestination = 0;
|
||||
|
||||
CfdpHandler::CfdpHandler(object_id_t setObjectId, CFDPDistributor* dist)
|
||||
: SystemObject(setObjectId) {
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
requestQueue = QueueFactory::instance()->createMessageQueue(
|
||||
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
distributor = dist;
|
||||
}
|
||||
|
||||
CfdpHandler::~CfdpHandler() = default;
|
||||
|
||||
ReturnValue_t CfdpHandler::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
this->distributor->registerHandler(this);
|
||||
return returnvalue::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 returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CfdpHandler::performOperation(uint8_t opCode) {
|
||||
ReturnValue_t status = returnvalue::OK;
|
||||
CommandMessage currentMessage;
|
||||
for (status = this->requestQueue->receiveMessage(¤tMessage); status == returnvalue::OK;
|
||||
status = this->requestQueue->receiveMessage(¤tMessage)) {
|
||||
store_address_t storeId = CfdpMessage::getStoreId(¤tMessage);
|
||||
this->handleRequest(storeId);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
uint16_t CfdpHandler::getIdentifier() { return 0; }
|
||||
|
||||
MessageQueueId_t CfdpHandler::getRequestQueue() { return this->requestQueue->getId(); }
|
@ -1,60 +0,0 @@
|
||||
#ifndef FSFW_CFDP_CFDPHANDLER_H_
|
||||
#define FSFW_CFDP_CFDPHANDLER_H_
|
||||
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tcdistribution/CFDPDistributor.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
|
||||
namespace Factory {
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
class CfdpHandler : public ExecutableObjectIF, public AcceptsTelecommandsIF, public SystemObject {
|
||||
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_ */
|
@ -1,5 +1,7 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_FILESIZE_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_FILESIZE_H_
|
||||
#ifndef FSFW_CFDP_FILESIZE_H_
|
||||
#define FSFW_CFDP_FILESIZE_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
@ -8,9 +10,11 @@ namespace cfdp {
|
||||
|
||||
struct FileSize : public SerializeIF {
|
||||
public:
|
||||
FileSize() : largeFile(false){};
|
||||
FileSize() = default;
|
||||
|
||||
FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
|
||||
explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
|
||||
|
||||
[[nodiscard]] uint64_t value() const { return fileSize; }
|
||||
|
||||
ReturnValue_t serialize(bool isLarge, uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) {
|
||||
@ -27,7 +31,7 @@ struct FileSize : public SerializeIF {
|
||||
return SerializeAdapter::serialize(&fileSize, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
size_t getSerializedSize() const override {
|
||||
[[nodiscard]] size_t getSerializedSize() const override {
|
||||
if (largeFile) {
|
||||
return 8;
|
||||
} else {
|
||||
@ -50,20 +54,22 @@ struct FileSize : public SerializeIF {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t setFileSize(uint64_t fileSize, bool largeFile) {
|
||||
ReturnValue_t setFileSize(uint64_t fileSize_, std::optional<bool> largeFile_) {
|
||||
if (largeFile_) {
|
||||
largeFile = largeFile_.value();
|
||||
}
|
||||
if (not largeFile and fileSize > UINT32_MAX) {
|
||||
// TODO: emit warning here
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
this->fileSize = fileSize;
|
||||
this->largeFile = largeFile;
|
||||
this->fileSize = fileSize_;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
bool isLargeFile() const { return largeFile; }
|
||||
uint64_t getSize(bool *largeFile = nullptr) const {
|
||||
if (largeFile != nullptr) {
|
||||
*largeFile = this->largeFile;
|
||||
[[nodiscard]] bool isLargeFile() const { return largeFile; }
|
||||
uint64_t getSize(bool *largeFile_ = nullptr) const {
|
||||
if (largeFile_ != nullptr) {
|
||||
*largeFile_ = this->largeFile;
|
||||
}
|
||||
return fileSize;
|
||||
}
|
||||
@ -75,4 +81,4 @@ struct FileSize : public SerializeIF {
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_CFDP_FILESIZE_H_ */
|
||||
#endif /* FSFW_CFDP_FILESIZE_H_ */
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "VarLenField.h"
|
||||
#include "VarLenFields.h"
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
@ -21,27 +20,27 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
|
||||
|
||||
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
|
||||
|
||||
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value) {
|
||||
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) {
|
||||
switch (widthInBytes) {
|
||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||
if (value > UINT8_MAX) {
|
||||
if (value_ > UINT8_MAX) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
this->value.oneByte = value;
|
||||
this->value.oneByte = value_;
|
||||
break;
|
||||
}
|
||||
case (cfdp::WidthInBytes::TWO_BYTES): {
|
||||
if (value > UINT16_MAX) {
|
||||
if (value_ > UINT16_MAX) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
this->value.twoBytes = value;
|
||||
this->value.twoBytes = value_;
|
||||
break;
|
||||
}
|
||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||
if (value > UINT32_MAX) {
|
||||
if (value_ > UINT32_MAX) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
this->value.fourBytes = value;
|
||||
this->value.fourBytes = value_;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -93,9 +92,9 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
|
||||
|
||||
size_t cfdp::VarLenField::getSerializedSize() const { return width; }
|
||||
|
||||
ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer,
|
||||
ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const uint8_t **buffer,
|
||||
size_t *size, Endianness streamEndianness) {
|
||||
this->width = width;
|
||||
this->width = width_;
|
||||
return deSerialize(buffer, size, streamEndianness);
|
||||
}
|
||||
|
||||
@ -118,3 +117,21 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cfdp::VarLenField::operator<(const cfdp::VarLenField &other) const {
|
||||
if (getWidth() < other.getWidth()) {
|
||||
return true;
|
||||
} else if (getWidth() == other.getWidth()) {
|
||||
return getValue() < other.getValue();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool cfdp::VarLenField::operator==(const cfdp::VarLenField &other) const {
|
||||
return getWidth() == other.getWidth() and getValue() == other.getValue();
|
||||
}
|
||||
|
||||
bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const {
|
||||
return not(*this == other);
|
||||
}
|
107
src/fsfw/cfdp/VarLenFields.h
Normal file
107
src/fsfw/cfdp/VarLenFields.h
Normal file
@ -0,0 +1,107 @@
|
||||
#ifndef FSFW_CFDP_PDU_VARLENFIELD_H_
|
||||
#define FSFW_CFDP_PDU_VARLENFIELD_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw/util/UnsignedByteField.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class VarLenField : public SerializeIF {
|
||||
public:
|
||||
union LengthFieldLen {
|
||||
uint8_t oneByte;
|
||||
uint16_t twoBytes;
|
||||
uint32_t fourBytes;
|
||||
uint64_t eightBytes;
|
||||
};
|
||||
|
||||
VarLenField();
|
||||
template <typename T>
|
||||
explicit VarLenField(UnsignedByteField<T> byteField);
|
||||
|
||||
VarLenField(cfdp::WidthInBytes width, size_t value);
|
||||
|
||||
bool operator==(const VarLenField &other) const;
|
||||
bool operator!=(const VarLenField &other) const;
|
||||
bool operator<(const VarLenField &other) const;
|
||||
|
||||
ReturnValue_t setValue(cfdp::WidthInBytes, size_t value);
|
||||
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t deSerialize(cfdp::WidthInBytes width, const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness);
|
||||
|
||||
[[nodiscard]] cfdp::WidthInBytes getWidth() const;
|
||||
[[nodiscard]] size_t getValue() const;
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) {
|
||||
os << "dec: " << id.getValue() << ", hex: " << std::hex << std::setw(id.getWidth())
|
||||
<< std::setfill('0') << id.getValue() << std::dec << std::setfill('0');
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
cfdp::WidthInBytes width;
|
||||
LengthFieldLen value{};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
|
||||
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
|
||||
static_assert((sizeof(T) % 2) == 0);
|
||||
setValue(width, byteField.getValue());
|
||||
}
|
||||
|
||||
struct EntityId : public VarLenField {
|
||||
public:
|
||||
EntityId() : VarLenField() {}
|
||||
template <typename T>
|
||||
explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
|
||||
EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {}
|
||||
};
|
||||
|
||||
struct TransactionSeqNum : public VarLenField {
|
||||
public:
|
||||
TransactionSeqNum() : VarLenField() {}
|
||||
template <typename T>
|
||||
explicit TransactionSeqNum(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
|
||||
TransactionSeqNum(cfdp::WidthInBytes width, size_t seqNum) : VarLenField(width, seqNum) {}
|
||||
};
|
||||
|
||||
struct TransactionId {
|
||||
TransactionId() = default;
|
||||
TransactionId(EntityId entityId, TransactionSeqNum seqNum)
|
||||
: entityId(std::move(entityId)), seqNum(std::move(seqNum)) {}
|
||||
|
||||
bool operator==(const TransactionId &other) const {
|
||||
return entityId == other.entityId and seqNum == other.seqNum;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
friend std::ostream &operator<<(std::ostream &os, const TransactionId &id) {
|
||||
os << "Source ID { " << id.entityId << " }, Sequence Number " << id.seqNum.getValue();
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
EntityId entityId;
|
||||
TransactionSeqNum seqNum;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_VARLENFIELD_H_ */
|
@ -11,12 +11,16 @@
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
static constexpr uint8_t VERSION_BITS = 0b00100000;
|
||||
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
|
||||
|
||||
// Second version of the protocol, only this one is supported here
|
||||
static constexpr uint8_t CFDP_VERSION_2 = 0b001;
|
||||
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
|
||||
|
||||
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP;
|
||||
|
||||
static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1);
|
||||
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELDS = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
||||
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
||||
static constexpr ReturnValue_t INVALID_PDU_DATAFIELD_LEN = returnvalue::makeCode(CFDP_CLASS_ID, 3);
|
||||
static constexpr ReturnValue_t INVALID_ACK_DIRECTIVE_FIELDS =
|
||||
returnvalue::makeCode(CFDP_CLASS_ID, 4);
|
||||
@ -26,13 +30,14 @@ static constexpr ReturnValue_t METADATA_CANT_PARSE_OPTIONS =
|
||||
returnvalue::makeCode(CFDP_CLASS_ID, 5);
|
||||
static constexpr ReturnValue_t NAK_CANT_PARSE_OPTIONS = returnvalue::makeCode(CFDP_CLASS_ID, 6);
|
||||
static constexpr ReturnValue_t FINISHED_CANT_PARSE_FS_RESPONSES =
|
||||
returnvalue::makeCode(CFDP_CLASS_ID, 6);
|
||||
returnvalue::makeCode(CFDP_CLASS_ID, 7);
|
||||
static constexpr ReturnValue_t FILESTORE_REQUIRES_SECOND_FILE =
|
||||
returnvalue::makeCode(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 =
|
||||
returnvalue::makeCode(CFDP_CLASS_ID, 9);
|
||||
static constexpr ReturnValue_t INVALID_PDU_FORMAT = returnvalue::makeCode(CFDP_CLASS_ID, 10);
|
||||
|
||||
//! Checksum types according to the SANA Checksum Types registry
|
||||
//! https://sanaregistry.org/r/checksum_identifiers/
|
||||
@ -45,17 +50,17 @@ enum ChecksumType {
|
||||
NULL_CHECKSUM = 15
|
||||
};
|
||||
|
||||
enum PduType : bool { FILE_DIRECTIVE = 0, FILE_DATA = 1 };
|
||||
enum PduType : uint8_t { FILE_DIRECTIVE = 0, FILE_DATA = 1 };
|
||||
|
||||
enum TransmissionModes : bool { ACKNOWLEDGED = 0, UNACKNOWLEDGED = 1 };
|
||||
enum TransmissionMode : uint8_t { ACKNOWLEDGED = 0, UNACKNOWLEDGED = 1 };
|
||||
|
||||
enum SegmentMetadataFlag : bool { NOT_PRESENT = 0, PRESENT = 1 };
|
||||
enum SegmentMetadataFlag : bool { NOT_PRESENT = false, PRESENT = true };
|
||||
|
||||
enum Direction : bool { TOWARDS_RECEIVER = 0, TOWARDS_SENDER = 1 };
|
||||
enum Direction : uint8_t { TOWARDS_RECEIVER = 0, TOWARDS_SENDER = 1 };
|
||||
|
||||
enum SegmentationControl : bool {
|
||||
NO_RECORD_BOUNDARIES_PRESERVATION = 0,
|
||||
RECORD_BOUNDARIES_PRESERVATION = 1
|
||||
NO_RECORD_BOUNDARIES_PRESERVATION = false,
|
||||
RECORD_BOUNDARIES_PRESERVATION = true
|
||||
};
|
||||
|
||||
enum WidthInBytes : uint8_t {
|
||||
@ -65,8 +70,9 @@ enum WidthInBytes : uint8_t {
|
||||
FOUR_BYTES = 4,
|
||||
};
|
||||
|
||||
enum FileDirectives : uint8_t {
|
||||
enum FileDirective : uint8_t {
|
||||
INVALID_DIRECTIVE = 0x0f,
|
||||
// The _DIRECTIVE suffix is mandatory here because of some nameclash!
|
||||
EOF_DIRECTIVE = 0x04,
|
||||
FINISH = 0x05,
|
||||
ACK = 0x06,
|
||||
@ -93,6 +99,14 @@ enum ConditionCode : uint8_t {
|
||||
CANCEL_REQUEST_RECEIVED = 0b1111
|
||||
};
|
||||
|
||||
enum FaultHandlerCode {
|
||||
RESERVED = 0b0000,
|
||||
NOTICE_OF_CANCELLATION = 0b0001,
|
||||
NOTICE_OF_SUSPENSION = 0b0010,
|
||||
IGNORE_ERROR = 0b0011,
|
||||
ABANDON_TRANSACTION = 0b0100
|
||||
};
|
||||
|
||||
enum AckTransactionStatus {
|
||||
UNDEFINED = 0b00,
|
||||
ACTIVE = 0b01,
|
||||
@ -100,18 +114,18 @@ enum AckTransactionStatus {
|
||||
UNRECOGNIZED = 0b11
|
||||
};
|
||||
|
||||
enum FinishedDeliveryCode { DATA_COMPLETE = 0, DATA_INCOMPLETE = 1 };
|
||||
enum FileDeliveryCode { DATA_COMPLETE = 0, DATA_INCOMPLETE = 1 };
|
||||
|
||||
enum FinishedFileStatus {
|
||||
enum FileDeliveryStatus {
|
||||
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 PromptResponseRequired : uint8_t { PROMPT_NAK = 0, PROMPT_KEEP_ALIVE = 1 };
|
||||
|
||||
enum TlvTypes : uint8_t {
|
||||
enum TlvType : uint8_t {
|
||||
FILESTORE_REQUEST = 0x00,
|
||||
FILESTORE_RESPONSE = 0x01,
|
||||
MSG_TO_USER = 0x02,
|
||||
|
2
src/fsfw/cfdp/handler/CMakeLists.txt
Normal file
2
src/fsfw/cfdp/handler/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
|
||||
FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp)
|
135
src/fsfw/cfdp/handler/CfdpHandler.cpp
Normal file
135
src/fsfw/cfdp/handler/CfdpHandler.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
#include "CfdpHandler.h"
|
||||
|
||||
#include "fsfw/cfdp/pdu/AckPduReader.h"
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
using namespace cfdp;
|
||||
|
||||
CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg)
|
||||
: SystemObject(fsfwParams.objectId),
|
||||
destHandler(
|
||||
DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, cfdpCfg.faultHandler),
|
||||
cfdpCfg.userHandler, cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList,
|
||||
cfdpCfg.lostSegmentsList),
|
||||
FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore,
|
||||
fsfwParams.tmStore)) {
|
||||
// TODO: Make queue params configurable, or better yet, expect it to be passed externally
|
||||
msgQueue = QueueFactory::instance()->createMessageQueue();
|
||||
destHandler.setMsgQueue(*msgQueue);
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; }
|
||||
|
||||
[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const {
|
||||
return destHandler.getDestHandlerParams().cfg.localId.getValue();
|
||||
}
|
||||
|
||||
[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue->getId(); }
|
||||
|
||||
ReturnValue_t CfdpHandler::initialize() {
|
||||
ReturnValue_t result = destHandler.initialize();
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
tcStore = destHandler.getTcStore();
|
||||
tmStore = destHandler.getTmStore();
|
||||
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) {
|
||||
// TODO: Receive TC packets and route them to source and dest handler, depending on which is
|
||||
// correct or more appropriate
|
||||
ReturnValue_t status;
|
||||
ReturnValue_t result = OK;
|
||||
TmTcMessage tmtcMsg;
|
||||
for (status = msgQueue->receiveMessage(&tmtcMsg); status == returnvalue::OK;
|
||||
status = msgQueue->receiveMessage(&tmtcMsg)) {
|
||||
result = handleCfdpPacket(tmtcMsg);
|
||||
if (result != OK) {
|
||||
status = result;
|
||||
}
|
||||
}
|
||||
auto& fsmRes = destHandler.performStateMachine();
|
||||
// TODO: Error handling?
|
||||
while (fsmRes.callStatus == CallStatus::CALL_AGAIN) {
|
||||
destHandler.performStateMachine();
|
||||
// TODO: Error handling?
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
|
||||
auto accessorPair = tcStore->getData(msg.getStorageId());
|
||||
if (accessorPair.first != OK) {
|
||||
return accessorPair.first;
|
||||
}
|
||||
PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size());
|
||||
ReturnValue_t result = reader.parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return INVALID_PDU_FORMAT;
|
||||
}
|
||||
// The CFDP distributor should have taken care of ensuring the destination ID is correct
|
||||
PduType type = reader.getPduType();
|
||||
// Only the destination handler can process these PDUs
|
||||
if (type == PduType::FILE_DATA) {
|
||||
// Disable auto-deletion of packet
|
||||
accessorPair.second.release();
|
||||
PacketInfo info(type, msg.getStorageId());
|
||||
result = destHandler.passPacket(info);
|
||||
} else {
|
||||
// Route depending on PDU type and directive type if applicable. It retrieves directive type
|
||||
// from the raw stream for better performance (with sanity and directive code check).
|
||||
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
|
||||
// procedure.
|
||||
|
||||
// PDU header only. Invalid supplied data. A directive packet should have a valid data field
|
||||
// with at least one byte being the directive code
|
||||
const uint8_t* pduDataField = reader.getPduDataField();
|
||||
if (pduDataField == nullptr) {
|
||||
return INVALID_PDU_FORMAT;
|
||||
}
|
||||
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
|
||||
return INVALID_DIRECTIVE_FIELD;
|
||||
}
|
||||
auto directive = static_cast<FileDirective>(pduDataField[0]);
|
||||
|
||||
auto passToDestHandler = [&]() {
|
||||
accessorPair.second.release();
|
||||
PacketInfo info(type, msg.getStorageId(), directive);
|
||||
result = destHandler.passPacket(info);
|
||||
};
|
||||
auto passToSourceHandler = [&]() {
|
||||
|
||||
};
|
||||
if (directive == FileDirective::METADATA or directive == FileDirective::EOF_DIRECTIVE or
|
||||
directive == FileDirective::PROMPT) {
|
||||
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
|
||||
// the destination handler
|
||||
passToDestHandler();
|
||||
} else if (directive == FileDirective::FINISH or directive == FileDirective::NAK or
|
||||
directive == FileDirective::KEEP_ALIVE) {
|
||||
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
|
||||
// the source handler
|
||||
passToSourceHandler();
|
||||
} else if (directive == FileDirective::ACK) {
|
||||
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
|
||||
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
|
||||
// the source handler, for a Finished PDU, it is passed to the destination handler.
|
||||
FileDirective ackedDirective;
|
||||
if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) {
|
||||
return INVALID_ACK_DIRECTIVE_FIELDS;
|
||||
}
|
||||
if (ackedDirective == FileDirective::EOF_DIRECTIVE) {
|
||||
passToSourceHandler();
|
||||
} else if (ackedDirective == FileDirective::FINISH) {
|
||||
passToDestHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
65
src/fsfw/cfdp/handler/CfdpHandler.h
Normal file
65
src/fsfw/cfdp/handler/CfdpHandler.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
|
||||
#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "fsfw/cfdp/handler/DestHandler.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
struct FsfwHandlerParams {
|
||||
FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest,
|
||||
StorageManagerIF& tcStore, StorageManagerIF& tmStore)
|
||||
: objectId(objectId), vfs(vfs), packetDest(packetDest), tcStore(tcStore), tmStore(tmStore) {}
|
||||
object_id_t objectId{};
|
||||
HasFileSystemIF& vfs;
|
||||
AcceptsTelemetryIF& packetDest;
|
||||
StorageManagerIF& tcStore;
|
||||
StorageManagerIF& tmStore;
|
||||
};
|
||||
|
||||
struct CfdpHandlerCfg {
|
||||
CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg,
|
||||
cfdp::UserBase& userHandler, cfdp::FaultHandlerBase& userFaultHandler,
|
||||
cfdp::PacketInfoListBase& packetInfo, cfdp::LostSegmentsListBase& lostSegmentsList,
|
||||
cfdp::RemoteConfigTableIF& remoteCfgProvider)
|
||||
: id(std::move(localId)),
|
||||
indicCfg(indicationCfg),
|
||||
packetInfoList(packetInfo),
|
||||
lostSegmentsList(lostSegmentsList),
|
||||
remoteCfgProvider(remoteCfgProvider),
|
||||
userHandler(userHandler),
|
||||
faultHandler(userFaultHandler) {}
|
||||
|
||||
cfdp::EntityId id;
|
||||
cfdp::IndicationCfg indicCfg;
|
||||
cfdp::PacketInfoListBase& packetInfoList;
|
||||
cfdp::LostSegmentsListBase& lostSegmentsList;
|
||||
cfdp::RemoteConfigTableIF& remoteCfgProvider;
|
||||
cfdp::UserBase& userHandler;
|
||||
cfdp::FaultHandlerBase& faultHandler;
|
||||
};
|
||||
|
||||
class CfdpHandler : public SystemObject, public ExecutableObjectIF, public AcceptsTelecommandsIF {
|
||||
public:
|
||||
explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg);
|
||||
|
||||
[[nodiscard]] const char* getName() const override;
|
||||
[[nodiscard]] uint32_t getIdentifier() const override;
|
||||
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
|
||||
private:
|
||||
MessageQueueIF* msgQueue = nullptr;
|
||||
cfdp::DestHandler destHandler;
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
StorageManagerIF* tmStore = nullptr;
|
||||
|
||||
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
|
||||
};
|
||||
|
||||
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
|
480
src/fsfw/cfdp/handler/DestHandler.cpp
Normal file
480
src/fsfw/cfdp/handler/DestHandler.cpp
Normal file
@ -0,0 +1,480 @@
|
||||
#include "DestHandler.h"
|
||||
|
||||
#include <etl/crc32.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/cfdp/pdu/EofPduReader.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataReader.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
#include "fsfw/objectmanager.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
cfdp::DestHandler::DestHandler(DestHandlerParams params, FsfwParams fsfwParams)
|
||||
: tlvVec(params.maxTlvsInOnePdu),
|
||||
userTlvVec(params.maxTlvsInOnePdu),
|
||||
dp(std::move(params)),
|
||||
fp(fsfwParams),
|
||||
tp(params.maxFilenameLen) {
|
||||
tp.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
|
||||
}
|
||||
|
||||
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::performStateMachine() {
|
||||
ReturnValue_t result;
|
||||
uint8_t errorIdx = 0;
|
||||
fsmRes.resetOfIteration();
|
||||
if (fsmRes.step == TransactionStep::IDLE) {
|
||||
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
|
||||
if (infoIter->pduType == PduType::FILE_DIRECTIVE and
|
||||
infoIter->directiveType == FileDirective::METADATA) {
|
||||
result = handleMetadataPdu(*infoIter);
|
||||
checkAndHandleError(result, errorIdx);
|
||||
// Store data was deleted in PDU handler because a store guard is used
|
||||
dp.packetListRef.erase(infoIter++);
|
||||
} else {
|
||||
infoIter++;
|
||||
}
|
||||
}
|
||||
if (fsmRes.step == TransactionStep::IDLE) {
|
||||
// To decrease the already high complexity of the software, all packets arriving before
|
||||
// a metadata PDU are deleted.
|
||||
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
|
||||
fp.tcStore->deleteData(infoIter->storeId);
|
||||
infoIter++;
|
||||
}
|
||||
dp.packetListRef.clear();
|
||||
}
|
||||
|
||||
if (fsmRes.step != TransactionStep::IDLE) {
|
||||
fsmRes.callStatus = CallStatus::CALL_AGAIN;
|
||||
}
|
||||
return updateFsmRes(errorIdx);
|
||||
}
|
||||
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
|
||||
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
|
||||
for (auto infoIter = dp.packetListRef.begin(); infoIter != dp.packetListRef.end();) {
|
||||
if (infoIter->pduType == PduType::FILE_DATA) {
|
||||
result = handleFileDataPdu(*infoIter);
|
||||
checkAndHandleError(result, errorIdx);
|
||||
// Store data was deleted in PDU handler because a store guard is used
|
||||
dp.packetListRef.erase(infoIter++);
|
||||
} else if (infoIter->pduType == PduType::FILE_DIRECTIVE and
|
||||
infoIter->directiveType == FileDirective::EOF_DIRECTIVE) {
|
||||
// TODO: Support for check timer missing
|
||||
result = handleEofPdu(*infoIter);
|
||||
checkAndHandleError(result, errorIdx);
|
||||
// Store data was deleted in PDU handler because a store guard is used
|
||||
dp.packetListRef.erase(infoIter++);
|
||||
} else {
|
||||
infoIter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fsmRes.step == TransactionStep::TRANSFER_COMPLETION) {
|
||||
result = handleTransferCompletion();
|
||||
checkAndHandleError(result, errorIdx);
|
||||
}
|
||||
if (fsmRes.step == TransactionStep::SENDING_FINISHED_PDU) {
|
||||
result = sendFinishedPdu();
|
||||
checkAndHandleError(result, errorIdx);
|
||||
finish();
|
||||
}
|
||||
return updateFsmRes(errorIdx);
|
||||
}
|
||||
if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
|
||||
// TODO: Will be implemented at a later stage
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "CFDP state machine for acknowledged mode not implemented yet" << std::endl;
|
||||
#endif
|
||||
}
|
||||
return updateFsmRes(errorIdx);
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::passPacket(PacketInfo packet) {
|
||||
if (dp.packetListRef.full()) {
|
||||
return FAILED;
|
||||
}
|
||||
dp.packetListRef.push_back(packet);
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::initialize() {
|
||||
if (fp.tmStore == nullptr) {
|
||||
fp.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
||||
if (fp.tmStore == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp.tcStore == nullptr) {
|
||||
fp.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
||||
if (fp.tcStore == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp.msgQueue == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
|
||||
// Process metadata PDU
|
||||
auto constAccessorPair = fp.tcStore->getData(info.storeId);
|
||||
if (constAccessorPair.first != OK) {
|
||||
// TODO: This is not a CFDP error. Event and/or warning?
|
||||
return constAccessorPair.first;
|
||||
}
|
||||
cfdp::StringLv sourceFileName;
|
||||
cfdp::StringLv destFileName;
|
||||
MetadataInfo metadataInfo(tp.fileSize, sourceFileName, destFileName);
|
||||
cfdp::Tlv* tlvArrayAsPtr = tlvVec.data();
|
||||
metadataInfo.setOptionsArray(&tlvArrayAsPtr, std::nullopt, tlvVec.size());
|
||||
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
|
||||
metadataInfo);
|
||||
ReturnValue_t result = reader.parseData();
|
||||
// TODO: The standard does not really specify what happens if this kind of error happens
|
||||
// I think it might be a good idea to cache some sort of error code, which
|
||||
// is translated into a warning and/or event by an upper layer
|
||||
if (result != OK) {
|
||||
return handleMetadataParseError(result, constAccessorPair.second.data(),
|
||||
constAccessorPair.second.size());
|
||||
}
|
||||
return startTransaction(reader, metadataInfo);
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
|
||||
// Process file data PDU
|
||||
auto constAccessorPair = fp.tcStore->getData(info.storeId);
|
||||
if (constAccessorPair.first != OK) {
|
||||
// TODO: This is not a CFDP error. Event and/or warning?
|
||||
return constAccessorPair.first;
|
||||
}
|
||||
cfdp::FileSize offset;
|
||||
FileDataInfo fdInfo(offset);
|
||||
FileDataReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), fdInfo);
|
||||
ReturnValue_t result = reader.parseData();
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
size_t fileSegmentLen = 0;
|
||||
const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen);
|
||||
FileOpParams fileOpParams(tp.destName.data(), fileSegmentLen);
|
||||
fileOpParams.offset = offset.value();
|
||||
if (dp.cfg.indicCfg.fileSegmentRecvIndicRequired) {
|
||||
FileSegmentRecvdParams segParams;
|
||||
segParams.offset = offset.value();
|
||||
segParams.id = tp.transactionId;
|
||||
segParams.length = fileSegmentLen;
|
||||
segParams.recContState = fdInfo.getRecordContinuationState();
|
||||
size_t segmentMetadatLen = 0;
|
||||
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
|
||||
segParams.segmentMetadata = {segMetadata, segmentMetadatLen};
|
||||
dp.user.fileSegmentRecvdIndication(segParams);
|
||||
}
|
||||
result = dp.user.vfs.writeToFile(fileOpParams, fileData);
|
||||
if (offset.value() + fileSegmentLen > tp.progress) {
|
||||
tp.progress = offset.value() + fileSegmentLen;
|
||||
}
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: Proper Error handling
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "File write error" << std::endl;
|
||||
#endif
|
||||
} else {
|
||||
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
|
||||
// Process EOF PDU
|
||||
auto constAccessorPair = fp.tcStore->getData(info.storeId);
|
||||
if (constAccessorPair.first != OK) {
|
||||
// TODO: This is not a CFDP error. Event and/or warning?
|
||||
return constAccessorPair.first;
|
||||
}
|
||||
EofInfo eofInfo(nullptr);
|
||||
EofPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(), eofInfo);
|
||||
ReturnValue_t result = reader.parseData();
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
// TODO: Error handling
|
||||
if (eofInfo.getConditionCode() == ConditionCode::NO_ERROR) {
|
||||
tp.crc = eofInfo.getChecksum();
|
||||
uint64_t fileSizeFromEof = eofInfo.getFileSize().value();
|
||||
// CFDP 4.6.1.2.9: Declare file size error if progress exceeds file size
|
||||
if (fileSizeFromEof > tp.progress) {
|
||||
// TODO: File size error
|
||||
}
|
||||
tp.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
|
||||
}
|
||||
if (dp.cfg.indicCfg.eofRecvIndicRequired) {
|
||||
dp.user.eofRecvIndication(getTransactionId());
|
||||
}
|
||||
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
|
||||
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
|
||||
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
|
||||
} else if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
|
||||
fsmRes.step = TransactionStep::SENDING_ACK_PDU;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
|
||||
const uint8_t* rawData, size_t maxSize) {
|
||||
// TODO: try to extract destination ID for error
|
||||
// TODO: Invalid metadata PDU.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Parsing Metadata PDU failed with code " << result << std::endl;
|
||||
#else
|
||||
#endif
|
||||
PduHeaderReader headerReader(rawData, maxSize);
|
||||
result = headerReader.parseData();
|
||||
if (result != OK) {
|
||||
// TODO: Now this really should not happen. Warning or error,
|
||||
// yield or cache appropriate returnvalue
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Parsing Header failed" << std::endl;
|
||||
#else
|
||||
#endif
|
||||
// TODO: Trigger appropriate event
|
||||
return result;
|
||||
}
|
||||
cfdp::EntityId destId;
|
||||
headerReader.getDestId(destId);
|
||||
RemoteEntityCfg* remoteCfg;
|
||||
if (not dp.remoteCfgTable.getRemoteCfg(destId, &remoteCfg)) {
|
||||
// TODO: No remote config for dest ID. I consider this a configuration error, which is not
|
||||
// covered by the standard.
|
||||
// Warning or error, yield or cache appropriate returnvalue
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "No remote config exists for destination ID" << std::endl;
|
||||
#else
|
||||
#endif
|
||||
// TODO: Trigger appropriate event
|
||||
}
|
||||
// TODO: Appropriate returnvalue?
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, MetadataInfo& info) {
|
||||
if (fsmRes.state != CfdpStates::IDLE) {
|
||||
// According to standard, discard metadata PDU if we are busy
|
||||
return OK;
|
||||
}
|
||||
ReturnValue_t result = OK;
|
||||
fsmRes.step = TransactionStep::TRANSACTION_START;
|
||||
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
|
||||
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
|
||||
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
|
||||
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
|
||||
}
|
||||
tp.checksumType = info.getChecksumType();
|
||||
tp.closureRequested = info.isClosureRequested();
|
||||
size_t sourceNameSize = 0;
|
||||
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
|
||||
if (sourceNameSize > tp.sourceName.size()) {
|
||||
// TODO: Warning, event etc.
|
||||
return FAILED;
|
||||
}
|
||||
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
|
||||
tp.sourceName[sourceNameSize] = '\0';
|
||||
size_t destNameSize = 0;
|
||||
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
|
||||
if (destNameSize > tp.destName.size()) {
|
||||
// TODO: Warning, event etc.
|
||||
return FAILED;
|
||||
}
|
||||
std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
|
||||
tp.destName[destNameSize] = '\0';
|
||||
reader.fillConfig(tp.pduConf);
|
||||
tp.pduConf.direction = Direction::TOWARDS_SENDER;
|
||||
tp.transactionId.entityId = tp.pduConf.sourceId;
|
||||
tp.transactionId.seqNum = tp.pduConf.seqNum;
|
||||
if (not dp.remoteCfgTable.getRemoteCfg(tp.pduConf.sourceId, &tp.remoteCfg)) {
|
||||
// TODO: Warning, event etc.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "cfdp::DestHandler" << __func__
|
||||
<< ": No remote configuration found for destination ID "
|
||||
<< tp.pduConf.sourceId.getValue() << std::endl;
|
||||
#endif
|
||||
return FAILED;
|
||||
}
|
||||
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
|
||||
// so there is no need to create a file or truncate an existing file
|
||||
if (destNameSize > 0 and sourceNameSize > 0) {
|
||||
FilesystemParams fparams(tp.destName.data());
|
||||
// TODO: Filesystem errors?
|
||||
if (dp.user.vfs.fileExists(fparams)) {
|
||||
dp.user.vfs.truncateFile(fparams);
|
||||
} else {
|
||||
result = dp.user.vfs.createFile(fparams);
|
||||
if (result != OK) {
|
||||
// TODO: Handle FS error. This is probably a case for the filestore rejection mechanism of
|
||||
// CFDP.
|
||||
// In any case, it does not really make sense to continue here
|
||||
}
|
||||
}
|
||||
}
|
||||
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
|
||||
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
|
||||
params.fileSize = tp.fileSize.getSize();
|
||||
params.destFileName = tp.destName.data();
|
||||
params.sourceFileName = tp.sourceName.data();
|
||||
params.msgsToUserArray = dynamic_cast<MessageToUserTlv*>(userTlvVec.data());
|
||||
params.msgsToUserLen = info.getOptionsLen();
|
||||
dp.user.metadataRecvdIndication(params);
|
||||
return result;
|
||||
}
|
||||
|
||||
cfdp::CfdpStates cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
|
||||
ReturnValue_t result;
|
||||
if (tp.checksumType != ChecksumType::NULL_CHECKSUM) {
|
||||
result = checksumVerification();
|
||||
if (result != OK) {
|
||||
// TODO: Warning / error handling?
|
||||
}
|
||||
} else {
|
||||
tp.conditionCode = ConditionCode::NO_ERROR;
|
||||
}
|
||||
result = noticeOfCompletion();
|
||||
if (result != OK) {
|
||||
}
|
||||
if (fsmRes.state == CfdpStates::BUSY_CLASS_1_NACKED) {
|
||||
if (tp.closureRequested) {
|
||||
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
} else if (fsmRes.state == CfdpStates::BUSY_CLASS_2_ACKED) {
|
||||
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
void cfdp::DestHandler::finish() {
|
||||
tp.reset();
|
||||
dp.packetListRef.clear();
|
||||
fsmRes.state = CfdpStates::IDLE;
|
||||
fsmRes.step = TransactionStep::IDLE;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::checksumVerification() {
|
||||
std::array<uint8_t, 1024> buf{};
|
||||
// TODO: Checksum verification and notice of completion
|
||||
etl::crc32 crcCalc;
|
||||
uint64_t currentOffset = 0;
|
||||
FileOpParams params(tp.destName.data(), tp.fileSize.value());
|
||||
while (currentOffset < tp.fileSize.value()) {
|
||||
uint64_t readLen;
|
||||
if (currentOffset + buf.size() > tp.fileSize.value()) {
|
||||
readLen = tp.fileSize.value() - currentOffset;
|
||||
} else {
|
||||
readLen = buf.size();
|
||||
}
|
||||
if (readLen > 0) {
|
||||
params.offset = currentOffset;
|
||||
params.size = readLen;
|
||||
auto result = dp.user.vfs.readFromFile(params, buf.data(), buf.size());
|
||||
if (result != OK) {
|
||||
// TODO: I think this is a case for a filestore rejection, but it might sense to print
|
||||
// a warning or trigger an event because this should generally not happen
|
||||
return FAILED;
|
||||
}
|
||||
crcCalc.add(buf.begin(), buf.begin() + readLen);
|
||||
}
|
||||
currentOffset += readLen;
|
||||
}
|
||||
|
||||
uint32_t value = crcCalc.value();
|
||||
if (value == tp.crc) {
|
||||
tp.conditionCode = ConditionCode::NO_ERROR;
|
||||
tp.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
|
||||
} else {
|
||||
// TODO: Proper error handling
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "CRC check for file " << tp.destName.data() << " failed" << std::endl;
|
||||
#endif
|
||||
tp.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::noticeOfCompletion() {
|
||||
if (dp.cfg.indicCfg.transactionFinishedIndicRequired) {
|
||||
TransactionFinishedParams params(tp.transactionId, tp.conditionCode, tp.deliveryCode,
|
||||
tp.deliveryStatus);
|
||||
dp.user.transactionFinishedIndication(params);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
|
||||
FinishedInfo info(tp.conditionCode, tp.deliveryCode, tp.deliveryStatus);
|
||||
FinishPduCreator finishedPdu(tp.pduConf, info);
|
||||
store_address_t storeId;
|
||||
uint8_t* dataPtr = nullptr;
|
||||
ReturnValue_t result =
|
||||
fp.tcStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
|
||||
if (result != OK) {
|
||||
// TODO: Error handling and event, this is a non CFDP specific error (most likely store is full)
|
||||
return result;
|
||||
}
|
||||
size_t serLen = 0;
|
||||
result = finishedPdu.serialize(dataPtr, serLen, finishedPdu.getSerializedSize());
|
||||
if (result != OK) {
|
||||
// TODO: Error printout, this really should not happen
|
||||
return result;
|
||||
}
|
||||
TmTcMessage msg(storeId);
|
||||
result = fp.msgQueue->sendMessage(fp.packetDest.getReportReceptionQueue(), &msg);
|
||||
if (result != OK) {
|
||||
// TODO: Error handling and event, this is a non CFDP specific error (most likely store is full)
|
||||
return result;
|
||||
}
|
||||
fsmRes.packetsSent++;
|
||||
return OK;
|
||||
}
|
||||
|
||||
cfdp::DestHandler::TransactionStep cfdp::DestHandler::getTransactionStep() const {
|
||||
return fsmRes.step;
|
||||
}
|
||||
|
||||
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::updateFsmRes(uint8_t errors) {
|
||||
fsmRes.errors = errors;
|
||||
fsmRes.result = OK;
|
||||
if (fsmRes.errors > 0) {
|
||||
fsmRes.result = FAILED;
|
||||
}
|
||||
return fsmRes;
|
||||
}
|
||||
|
||||
const cfdp::TransactionId& cfdp::DestHandler::getTransactionId() const { return tp.transactionId; }
|
||||
|
||||
void cfdp::DestHandler::checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx) {
|
||||
if (result != OK and errorIdx < 3) {
|
||||
fsmRes.errorCodes[errorIdx] = result;
|
||||
errorIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
void cfdp::DestHandler::setMsgQueue(MessageQueueIF& queue) { fp.msgQueue = &queue; }
|
||||
|
||||
void cfdp::DestHandler::setEventReporter(EventReportingProxyIF& reporter) {
|
||||
fp.eventReporter = &reporter;
|
||||
}
|
||||
|
||||
const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const { return dp; }
|
||||
|
||||
StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fp.tmStore; }
|
||||
StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fp.tcStore; }
|
202
src/fsfw/cfdp/handler/DestHandler.h
Normal file
202
src/fsfw/cfdp/handler/DestHandler.h
Normal file
@ -0,0 +1,202 @@
|
||||
#ifndef FSFW_CFDP_CFDPDESTHANDLER_H
|
||||
#define FSFW_CFDP_CFDPDESTHANDLER_H
|
||||
|
||||
#include <etl/list.h>
|
||||
#include <etl/set.h>
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "RemoteConfigTableIF.h"
|
||||
#include "UserBase.h"
|
||||
#include "defs.h"
|
||||
#include "fsfw/cfdp/handler/mib.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
|
||||
#include "fsfw/cfdp/pdu/PduConfig.h"
|
||||
#include "fsfw/container/DynamicFIFO.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
#include "fsfw/storagemanager/storeAddress.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
struct PacketInfo {
|
||||
PacketInfo(PduType type, store_address_t storeId,
|
||||
std::optional<FileDirective> directive = std::nullopt)
|
||||
: pduType(type), directiveType(directive), storeId(storeId) {}
|
||||
|
||||
PduType pduType = PduType::FILE_DATA;
|
||||
std::optional<FileDirective> directiveType = FileDirective::INVALID_DIRECTIVE;
|
||||
store_address_t storeId = store_address_t::invalid();
|
||||
PacketInfo() = default;
|
||||
};
|
||||
|
||||
template <size_t SIZE>
|
||||
using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>;
|
||||
template <size_t SIZE>
|
||||
using PacketInfoList = etl::list<PacketInfo, SIZE>;
|
||||
using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>;
|
||||
using PacketInfoListBase = etl::ilist<PacketInfo>;
|
||||
|
||||
struct DestHandlerParams {
|
||||
DestHandlerParams(LocalEntityCfg cfg, UserBase& user, RemoteConfigTableIF& remoteCfgTable,
|
||||
PacketInfoListBase& packetList,
|
||||
// TODO: This container can potentially take tons of space. For a better
|
||||
// memory efficient implementation, an additional abstraction could be
|
||||
// be used so users can use uint32_t as the pair type
|
||||
LostSegmentsListBase& lostSegmentsContainer)
|
||||
: cfg(std::move(cfg)),
|
||||
user(user),
|
||||
remoteCfgTable(remoteCfgTable),
|
||||
packetListRef(packetList),
|
||||
lostSegmentsContainer(lostSegmentsContainer) {}
|
||||
|
||||
LocalEntityCfg cfg;
|
||||
UserBase& user;
|
||||
RemoteConfigTableIF& remoteCfgTable;
|
||||
|
||||
PacketInfoListBase& packetListRef;
|
||||
LostSegmentsListBase& lostSegmentsContainer;
|
||||
uint8_t maxTlvsInOnePdu = 10;
|
||||
size_t maxFilenameLen = 255;
|
||||
};
|
||||
|
||||
struct FsfwParams {
|
||||
FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
|
||||
EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore,
|
||||
StorageManagerIF& tmStore)
|
||||
: FsfwParams(packetDest, msgQueue, eventReporter) {
|
||||
this->tcStore = &tcStore;
|
||||
this->tmStore = &tmStore;
|
||||
}
|
||||
|
||||
FsfwParams(AcceptsTelemetryIF& packetDest, MessageQueueIF* msgQueue,
|
||||
EventReportingProxyIF* eventReporter)
|
||||
: packetDest(packetDest), msgQueue(msgQueue), eventReporter(eventReporter) {}
|
||||
AcceptsTelemetryIF& packetDest;
|
||||
MessageQueueIF* msgQueue;
|
||||
EventReportingProxyIF* eventReporter = nullptr;
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
StorageManagerIF* tmStore = nullptr;
|
||||
};
|
||||
|
||||
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
|
||||
|
||||
class DestHandler {
|
||||
public:
|
||||
enum class TransactionStep {
|
||||
IDLE = 0,
|
||||
TRANSACTION_START = 1,
|
||||
RECEIVING_FILE_DATA_PDUS = 2,
|
||||
SENDING_ACK_PDU = 3,
|
||||
TRANSFER_COMPLETION = 4,
|
||||
SENDING_FINISHED_PDU = 5
|
||||
};
|
||||
|
||||
struct FsmResult {
|
||||
public:
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
|
||||
TransactionStep step = TransactionStep::IDLE;
|
||||
CfdpStates state = CfdpStates::IDLE;
|
||||
uint32_t packetsSent = 0;
|
||||
uint8_t errors = 0;
|
||||
std::array<ReturnValue_t, 3> errorCodes = {};
|
||||
void resetOfIteration() {
|
||||
result = returnvalue::OK;
|
||||
callStatus = CallStatus::CALL_AFTER_DELAY;
|
||||
packetsSent = 0;
|
||||
errors = 0;
|
||||
errorCodes.fill(returnvalue::OK);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Will be returned if it is advisable to call the state machine operation call again
|
||||
*/
|
||||
ReturnValue_t PARTIAL_SUCCESS = returnvalue::makeCode(0, 2);
|
||||
ReturnValue_t FAILURE = returnvalue::makeCode(0, 3);
|
||||
explicit DestHandler(DestHandlerParams handlerParams, FsfwParams fsfwParams);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
* - @c returnvalue::OK State machine OK for this execution cycle
|
||||
* - @c CALL_FSM_AGAIN State machine should be called again.
|
||||
*/
|
||||
const FsmResult& performStateMachine();
|
||||
void setMsgQueue(MessageQueueIF& queue);
|
||||
void setEventReporter(EventReportingProxyIF& reporter);
|
||||
|
||||
ReturnValue_t passPacket(PacketInfo packet);
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
[[nodiscard]] CfdpStates getCfdpState() const;
|
||||
[[nodiscard]] TransactionStep getTransactionStep() const;
|
||||
[[nodiscard]] const TransactionId& getTransactionId() const;
|
||||
[[nodiscard]] const DestHandlerParams& getDestHandlerParams() const;
|
||||
[[nodiscard]] StorageManagerIF* getTcStore() const;
|
||||
[[nodiscard]] StorageManagerIF* getTmStore() const;
|
||||
|
||||
private:
|
||||
struct TransactionParams {
|
||||
// Initialize char vectors with length + 1 for 0 termination
|
||||
explicit TransactionParams(size_t maxFileNameLen)
|
||||
: sourceName(maxFileNameLen + 1), destName(maxFileNameLen + 1) {}
|
||||
|
||||
void reset() {
|
||||
pduConf = PduConfig();
|
||||
transactionId = TransactionId();
|
||||
std::fill(sourceName.begin(), sourceName.end(), '\0');
|
||||
std::fill(destName.begin(), destName.end(), '\0');
|
||||
fileSize.setFileSize(0, false);
|
||||
conditionCode = ConditionCode::NO_ERROR;
|
||||
deliveryCode = FileDeliveryCode::DATA_INCOMPLETE;
|
||||
deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY;
|
||||
crc = 0;
|
||||
progress = 0;
|
||||
remoteCfg = nullptr;
|
||||
closureRequested = false;
|
||||
checksumType = ChecksumType::NULL_CHECKSUM;
|
||||
}
|
||||
|
||||
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
|
||||
bool closureRequested = false;
|
||||
std::vector<char> sourceName;
|
||||
std::vector<char> destName;
|
||||
cfdp::FileSize fileSize;
|
||||
TransactionId transactionId;
|
||||
PduConfig pduConf;
|
||||
ConditionCode conditionCode = ConditionCode::NO_ERROR;
|
||||
FileDeliveryCode deliveryCode = FileDeliveryCode::DATA_INCOMPLETE;
|
||||
FileDeliveryStatus deliveryStatus = FileDeliveryStatus::DISCARDED_DELIBERATELY;
|
||||
uint32_t crc = 0;
|
||||
uint64_t progress = 0;
|
||||
RemoteEntityCfg* remoteCfg = nullptr;
|
||||
};
|
||||
|
||||
std::vector<cfdp::Tlv> tlvVec;
|
||||
std::vector<cfdp::Tlv> userTlvVec;
|
||||
DestHandlerParams dp;
|
||||
FsfwParams fp;
|
||||
TransactionParams tp;
|
||||
FsmResult fsmRes;
|
||||
|
||||
ReturnValue_t startTransaction(MetadataPduReader& reader, MetadataInfo& info);
|
||||
ReturnValue_t handleMetadataPdu(const PacketInfo& info);
|
||||
ReturnValue_t handleFileDataPdu(const PacketInfo& info);
|
||||
ReturnValue_t handleEofPdu(const PacketInfo& info);
|
||||
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
|
||||
size_t maxSize);
|
||||
ReturnValue_t handleTransferCompletion();
|
||||
ReturnValue_t sendFinishedPdu();
|
||||
ReturnValue_t noticeOfCompletion();
|
||||
ReturnValue_t checksumVerification();
|
||||
const FsmResult& updateFsmRes(uint8_t errors);
|
||||
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
|
||||
void finish();
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_CFDPDESTHANDLER_H
|
51
src/fsfw/cfdp/handler/FaultHandlerBase.cpp
Normal file
51
src/fsfw/cfdp/handler/FaultHandlerBase.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "FaultHandlerBase.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
FaultHandlerBase::FaultHandlerBase() = default;
|
||||
FaultHandlerBase::~FaultHandlerBase() = default;
|
||||
|
||||
bool FaultHandlerBase::getFaultHandler(cfdp::ConditionCode code,
|
||||
cfdp::FaultHandlerCode& handler) const {
|
||||
auto iter = faultHandlerMap.find(code);
|
||||
if (iter == faultHandlerMap.end()) {
|
||||
return false;
|
||||
}
|
||||
handler = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FaultHandlerBase::setFaultHandler(cfdp::ConditionCode code, cfdp::FaultHandlerCode handler) {
|
||||
if (not faultHandlerMap.contains(code)) {
|
||||
return false;
|
||||
}
|
||||
if (handler != FaultHandlerCode::NOTICE_OF_SUSPENSION and
|
||||
handler != FaultHandlerCode::ABANDON_TRANSACTION and
|
||||
handler != FaultHandlerCode::NOTICE_OF_CANCELLATION and
|
||||
handler != FaultHandlerCode::IGNORE_ERROR) {
|
||||
return false;
|
||||
}
|
||||
faultHandlerMap[code] = handler;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FaultHandlerBase::reportFault(cfdp::TransactionId& id, cfdp::ConditionCode code) {
|
||||
if (not faultHandlerMap.contains(code)) {
|
||||
return false;
|
||||
}
|
||||
cfdp::FaultHandlerCode fh = faultHandlerMap[code];
|
||||
if (fh == cfdp::FaultHandlerCode::IGNORE_ERROR) {
|
||||
ignoreCb(id, code);
|
||||
} else if (fh == cfdp::FaultHandlerCode::ABANDON_TRANSACTION) {
|
||||
abandonCb(id, code);
|
||||
} else if (fh == cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION) {
|
||||
noticeOfCancellationCb(id, code);
|
||||
} else if (fh == cfdp::FaultHandlerCode::NOTICE_OF_SUSPENSION) {
|
||||
noticeOfSuspensionCb(id, code);
|
||||
} else {
|
||||
// Should never happen, but use defensive programming
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace cfdp
|
77
src/fsfw/cfdp/handler/FaultHandlerBase.h
Normal file
77
src/fsfw/cfdp/handler/FaultHandlerBase.h
Normal file
@ -0,0 +1,77 @@
|
||||
#ifndef FSFW_CFDP_FAULTHANDLERBASE_H
|
||||
#define FSFW_CFDP_FAULTHANDLERBASE_H
|
||||
|
||||
#include <etl/flat_map.h>
|
||||
|
||||
#include "fsfw/cfdp/VarLenFields.h"
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
/**
|
||||
* @brief Provides a way to implement the fault handling procedures as specified
|
||||
* in chapter 4.8 of the CFDP standard.
|
||||
*
|
||||
* @details
|
||||
* It is passed into the CFDP handlers as part of the local entity configuration and provides
|
||||
* a way to specify custom user error handlers.
|
||||
*
|
||||
* It does so by mapping each applicable CFDP condition code to a fault handler which
|
||||
* is denoted by the four @cfdp::FaultHandlerCodes. This code is used to dispatch
|
||||
* to a user-provided callback function:
|
||||
*
|
||||
* 1. @FaultHandlerCodes::IGNORE_ERROR -> @ignore_cb
|
||||
* 2. @FaultHandlerCodes::NOTICE_OF_CANCELLATION` -> @notice_of_cancellation_cb
|
||||
* 3. @FaultHandlerCodes::NOTICE_OF_SUSPENSION` -> @notice_of_suspension_cb
|
||||
* 4. @FaultHandlerCodes::ABANDON_TRANSACTION` -> @abandon_transaction_cb
|
||||
*
|
||||
* For each error reported by @reportError, the appropriate fault handler callback
|
||||
* will be called. The user provides the callbacks by providing a custom class which implements
|
||||
* these base class and all abstract fault handler callbacks.
|
||||
*/
|
||||
class FaultHandlerBase {
|
||||
public:
|
||||
virtual ~FaultHandlerBase();
|
||||
FaultHandlerBase();
|
||||
|
||||
/**
|
||||
* Get the fault handler code for the given condition code
|
||||
* @param code
|
||||
* @param handler [out] Will be set to the approrpiate handler for the condition code if
|
||||
* it is valid
|
||||
* @return
|
||||
* - true if the condition code is valid
|
||||
* - false otherwise
|
||||
*/
|
||||
bool getFaultHandler(cfdp::ConditionCode code, cfdp::FaultHandlerCode& handler) const;
|
||||
|
||||
bool setFaultHandler(cfdp::ConditionCode code, cfdp::FaultHandlerCode handler);
|
||||
|
||||
bool reportFault(cfdp::TransactionId& id, cfdp::ConditionCode code);
|
||||
|
||||
virtual void noticeOfSuspensionCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0;
|
||||
virtual void noticeOfCancellationCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0;
|
||||
virtual void abandonCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0;
|
||||
virtual void ignoreCb(cfdp::TransactionId& id, cfdp::ConditionCode code) = 0;
|
||||
|
||||
private:
|
||||
etl::flat_map<cfdp::ConditionCode, cfdp::FaultHandlerCode, 10> faultHandlerMap = {
|
||||
etl::pair{cfdp::ConditionCode::POSITIVE_ACK_LIMIT_REACHED,
|
||||
cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::KEEP_ALIVE_LIMIT_REACHED,
|
||||
cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::INVALID_TRANSMISSION_MODE,
|
||||
cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::FILE_CHECKSUM_FAILURE, cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::FILE_SIZE_ERROR, cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::NAK_LIMIT_REACHED, cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::INACTIVITY_DETECTED, cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::UNSUPPORTED_CHECKSUM_TYPE,
|
||||
cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::FILESTORE_REJECTION, cfdp::FaultHandlerCode::IGNORE_ERROR},
|
||||
etl::pair{cfdp::ConditionCode::CHECK_LIMIT_REACHED, cfdp::FaultHandlerCode::IGNORE_ERROR}};
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_FAULTHANDLERBASE_H
|
35
src/fsfw/cfdp/handler/RemoteConfigTableIF.h
Normal file
35
src/fsfw/cfdp/handler/RemoteConfigTableIF.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef FSFW_CFDP_HANDLER_REMOTECONFIGTABLEIF_H
|
||||
#define FSFW_CFDP_HANDLER_REMOTECONFIGTABLEIF_H
|
||||
|
||||
#include "fsfw/cfdp/handler/mib.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class RemoteConfigTableIF {
|
||||
public:
|
||||
virtual ~RemoteConfigTableIF() = default;
|
||||
virtual bool getRemoteCfg(const cfdp::EntityId& remoteId, cfdp::RemoteEntityCfg** cfg) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for the common case that there is exactly one remote entity
|
||||
*/
|
||||
class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
||||
public:
|
||||
explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
|
||||
|
||||
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
|
||||
if (remoteId != cfg.remoteId) {
|
||||
return false;
|
||||
}
|
||||
*cfg_ = &cfg;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
RemoteEntityCfg cfg;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_HANDLER_REMOTECONFIGTABLEIF_H
|
1
src/fsfw/cfdp/handler/SourceHandler.cpp
Normal file
1
src/fsfw/cfdp/handler/SourceHandler.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "SourceHandler.h"
|
6
src/fsfw/cfdp/handler/SourceHandler.h
Normal file
6
src/fsfw/cfdp/handler/SourceHandler.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
|
||||
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
|
||||
|
||||
class SourceHandler {};
|
||||
|
||||
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H
|
12
src/fsfw/cfdp/handler/StatusReportIF.h
Normal file
12
src/fsfw/cfdp/handler/StatusReportIF.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef FSFW_CFDP_HANDLER_STATUSREPORTIF_H
|
||||
#define FSFW_CFDP_HANDLER_STATUSREPORTIF_H
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class StatusReportIF {
|
||||
virtual ~StatusReportIF() = default;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_HANDLER_STATUSREPORTIF_H
|
3
src/fsfw/cfdp/handler/UserBase.cpp
Normal file
3
src/fsfw/cfdp/handler/UserBase.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "UserBase.h"
|
||||
|
||||
cfdp::UserBase::UserBase(HasFileSystemIF& vfs) : vfs(vfs) {}
|
101
src/fsfw/cfdp/handler/UserBase.h
Normal file
101
src/fsfw/cfdp/handler/UserBase.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef FSFW_CFDP_USERBASE_H
|
||||
#define FSFW_CFDP_USERBASE_H
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "StatusReportIF.h"
|
||||
#include "fsfw/cfdp/VarLenFields.h"
|
||||
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
|
||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
||||
#include "fsfw/filesystem/HasFileSystemIF.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
struct TransactionFinishedParams {
|
||||
TransactionFinishedParams(const TransactionId& id, ConditionCode code, FileDeliveryCode delivCode,
|
||||
FileDeliveryStatus status)
|
||||
: id(id), condCode(code), status(status), deliveryCode(delivCode) {}
|
||||
|
||||
const TransactionId& id;
|
||||
ConditionCode condCode;
|
||||
FileDeliveryStatus status;
|
||||
FileDeliveryCode deliveryCode;
|
||||
std::vector<FilestoreResponseTlv*> fsResponses;
|
||||
StatusReportIF* statusReport = nullptr;
|
||||
};
|
||||
|
||||
struct MetadataRecvdParams {
|
||||
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId)
|
||||
: id(id), sourceId(sourceId) {}
|
||||
const TransactionId& id;
|
||||
const EntityId& sourceId;
|
||||
uint64_t fileSize = 0;
|
||||
const char* sourceFileName = "";
|
||||
const char* destFileName = "";
|
||||
size_t msgsToUserLen = 0;
|
||||
const MessageToUserTlv* msgsToUserArray = nullptr;
|
||||
};
|
||||
|
||||
struct FileSegmentRecvdParams {
|
||||
TransactionId id;
|
||||
size_t offset;
|
||||
size_t length;
|
||||
std::optional<RecordContinuationState> recContState = std::nullopt;
|
||||
std::pair<const uint8_t*, size_t> segmentMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base class which provides a user interface to interact with CFDP handlers.
|
||||
*
|
||||
* @details
|
||||
* This class is also used to pass the Virtual Filestore (VFS) Implementation to the CFDP
|
||||
* handlers so the filestore operations can be mapped to the underlying filestore.
|
||||
*
|
||||
* It is used by implementing it in a child class and then passing it to the CFDP
|
||||
* handler objects. The base class provides default implementation for the user indication
|
||||
* primitives specified in the CFDP standard. The user can override these implementations
|
||||
* to provide custom indication handlers.
|
||||
*
|
||||
* Please note that for all indication callbacks, the passed transaction ID reference will
|
||||
* become invalid shortly after the function has been executed. If the transaction ID is to be
|
||||
* cached or used, create an own copy of it.
|
||||
* @param vfs Virtual Filestore Object. Will be used for all file operations
|
||||
*/
|
||||
class UserBase {
|
||||
friend class DestHandler;
|
||||
|
||||
public:
|
||||
explicit UserBase(HasFileSystemIF& vfs);
|
||||
|
||||
virtual void transactionIndication(const TransactionId& id) = 0;
|
||||
virtual void eofSentIndication(const TransactionId& id) = 0;
|
||||
virtual void transactionFinishedIndication(const TransactionFinishedParams& params) = 0;
|
||||
/**
|
||||
* Will be called if metadata was received.
|
||||
*
|
||||
* IMPORTANT: The passed struct contains the messages to the user in form of a raw C array.
|
||||
* The TLVs in these arrays are zero-copy types, which means that they point to the raw data
|
||||
* inside the metadata packet directly. The metadata packet will be deleted from the TC store
|
||||
* shortly after it was processed. If some of the data is to be cached and/or used after the
|
||||
* function call, it needs to be copied into another user-provided buffer.
|
||||
* @param params
|
||||
*/
|
||||
virtual void metadataRecvdIndication(const MetadataRecvdParams& params) = 0;
|
||||
virtual void fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) = 0;
|
||||
virtual void reportIndication(const TransactionId& id, StatusReportIF& report) = 0;
|
||||
virtual void suspendedIndication(const TransactionId& id, ConditionCode code) = 0;
|
||||
virtual void resumedIndication(const TransactionId& id, size_t progress) = 0;
|
||||
virtual void faultIndication(const TransactionId& id, ConditionCode code, size_t progress) = 0;
|
||||
virtual void abandonedIndication(const TransactionId& id, ConditionCode code,
|
||||
size_t progress) = 0;
|
||||
virtual void eofRecvIndication(const TransactionId& id) = 0;
|
||||
|
||||
private:
|
||||
HasFileSystemIF& vfs;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_USERBASE_H
|
9
src/fsfw/cfdp/handler/defs.h
Normal file
9
src/fsfw/cfdp/handler/defs.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef FSFW_CFDP_HANDLER_DEFS_H
|
||||
#define FSFW_CFDP_HANDLER_DEFS_H
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
|
||||
|
||||
}
|
||||
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
42
src/fsfw/cfdp/handler/mib.h
Normal file
42
src/fsfw/cfdp/handler/mib.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef FSFW_CFDP_MIB_H
|
||||
#define FSFW_CFDP_MIB_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "FaultHandlerBase.h"
|
||||
#include "fsfw/cfdp/pdu/PduConfig.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
struct IndicationCfg {
|
||||
bool eofSentIndicRequired = true;
|
||||
bool eofRecvIndicRequired = true;
|
||||
bool fileSegmentRecvIndicRequired = true;
|
||||
bool transactionFinishedIndicRequired = true;
|
||||
bool suspendedIndicRequired = true;
|
||||
bool resumedIndicRequired = true;
|
||||
};
|
||||
|
||||
struct LocalEntityCfg {
|
||||
LocalEntityCfg(EntityId localId, IndicationCfg indicationCfg, FaultHandlerBase& fhBase)
|
||||
: localId(std::move(localId)), indicCfg(indicationCfg), fhBase(fhBase) {}
|
||||
|
||||
EntityId localId;
|
||||
IndicationCfg indicCfg;
|
||||
FaultHandlerBase& fhBase;
|
||||
};
|
||||
|
||||
struct RemoteEntityCfg {
|
||||
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
|
||||
EntityId remoteId;
|
||||
size_t maxFileSegmentLen = 2048;
|
||||
bool closureRequested = false;
|
||||
bool crcOnTransmission = false;
|
||||
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
|
||||
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
|
||||
const uint8_t version = CFDP_VERSION_2;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_MIB_H
|
50
src/fsfw/cfdp/helpers.cpp
Normal file
50
src/fsfw/cfdp/helpers.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "helpers.h"
|
||||
|
||||
const char* COND_CODE_STRINGS[14] = {"Unknown",
|
||||
"No Error",
|
||||
"Positive ACK Limit Reached",
|
||||
"Keep Alive Limit Reached",
|
||||
"Invalid Transmission Mode",
|
||||
"Filestore Rejection",
|
||||
"File Checksum Failure",
|
||||
"File Size Error",
|
||||
"NAK limit reached",
|
||||
"Inactivity Detected",
|
||||
"Check Limit Reached",
|
||||
"Unsupported Checksum Type",
|
||||
"Suspend Request Received",
|
||||
"Cancel Request Received"};
|
||||
|
||||
const char* cfdp::getConditionCodeString(cfdp::ConditionCode code) {
|
||||
switch (code) {
|
||||
case NO_CONDITION_FIELD:
|
||||
return COND_CODE_STRINGS[0];
|
||||
case NO_ERROR:
|
||||
return COND_CODE_STRINGS[1];
|
||||
case POSITIVE_ACK_LIMIT_REACHED:
|
||||
return COND_CODE_STRINGS[2];
|
||||
case KEEP_ALIVE_LIMIT_REACHED:
|
||||
return COND_CODE_STRINGS[3];
|
||||
case INVALID_TRANSMISSION_MODE:
|
||||
return COND_CODE_STRINGS[4];
|
||||
case FILESTORE_REJECTION:
|
||||
return COND_CODE_STRINGS[5];
|
||||
case FILE_CHECKSUM_FAILURE:
|
||||
return COND_CODE_STRINGS[6];
|
||||
case FILE_SIZE_ERROR:
|
||||
return COND_CODE_STRINGS[7];
|
||||
case NAK_LIMIT_REACHED:
|
||||
return COND_CODE_STRINGS[8];
|
||||
case INACTIVITY_DETECTED:
|
||||
return COND_CODE_STRINGS[9];
|
||||
case CHECK_LIMIT_REACHED:
|
||||
return COND_CODE_STRINGS[10];
|
||||
case UNSUPPORTED_CHECKSUM_TYPE:
|
||||
return COND_CODE_STRINGS[11];
|
||||
case SUSPEND_REQUEST_RECEIVED:
|
||||
return COND_CODE_STRINGS[12];
|
||||
case CANCEL_REQUEST_RECEIVED:
|
||||
return COND_CODE_STRINGS[13];
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
11
src/fsfw/cfdp/helpers.h
Normal file
11
src/fsfw/cfdp/helpers.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef FSFW_EXAMPLE_HOSTED_HELPER_H
|
||||
#define FSFW_EXAMPLE_HOSTED_HELPER_H
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
const char* getConditionCodeString(cfdp::ConditionCode code);
|
||||
|
||||
}
|
||||
#endif // FSFW_EXAMPLE_HOSTED_HELPER_H
|
@ -1,12 +1,12 @@
|
||||
#include "AckInfo.h"
|
||||
|
||||
AckInfo::AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
||||
AckInfo::AckInfo(cfdp::FileDirective ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
||||
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode)
|
||||
: ackedDirective(ackedDirective),
|
||||
ackedConditionCode(ackedConditionCode),
|
||||
transactionStatus(transactionStatus),
|
||||
directiveSubtypeCode(directiveSubtypeCode) {
|
||||
if (ackedDirective == cfdp::FileDirectives::FINISH) {
|
||||
if (ackedDirective == cfdp::FileDirective::FINISH) {
|
||||
this->directiveSubtypeCode = 0b0001;
|
||||
} else {
|
||||
this->directiveSubtypeCode = 0b0000;
|
||||
@ -17,16 +17,16 @@ cfdp::ConditionCode AckInfo::getAckedConditionCode() const { return ackedConditi
|
||||
|
||||
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) {
|
||||
this->ackedConditionCode = ackedConditionCode;
|
||||
if (ackedDirective == cfdp::FileDirectives::FINISH) {
|
||||
if (ackedDirective == cfdp::FileDirective::FINISH) {
|
||||
this->directiveSubtypeCode = 0b0001;
|
||||
} else {
|
||||
this->directiveSubtypeCode = 0b0000;
|
||||
}
|
||||
}
|
||||
|
||||
cfdp::FileDirectives AckInfo::getAckedDirective() const { return ackedDirective; }
|
||||
cfdp::FileDirective AckInfo::getAckedDirective() const { return ackedDirective; }
|
||||
|
||||
void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective) {
|
||||
void AckInfo::setAckedDirective(cfdp::FileDirective ackedDirective) {
|
||||
this->ackedDirective = ackedDirective;
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,14 @@
|
||||
class AckInfo {
|
||||
public:
|
||||
AckInfo();
|
||||
AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
||||
AckInfo(cfdp::FileDirective 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);
|
||||
cfdp::FileDirective getAckedDirective() const;
|
||||
void setAckedDirective(cfdp::FileDirective ackedDirective);
|
||||
|
||||
uint8_t getDirectiveSubtypeCode() const;
|
||||
void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode);
|
||||
@ -22,7 +22,7 @@ class AckInfo {
|
||||
void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus);
|
||||
|
||||
private:
|
||||
cfdp::FileDirectives ackedDirective = cfdp::FileDirectives::INVALID_DIRECTIVE;
|
||||
cfdp::FileDirective ackedDirective = cfdp::FileDirective::INVALID_DIRECTIVE;
|
||||
cfdp::ConditionCode ackedConditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
|
||||
cfdp::AckTransactionStatus transactionStatus = cfdp::AckTransactionStatus::UNDEFINED;
|
||||
uint8_t directiveSubtypeCode = 0;
|
||||
|
33
src/fsfw/cfdp/pdu/AckPduCreator.cpp
Normal file
33
src/fsfw/cfdp/pdu/AckPduCreator.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "AckPduCreator.h"
|
||||
|
||||
AckPduCreator::AckPduCreator(AckInfo &ackInfo, PduConfig &pduConf)
|
||||
: FileDirectiveCreator(pduConf, cfdp::FileDirective::ACK, 2), ackInfo(ackInfo) {}
|
||||
|
||||
size_t AckPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); }
|
||||
|
||||
ReturnValue_t AckPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
cfdp::FileDirective ackedDirective = ackInfo.getAckedDirective();
|
||||
uint8_t directiveSubtypeCode = ackInfo.getDirectiveSubtypeCode();
|
||||
cfdp::ConditionCode ackedConditionCode = ackInfo.getAckedConditionCode();
|
||||
cfdp::AckTransactionStatus transactionStatus = ackInfo.getTransactionStatus();
|
||||
if (ackedDirective != cfdp::FileDirective::FINISH and
|
||||
ackedDirective != cfdp::FileDirective::EOF_DIRECTIVE) {
|
||||
// TODO: better returncode
|
||||
return returnvalue::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 returnvalue::OK;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
||||
#ifndef FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
||||
#define FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
||||
|
||||
#include "AckInfo.h"
|
||||
#include "FileDirectiveDeserializer.h"
|
||||
#include "FileDirectiveSerializer.h"
|
||||
#include "FileDirectiveCreator.h"
|
||||
#include "FileDirectiveReader.h"
|
||||
|
||||
class AckPduSerializer : public FileDirectiveSerializer {
|
||||
class AckPduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
/**
|
||||
* @brief Serializer to pack ACK PDUs
|
||||
@ -16,9 +16,9 @@ class AckPduSerializer : public FileDirectiveSerializer {
|
||||
* @param transactionStatus
|
||||
* @param pduConf
|
||||
*/
|
||||
AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf);
|
||||
AckPduCreator(AckInfo& ackInfo, PduConfig& pduConf);
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
@ -27,4 +27,4 @@ class AckPduSerializer : public FileDirectiveSerializer {
|
||||
AckInfo& ackInfo;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */
|
||||
#endif /* FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */
|
@ -1,37 +0,0 @@
|
||||
#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 != returnvalue::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 returnvalue::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;
|
||||
}
|
45
src/fsfw/cfdp/pdu/AckPduReader.cpp
Normal file
45
src/fsfw/cfdp/pdu/AckPduReader.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "AckPduReader.h"
|
||||
|
||||
AckPduReader::AckPduReader(const uint8_t* pduBuf, size_t maxSize, AckInfo& info)
|
||||
: FileDirectiveReader(pduBuf, maxSize), info(info) {}
|
||||
|
||||
ReturnValue_t AckPduReader::parseData() {
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
||||
if (currentIdx + 2 > this->maxSize) {
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
if (not checkAndSetCodes(pointers.rawPtr[currentIdx], pointers.rawPtr[currentIdx + 1])) {
|
||||
return cfdp::INVALID_ACK_DIRECTIVE_FIELDS;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
bool AckPduReader::checkAndSetCodes(uint8_t firstByte, uint8_t secondByte) {
|
||||
cfdp::FileDirective directive;
|
||||
if (not checkAckedDirectiveField(firstByte, directive)) {
|
||||
return false;
|
||||
}
|
||||
this->info.setAckedDirective(directive);
|
||||
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;
|
||||
}
|
||||
bool AckPduReader::checkAckedDirectiveField(uint8_t firstPduDataByte,
|
||||
cfdp::FileDirective& ackedDirective) {
|
||||
uint8_t ackedDirectiveRaw = static_cast<cfdp::FileDirective>(firstPduDataByte >> 4);
|
||||
if (ackedDirectiveRaw != cfdp::FileDirective::EOF_DIRECTIVE and
|
||||
ackedDirectiveRaw != cfdp::FileDirective::FINISH) {
|
||||
return false;
|
||||
}
|
||||
ackedDirective = (static_cast<cfdp::FileDirective>(ackedDirectiveRaw));
|
||||
return true;
|
||||
}
|
@ -2,18 +2,21 @@
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_
|
||||
|
||||
#include "AckInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
|
||||
class AckPduDeserializer : public FileDirectiveDeserializer {
|
||||
class AckPduReader : public FileDirectiveReader {
|
||||
public:
|
||||
AckPduDeserializer(const uint8_t* pduBuf, size_t maxSize, AckInfo& info);
|
||||
AckPduReader(const uint8_t* pduBuf, size_t maxSize, AckInfo& info);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
* - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields
|
||||
*/
|
||||
ReturnValue_t parseData();
|
||||
ReturnValue_t parseData() override;
|
||||
|
||||
static bool checkAckedDirectiveField(uint8_t firstPduDataByte,
|
||||
cfdp::FileDirective& ackedDirective);
|
||||
|
||||
private:
|
||||
bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode);
|
@ -1,36 +0,0 @@
|
||||
#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 != returnvalue::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 returnvalue::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 returnvalue::OK;
|
||||
}
|
@ -1,30 +1,29 @@
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE PduConfig.cpp
|
||||
VarLenField.cpp
|
||||
HeaderSerializer.cpp
|
||||
HeaderDeserializer.cpp
|
||||
FileDirectiveDeserializer.cpp
|
||||
FileDirectiveSerializer.cpp
|
||||
HeaderCreator.cpp
|
||||
HeaderReader.cpp
|
||||
FileDirectiveReader.cpp
|
||||
FileDirectiveCreator.cpp
|
||||
AckInfo.cpp
|
||||
AckPduSerializer.cpp
|
||||
AckPduDeserializer.cpp
|
||||
AckPduCreator.cpp
|
||||
AckPduReader.cpp
|
||||
EofInfo.cpp
|
||||
EofPduSerializer.cpp
|
||||
EofPduDeserializer.cpp
|
||||
EofPduCreator.cpp
|
||||
EofPduReader.cpp
|
||||
NakInfo.cpp
|
||||
NakPduSerializer.cpp
|
||||
NakPduDeserializer.cpp
|
||||
NakPduCreator.cpp
|
||||
NakPduReader.cpp
|
||||
FinishedInfo.cpp
|
||||
FinishedPduSerializer.cpp
|
||||
FinishedPduDeserializer.cpp
|
||||
FinishedPduCreator.cpp
|
||||
FinishedPduReader.cpp
|
||||
MetadataInfo.cpp
|
||||
MetadataPduSerializer.cpp
|
||||
MetadataPduDeserializer.cpp
|
||||
KeepAlivePduSerializer.cpp
|
||||
KeepAlivePduDeserializer.cpp
|
||||
PromptPduSerializer.cpp
|
||||
PromptPduDeserializer.cpp
|
||||
FileDataSerializer.cpp
|
||||
FileDataDeserializer.cpp
|
||||
MetadataPduCreator.cpp
|
||||
MetadataPduReader.cpp
|
||||
KeepAlivePduCreator.cpp
|
||||
KeepAlivePduReader.cpp
|
||||
PromptPduCreator.cpp
|
||||
PromptPduReader.cpp
|
||||
FileDataCreator.cpp
|
||||
FileDataReader.cpp
|
||||
FileDataInfo.cpp)
|
||||
|
@ -7,16 +7,16 @@
|
||||
|
||||
struct EofInfo {
|
||||
public:
|
||||
EofInfo(EntityIdTlv* faultLoc = nullptr);
|
||||
explicit 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;
|
||||
[[nodiscard]] uint32_t getChecksum() const;
|
||||
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
|
||||
|
||||
EntityIdTlv* getFaultLoc() const;
|
||||
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
|
||||
cfdp::FileSize& getFileSize();
|
||||
void setChecksum(uint32_t checksum);
|
||||
void setConditionCode(cfdp::ConditionCode conditionCode);
|
||||
|
@ -1,21 +1,17 @@
|
||||
#include "EofPduSerializer.h"
|
||||
#include "EofPduCreator.h"
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
EofPduSerializer::EofPduSerializer(PduConfig &conf, EofInfo &info)
|
||||
: FileDirectiveSerializer(conf, cfdp::FileDirectives::EOF_DIRECTIVE, 9), info(info) {
|
||||
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
|
||||
EofPduCreator::EofPduCreator(PduConfig &conf, EofInfo &info)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::EOF_DIRECTIVE, 9), info(info) {
|
||||
setDirectiveDataFieldLen(info.getSerializedSize(HeaderCreator::getLargeFileFlag()));
|
||||
}
|
||||
|
||||
size_t EofPduSerializer::getSerializedSize() const {
|
||||
return FileDirectiveSerializer::getWholePduSize();
|
||||
}
|
||||
size_t EofPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); }
|
||||
|
||||
ReturnValue_t EofPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
ReturnValue_t EofPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result =
|
||||
FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
@ -2,18 +2,20 @@
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_
|
||||
|
||||
#include "EofInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
|
||||
|
||||
class EofPduSerializer : public FileDirectiveSerializer {
|
||||
class EofPduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
EofPduSerializer(PduConfig& conf, EofInfo& info);
|
||||
EofPduCreator(PduConfig& conf, EofInfo& info);
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
using FileDirectiveCreator::serialize;
|
||||
|
||||
private:
|
||||
EofInfo& info;
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_
|
||||
|
||||
#include "EofInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.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_ */
|
@ -1,23 +1,23 @@
|
||||
#include "EofPduDeserializer.h"
|
||||
#include "EofPduReader.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) {}
|
||||
EofPduReader::EofPduReader(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo)
|
||||
: FileDirectiveReader(pduBuf, maxSize), info(eofInfo) {}
|
||||
|
||||
ReturnValue_t EofPduDeserializer::parseData() {
|
||||
ReturnValue_t result = FileDirectiveDeserializer::parseData();
|
||||
ReturnValue_t EofPduReader::parseData() {
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const uint8_t* bufPtr = rawPtr;
|
||||
const uint8_t* bufPtr = pointers.rawPtr;
|
||||
size_t expectedFileFieldLen = 4;
|
||||
if (this->getLargeFileFlag()) {
|
||||
expectedFileFieldLen = 8;
|
||||
}
|
||||
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
|
||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
||||
size_t deserLen = maxSize;
|
||||
if (maxSize < currentIdx + 5 + expectedFileFieldLen) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
17
src/fsfw/cfdp/pdu/EofPduReader.h
Normal file
17
src/fsfw/cfdp/pdu/EofPduReader.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_
|
||||
|
||||
#include "EofInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
|
||||
class EofPduReader : public FileDirectiveReader {
|
||||
public:
|
||||
EofPduReader(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo);
|
||||
|
||||
ReturnValue_t parseData() override;
|
||||
|
||||
private:
|
||||
EofInfo& info;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_EOFPDUDESERIALIZER_H_ */
|
@ -1,28 +1,31 @@
|
||||
#include "FileDataSerializer.h"
|
||||
#include "FileDataCreator.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
FileDataSerializer::FileDataSerializer(PduConfig& conf, FileDataInfo& info)
|
||||
: HeaderSerializer(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()),
|
||||
info(info) {
|
||||
FileDataCreator::FileDataCreator(PduConfig& conf, FileDataInfo& info)
|
||||
: HeaderCreator(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()), info(info) {
|
||||
update();
|
||||
}
|
||||
|
||||
void FileDataSerializer::update() {
|
||||
void FileDataCreator::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,
|
||||
ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (buffer == nullptr or size == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (*size + getSerializedSize() > maxSize) {
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
ReturnValue_t result = HeaderCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::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();
|
||||
@ -50,6 +53,6 @@ ReturnValue_t FileDataSerializer::serialize(uint8_t** buffer, size_t* size, size
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t FileDataSerializer::getSerializedSize() const {
|
||||
return HeaderSerializer::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag());
|
||||
size_t FileDataCreator::getSerializedSize() const {
|
||||
return HeaderCreator::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag());
|
||||
}
|
27
src/fsfw/cfdp/pdu/FileDataCreator.h
Normal file
27
src/fsfw/cfdp/pdu/FileDataCreator.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
|
||||
#define FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "FileDataInfo.h"
|
||||
#include "HeaderCreator.h"
|
||||
|
||||
class FileDataCreator : public HeaderCreator {
|
||||
public:
|
||||
FileDataCreator(PduConfig& conf, FileDataInfo& info);
|
||||
|
||||
void update();
|
||||
|
||||
ReturnValue_t serialize(uint8_t* buf, size_t& serLen, size_t maxSize) const {
|
||||
return SerializeIF::serialize(buf, serLen, maxSize, SerializeIF::Endianness::NETWORK);
|
||||
}
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
private:
|
||||
FileDataInfo& info;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_FILEDATASERIALIZER_H_ */
|
@ -57,16 +57,16 @@ ReturnValue_t FileDataInfo::addSegmentMetadataInfo(cfdp::RecordContinuationState
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
const uint8_t *FileDataInfo::getFileData(size_t *fileSize) const {
|
||||
if (fileSize != nullptr) {
|
||||
*fileSize = this->fileSize;
|
||||
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;
|
||||
const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
|
||||
if (segmentMetadataLen_ != nullptr) {
|
||||
*segmentMetadataLen_ = this->segmentMetadataLen;
|
||||
}
|
||||
return segmentMetadata;
|
||||
}
|
||||
|
@ -6,25 +6,25 @@
|
||||
|
||||
class FileDataInfo {
|
||||
public:
|
||||
FileDataInfo(cfdp::FileSize& offset);
|
||||
explicit FileDataInfo(cfdp::FileSize& offset);
|
||||
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
|
||||
|
||||
size_t getSerializedSize(bool largeFile = false) const;
|
||||
[[nodiscard]] 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;
|
||||
[[nodiscard]] cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const;
|
||||
[[nodiscard]] cfdp::SegmentationControl getSegmentationControl() const;
|
||||
[[nodiscard]] cfdp::RecordContinuationState getRecordContinuationState() const;
|
||||
void setRecordContinuationState(cfdp::RecordContinuationState recContState);
|
||||
void setSegmentationControl(cfdp::SegmentationControl segCtrl);
|
||||
|
||||
size_t getSegmentMetadataLen() const;
|
||||
[[nodiscard]] size_t getSegmentMetadataLen() const;
|
||||
void setSegmentMetadataLen(size_t len);
|
||||
void setSegmentMetadata(const uint8_t* ptr);
|
||||
bool hasSegmentMetadata() const;
|
||||
[[nodiscard]] bool hasSegmentMetadata() const;
|
||||
void setSegmentMetadataFlag(bool enable);
|
||||
ReturnValue_t addSegmentMetadataInfo(cfdp::RecordContinuationState recContState,
|
||||
const uint8_t* segmentMetadata, size_t segmentMetadataLen);
|
||||
|
@ -1,17 +1,16 @@
|
||||
#include "FileDataDeserializer.h"
|
||||
#include "FileDataReader.h"
|
||||
|
||||
FileDataDeserializer::FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize,
|
||||
FileDataInfo& info)
|
||||
: HeaderDeserializer(pduBuf, maxSize), info(info) {}
|
||||
FileDataReader::FileDataReader(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info)
|
||||
: PduHeaderReader(pduBuf, maxSize), info(info) {}
|
||||
|
||||
ReturnValue_t FileDataDeserializer::parseData() {
|
||||
ReturnValue_t result = HeaderDeserializer::parseData();
|
||||
ReturnValue_t FileDataReader::parseData() {
|
||||
ReturnValue_t result = PduHeaderReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
size_t currentIdx = HeaderDeserializer::getHeaderSize();
|
||||
const uint8_t* buf = rawPtr + currentIdx;
|
||||
size_t remSize = HeaderDeserializer::getWholePduSize() - currentIdx;
|
||||
size_t currentIdx = PduHeaderReader::getHeaderSize();
|
||||
const uint8_t* buf = pointers.rawPtr + currentIdx;
|
||||
size_t remSize = PduHeaderReader::getWholePduSize() - currentIdx;
|
||||
if (remSize < 1) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
@ -41,8 +40,8 @@ ReturnValue_t FileDataDeserializer::parseData() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
SerializeIF::Endianness FileDataDeserializer::getEndianness() const { return endianness; }
|
||||
SerializeIF::Endianness FileDataReader::getEndianness() const { return endianness; }
|
||||
|
||||
void FileDataDeserializer::setEndianness(SerializeIF::Endianness endianness) {
|
||||
this->endianness = endianness;
|
||||
void FileDataReader::setEndianness(SerializeIF::Endianness endianness_) {
|
||||
endianness = endianness_;
|
||||
}
|
@ -3,14 +3,14 @@
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "FileDataInfo.h"
|
||||
#include "HeaderDeserializer.h"
|
||||
#include "PduHeaderReader.h"
|
||||
|
||||
class FileDataDeserializer : public HeaderDeserializer {
|
||||
class FileDataReader : public PduHeaderReader {
|
||||
public:
|
||||
FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info);
|
||||
FileDataReader(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info);
|
||||
|
||||
ReturnValue_t parseData();
|
||||
SerializeIF::Endianness getEndianness() const;
|
||||
ReturnValue_t parseData() override;
|
||||
[[nodiscard]] SerializeIF::Endianness getEndianness() const;
|
||||
void setEndianness(SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK);
|
||||
|
||||
private:
|
@ -1,23 +0,0 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "FileDataInfo.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_ */
|
39
src/fsfw/cfdp/pdu/FileDirectiveCreator.cpp
Normal file
39
src/fsfw/cfdp/pdu/FileDirectiveCreator.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "FileDirectiveCreator.h"
|
||||
|
||||
FileDirectiveCreator::FileDirectiveCreator(PduConfig &pduConf, cfdp::FileDirective directiveCode,
|
||||
size_t directiveParamFieldLen)
|
||||
: HeaderCreator(pduConf, cfdp::PduType::FILE_DIRECTIVE, directiveParamFieldLen + 1),
|
||||
directiveCode(directiveCode) {}
|
||||
|
||||
size_t FileDirectiveCreator::getSerializedSize() const {
|
||||
return HeaderCreator::getSerializedSize() + 1;
|
||||
}
|
||||
|
||||
ReturnValue_t FileDirectiveCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
if (buffer == nullptr or size == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (FileDirectiveCreator::getWholePduSize() > maxSize) {
|
||||
return BUFFER_TOO_SHORT;
|
||||
}
|
||||
ReturnValue_t result = HeaderCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (*size >= maxSize) {
|
||||
return BUFFER_TOO_SHORT;
|
||||
}
|
||||
**buffer = directiveCode;
|
||||
*buffer += 1;
|
||||
*size += 1;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void FileDirectiveCreator::setDirectiveDataFieldLen(size_t len) {
|
||||
// Set length of data field plus 1 byte for the directive octet
|
||||
HeaderCreator::setPduDataFieldLen(len + 1);
|
||||
}
|
||||
|
||||
cfdp::FileDirective FileDirectiveCreator::getDirectiveCode() const { return directiveCode; }
|
34
src/fsfw/cfdp/pdu/FileDirectiveCreator.h
Normal file
34
src/fsfw/cfdp/pdu/FileDirectiveCreator.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/HeaderCreator.h"
|
||||
|
||||
class FileDirectiveCreator : public HeaderCreator {
|
||||
public:
|
||||
FileDirectiveCreator(PduConfig& pduConf, cfdp::FileDirective directiveCode,
|
||||
size_t directiveParamFieldLen);
|
||||
|
||||
[[nodiscard]] cfdp::FileDirective getDirectiveCode() const;
|
||||
|
||||
/**
|
||||
* This only returns the size of the PDU header + 1 for the directive code octet.
|
||||
* Use FileDirectiveCreator::getWholePduSize to get the full packet length, assuming
|
||||
* the length fields was set correctly
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
[[nodiscard]] ReturnValue_t serialize(uint8_t* buffer, size_t& serLen, size_t maxSize) const {
|
||||
return SerializeIF::serialize(buffer, serLen, maxSize, SerializeIF::Endianness::NETWORK);
|
||||
}
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
void setDirectiveDataFieldLen(size_t len);
|
||||
|
||||
private:
|
||||
cfdp::FileDirective directiveCode = cfdp::FileDirective::INVALID_DIRECTIVE;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ */
|
@ -1,49 +0,0 @@
|
||||
#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 != returnvalue::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 returnvalue::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; }
|
49
src/fsfw/cfdp/pdu/FileDirectiveReader.cpp
Normal file
49
src/fsfw/cfdp/pdu/FileDirectiveReader.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "FileDirectiveReader.h"
|
||||
|
||||
FileDirectiveReader::FileDirectiveReader(const uint8_t *pduBuf, size_t maxSize)
|
||||
: PduHeaderReader(pduBuf, maxSize) {}
|
||||
|
||||
cfdp::FileDirective FileDirectiveReader::getFileDirective() const { return fileDirective; }
|
||||
|
||||
ReturnValue_t FileDirectiveReader::parseData() {
|
||||
ReturnValue_t result = PduHeaderReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (this->getPduDataFieldLen() < 1) {
|
||||
return cfdp::INVALID_PDU_DATAFIELD_LEN;
|
||||
}
|
||||
if (FileDirectiveReader::getWholePduSize() > maxSize) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
size_t currentIdx = PduHeaderReader::getHeaderSize();
|
||||
if (not checkFileDirective(pointers.rawPtr[currentIdx])) {
|
||||
return cfdp::INVALID_DIRECTIVE_FIELD;
|
||||
}
|
||||
setFileDirective(static_cast<cfdp::FileDirective>(pointers.rawPtr[currentIdx]));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t FileDirectiveReader::getHeaderSize() const {
|
||||
// return size of header plus the directive byte
|
||||
return PduHeaderReader::getHeaderSize() + 1;
|
||||
}
|
||||
|
||||
bool FileDirectiveReader::checkFileDirective(uint8_t rawByte) {
|
||||
if (rawByte < cfdp::FileDirective::EOF_DIRECTIVE or
|
||||
(rawByte > cfdp::FileDirective::PROMPT and rawByte != cfdp::FileDirective::KEEP_ALIVE)) {
|
||||
// Invalid directive field
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileDirectiveReader::setFileDirective(cfdp::FileDirective fileDirective_) {
|
||||
fileDirective = fileDirective_;
|
||||
}
|
||||
|
||||
void FileDirectiveReader::setEndianness(SerializeIF::Endianness endianness_) {
|
||||
endianness = endianness_;
|
||||
}
|
||||
|
||||
SerializeIF::Endianness FileDirectiveReader::getEndianness() const { return endianness; }
|
@ -2,7 +2,7 @@
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "fsfw/cfdp/pdu/HeaderDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
|
||||
/**
|
||||
* @brief This class is used to deserialize a PDU file directive header from raw memory.
|
||||
@ -11,28 +11,27 @@
|
||||
* This is a zero-copy implementation and #parseData needs to be called to ensure the data is
|
||||
* valid.
|
||||
*/
|
||||
class FileDirectiveDeserializer : public HeaderDeserializer {
|
||||
class FileDirectiveReader : public PduHeaderReader {
|
||||
public:
|
||||
FileDirectiveDeserializer(const uint8_t* pduBuf, size_t maxSize);
|
||||
FileDirectiveReader(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;
|
||||
ReturnValue_t parseData() override;
|
||||
[[nodiscard]] size_t getHeaderSize() const override;
|
||||
|
||||
cfdp::FileDirectives getFileDirective() const;
|
||||
[[nodiscard]] cfdp::FileDirective getFileDirective() const;
|
||||
|
||||
void setEndianness(SerializeIF::Endianness endianness);
|
||||
SerializeIF::Endianness getEndianness() const;
|
||||
[[nodiscard]] SerializeIF::Endianness getEndianness() const;
|
||||
static bool checkFileDirective(uint8_t rawByte);
|
||||
|
||||
protected:
|
||||
bool checkFileDirective(uint8_t rawByte);
|
||||
|
||||
private:
|
||||
void setFileDirective(cfdp::FileDirectives fileDirective);
|
||||
cfdp::FileDirectives fileDirective = cfdp::FileDirectives::INVALID_DIRECTIVE;
|
||||
void setFileDirective(cfdp::FileDirective fileDirective);
|
||||
cfdp::FileDirective fileDirective = cfdp::FileDirective::INVALID_DIRECTIVE;
|
||||
SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK;
|
||||
};
|
||||
|
@ -1,38 +0,0 @@
|
||||
#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 returnvalue::FAILED;
|
||||
}
|
||||
if (FileDirectiveSerializer::getWholePduSize() > maxSize) {
|
||||
return BUFFER_TOO_SHORT;
|
||||
}
|
||||
ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (*size >= maxSize) {
|
||||
return BUFFER_TOO_SHORT;
|
||||
}
|
||||
**buffer = directiveCode;
|
||||
*buffer += 1;
|
||||
*size += 1;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void FileDirectiveSerializer::setDirectiveDataFieldLen(size_t len) {
|
||||
// Set length of data field plus 1 byte for the directive octet
|
||||
HeaderSerializer::setPduDataFieldLen(len + 1);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#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_ */
|
@ -2,9 +2,8 @@
|
||||
|
||||
FinishedInfo::FinishedInfo() {}
|
||||
|
||||
FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode,
|
||||
cfdp::FinishedDeliveryCode deliveryCode,
|
||||
cfdp::FinishedFileStatus fileStatus)
|
||||
FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FileDeliveryCode deliveryCode,
|
||||
cfdp::FileDeliveryStatus fileStatus)
|
||||
: conditionCode(conditionCode), deliveryCode(deliveryCode), fileStatus(fileStatus) {}
|
||||
|
||||
size_t FinishedInfo::getSerializedSize() const {
|
||||
@ -83,13 +82,13 @@ void FinishedInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
|
||||
this->conditionCode = conditionCode;
|
||||
}
|
||||
|
||||
cfdp::FinishedDeliveryCode FinishedInfo::getDeliveryCode() const { return deliveryCode; }
|
||||
cfdp::FileDeliveryCode FinishedInfo::getDeliveryCode() const { return deliveryCode; }
|
||||
|
||||
void FinishedInfo::setDeliveryCode(cfdp::FinishedDeliveryCode deliveryCode) {
|
||||
void FinishedInfo::setDeliveryCode(cfdp::FileDeliveryCode deliveryCode) {
|
||||
this->deliveryCode = deliveryCode;
|
||||
}
|
||||
|
||||
cfdp::FinishedFileStatus FinishedInfo::getFileStatus() const { return fileStatus; }
|
||||
cfdp::FileDeliveryStatus FinishedInfo::getFileStatus() const { return fileStatus; }
|
||||
|
||||
void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) {
|
||||
this->fsResponsesLen = fsResponsesLen;
|
||||
@ -97,6 +96,6 @@ void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) {
|
||||
|
||||
size_t FinishedInfo::getFsResponsesLen() const { return fsResponsesLen; }
|
||||
|
||||
void FinishedInfo::setFileStatus(cfdp::FinishedFileStatus fileStatus) {
|
||||
void FinishedInfo::setFileStatus(cfdp::FileDeliveryStatus fileStatus) {
|
||||
this->fileStatus = fileStatus;
|
||||
}
|
||||
|
@ -8,13 +8,13 @@
|
||||
class FinishedInfo {
|
||||
public:
|
||||
FinishedInfo();
|
||||
FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FinishedDeliveryCode deliveryCode,
|
||||
cfdp::FinishedFileStatus fileStatus);
|
||||
FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FileDeliveryCode deliveryCode,
|
||||
cfdp::FileDeliveryStatus fileStatus);
|
||||
|
||||
size_t getSerializedSize() const;
|
||||
[[nodiscard]] size_t getSerializedSize() const;
|
||||
|
||||
bool hasFsResponses() const;
|
||||
bool canHoldFsResponses() const;
|
||||
[[nodiscard]] bool hasFsResponses() const;
|
||||
[[nodiscard]] bool canHoldFsResponses() const;
|
||||
|
||||
ReturnValue_t setFilestoreResponsesArray(FilestoreResponseTlv** fsResponses,
|
||||
size_t* fsResponsesLen, const size_t* maxFsResponseLen);
|
||||
@ -22,20 +22,20 @@ class FinishedInfo {
|
||||
|
||||
ReturnValue_t getFilestoreResonses(FilestoreResponseTlv*** fsResponses, size_t* fsResponsesLen,
|
||||
size_t* fsResponsesMaxLen);
|
||||
size_t getFsResponsesLen() const;
|
||||
[[nodiscard]] size_t getFsResponsesLen() const;
|
||||
void setFilestoreResponsesArrayLen(size_t fsResponsesLen);
|
||||
ReturnValue_t getFaultLocation(EntityIdTlv** entityId);
|
||||
cfdp::ConditionCode getConditionCode() const;
|
||||
[[nodiscard]] 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);
|
||||
[[nodiscard]] cfdp::FileDeliveryCode getDeliveryCode() const;
|
||||
void setDeliveryCode(cfdp::FileDeliveryCode deliveryCode);
|
||||
[[nodiscard]] cfdp::FileDeliveryStatus getFileStatus() const;
|
||||
void setFileStatus(cfdp::FileDeliveryStatus fileStatus);
|
||||
|
||||
private:
|
||||
cfdp::ConditionCode conditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
|
||||
cfdp::FinishedDeliveryCode deliveryCode = cfdp::FinishedDeliveryCode::DATA_COMPLETE;
|
||||
cfdp::FinishedFileStatus fileStatus = cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY;
|
||||
cfdp::FileDeliveryCode deliveryCode = cfdp::FileDeliveryCode::DATA_COMPLETE;
|
||||
cfdp::FileDeliveryStatus fileStatus = cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY;
|
||||
FilestoreResponseTlv** fsResponses = nullptr;
|
||||
size_t fsResponsesLen = 0;
|
||||
size_t fsResponsesMaxLen = 0;
|
||||
|
@ -1,22 +1,19 @@
|
||||
#include "FinishedPduSerializer.h"
|
||||
#include "FinishedPduCreator.h"
|
||||
|
||||
FinishPduSerializer::FinishPduSerializer(PduConfig &conf, FinishedInfo &finishInfo)
|
||||
: FileDirectiveSerializer(conf, cfdp::FileDirectives::FINISH, 0), finishInfo(finishInfo) {
|
||||
FinishPduCreator::FinishPduCreator(PduConfig &conf, FinishedInfo &finishInfo)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::FINISH, 0), finishInfo(finishInfo) {
|
||||
updateDirectiveFieldLen();
|
||||
}
|
||||
|
||||
size_t FinishPduSerializer::getSerializedSize() const {
|
||||
return FinishPduSerializer::getWholePduSize();
|
||||
}
|
||||
size_t FinishPduCreator::getSerializedSize() const { return FinishPduCreator::getWholePduSize(); }
|
||||
|
||||
void FinishPduSerializer::updateDirectiveFieldLen() {
|
||||
void FinishPduCreator::updateDirectiveFieldLen() {
|
||||
setDirectiveDataFieldLen(finishInfo.getSerializedSize());
|
||||
}
|
||||
|
||||
ReturnValue_t FinishPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
ReturnValue_t FinishPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result =
|
||||
FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
24
src/fsfw/cfdp/pdu/FinishedPduCreator.h
Normal file
24
src/fsfw/cfdp/pdu/FinishedPduCreator.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_
|
||||
#define FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_
|
||||
|
||||
#include "FinishedInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
|
||||
class FinishPduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
FinishPduCreator(PduConfig& pduConf, FinishedInfo& finishInfo);
|
||||
|
||||
void updateDirectiveFieldLen();
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
using FileDirectiveCreator::serialize;
|
||||
|
||||
private:
|
||||
FinishedInfo& finishInfo;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_ */
|
@ -1,22 +0,0 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedInfo.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_ */
|
@ -1,25 +1,24 @@
|
||||
#include "FinishedPduDeserializer.h"
|
||||
#include "FinishedPduReader.h"
|
||||
|
||||
FinishPduDeserializer::FinishPduDeserializer(const uint8_t* pduBuf, size_t maxSize,
|
||||
FinishedInfo& info)
|
||||
: FileDirectiveDeserializer(pduBuf, maxSize), finishedInfo(info) {}
|
||||
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
|
||||
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}
|
||||
|
||||
ReturnValue_t FinishPduDeserializer::parseData() {
|
||||
ReturnValue_t result = FileDirectiveDeserializer::parseData();
|
||||
ReturnValue_t FinishPduReader::parseData() {
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
|
||||
const uint8_t* buf = rawPtr + currentIdx;
|
||||
size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
|
||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
||||
const uint8_t* buf = pointers.rawPtr + currentIdx;
|
||||
size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx;
|
||||
if (remSize < 1) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
uint8_t firstByte = *buf;
|
||||
cfdp::ConditionCode condCode = static_cast<cfdp::ConditionCode>((firstByte >> 4) & 0x0f);
|
||||
auto 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));
|
||||
finishedInfo.setDeliveryCode(static_cast<cfdp::FileDeliveryCode>(firstByte >> 2 & 0b1));
|
||||
finishedInfo.setFileStatus(static_cast<cfdp::FileDeliveryStatus>(firstByte & 0b11));
|
||||
buf += 1;
|
||||
remSize -= 1;
|
||||
currentIdx += 1;
|
||||
@ -29,9 +28,9 @@ ReturnValue_t FinishPduDeserializer::parseData() {
|
||||
return result;
|
||||
}
|
||||
|
||||
FinishedInfo& FinishPduDeserializer::getInfo() { return finishedInfo; }
|
||||
FinishedInfo& FinishPduReader::getInfo() { return finishedInfo; }
|
||||
|
||||
ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf,
|
||||
ReturnValue_t FinishPduReader::parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf,
|
||||
cfdp::ConditionCode conditionCode) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
size_t fsResponsesIdx = 0;
|
||||
@ -39,7 +38,7 @@ ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx,
|
||||
FilestoreResponseTlv** fsResponseArray = nullptr;
|
||||
size_t fsResponseMaxArrayLen = 0;
|
||||
EntityIdTlv* faultLocation = nullptr;
|
||||
cfdp::TlvTypes nextTlv = cfdp::TlvTypes::INVALID_TLV;
|
||||
cfdp::TlvType nextTlv = cfdp::TlvType::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
|
||||
@ -47,8 +46,8 @@ ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx,
|
||||
if (currentIdx + 2 > maxSize) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
nextTlv = static_cast<cfdp::TlvTypes>(*buf);
|
||||
if (nextTlv == cfdp::TlvTypes::FILESTORE_RESPONSE) {
|
||||
nextTlv = static_cast<cfdp::TlvType>(*buf);
|
||||
if (nextTlv == cfdp::TlvType::FILESTORE_RESPONSE) {
|
||||
if (fsResponseArray == nullptr) {
|
||||
if (not finishedInfo.canHoldFsResponses()) {
|
||||
return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES;
|
||||
@ -64,7 +63,7 @@ ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx,
|
||||
return result;
|
||||
}
|
||||
fsResponsesIdx += 1;
|
||||
} else if (nextTlv == cfdp::TlvTypes::ENTITY_ID) {
|
||||
} else if (nextTlv == cfdp::TlvType::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
|
22
src/fsfw/cfdp/pdu/FinishedPduReader.h
Normal file
22
src/fsfw/cfdp/pdu/FinishedPduReader.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_
|
||||
#define FSFW_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedInfo.h"
|
||||
|
||||
class FinishPduReader : public FileDirectiveReader {
|
||||
public:
|
||||
FinishPduReader(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_CFDP_PDU_FINISHEDPDUDESERIALIZER_H_ */
|
@ -1,23 +0,0 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_FINISHEDPDUSERIALIZER_H_
|
||||
|
||||
#include "FinishedInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.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_ */
|
111
src/fsfw/cfdp/pdu/HeaderCreator.cpp
Normal file
111
src/fsfw/cfdp/pdu/HeaderCreator.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
#include "HeaderCreator.h"
|
||||
|
||||
HeaderCreator::HeaderCreator(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 HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
if (buffer == nullptr or size == nullptr) {
|
||||
return returnvalue::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 != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = pduConf.seqNum.serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = pduConf.destId.serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t HeaderCreator::getSerializedSize() const {
|
||||
return pduConf.seqNum.getWidth() + pduConf.sourceId.getWidth() * 2 + 4;
|
||||
}
|
||||
|
||||
ReturnValue_t HeaderCreator::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) {
|
||||
// We could implement this, but I prefer dedicated classes
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
size_t HeaderCreator::getWholePduSize() const {
|
||||
// Return size of header plus the PDU data field length
|
||||
return pduDataFieldLen + HeaderCreator::getSerializedSize();
|
||||
}
|
||||
|
||||
size_t HeaderCreator::getPduDataFieldLen() const { return pduDataFieldLen; }
|
||||
|
||||
void HeaderCreator::setPduDataFieldLen(size_t pduDataFieldLen_) {
|
||||
pduDataFieldLen = pduDataFieldLen_;
|
||||
}
|
||||
|
||||
void HeaderCreator::setPduType(cfdp::PduType pduType_) { pduType = pduType_; }
|
||||
|
||||
void HeaderCreator::setSegmentMetadataFlag(cfdp::SegmentMetadataFlag segmentMetadataFlag_) {
|
||||
segmentMetadataFlag = segmentMetadataFlag_;
|
||||
}
|
||||
|
||||
cfdp::PduType HeaderCreator::getPduType() const { return pduType; }
|
||||
|
||||
cfdp::Direction HeaderCreator::getDirection() const { return pduConf.direction; }
|
||||
|
||||
cfdp::TransmissionMode HeaderCreator::getTransmissionMode() const { return pduConf.mode; }
|
||||
|
||||
bool HeaderCreator::getCrcFlag() const { return pduConf.crcFlag; }
|
||||
|
||||
bool HeaderCreator::getLargeFileFlag() const { return pduConf.largeFile; }
|
||||
|
||||
cfdp::SegmentationControl HeaderCreator::getSegmentationControl() const { return segmentationCtrl; }
|
||||
|
||||
cfdp::WidthInBytes HeaderCreator::getLenEntityIds() const { return pduConf.sourceId.getWidth(); }
|
||||
|
||||
cfdp::WidthInBytes HeaderCreator::getLenSeqNum() const { return pduConf.seqNum.getWidth(); }
|
||||
|
||||
cfdp::SegmentMetadataFlag HeaderCreator::getSegmentMetadataFlag() const {
|
||||
return segmentMetadataFlag;
|
||||
}
|
||||
|
||||
void HeaderCreator::getSourceId(cfdp::EntityId &sourceId) const { sourceId = pduConf.sourceId; }
|
||||
|
||||
void HeaderCreator::getDestId(cfdp::EntityId &destId) const { destId = pduConf.destId; }
|
||||
|
||||
void HeaderCreator::setSegmentationControl(cfdp::SegmentationControl segmentationControl) {
|
||||
this->segmentationCtrl = segmentationControl;
|
||||
}
|
||||
|
||||
void HeaderCreator::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const {
|
||||
seqNum = pduConf.seqNum;
|
||||
}
|
||||
|
||||
bool HeaderCreator::hasSegmentMetadataFlag() const {
|
||||
if (this->segmentMetadataFlag == cfdp::SegmentMetadataFlag::PRESENT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_HEADERSERIALIZER_H_
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "PduConfig.h"
|
||||
#include "PduHeaderIF.h"
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
|
||||
class HeaderSerializer : public SerializeIF, public PduHeaderIF {
|
||||
class HeaderCreator : public SerializeIF, public PduHeaderIF {
|
||||
public:
|
||||
HeaderSerializer(
|
||||
HeaderCreator(
|
||||
PduConfig& pduConf, cfdp::PduType pduType, size_t initPduDataFieldLen,
|
||||
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT,
|
||||
cfdp::SegmentationControl segCtrl =
|
||||
@ -23,7 +23,7 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF {
|
||||
* data field length was not properly.
|
||||
* @return
|
||||
*/
|
||||
size_t getSerializedSize() const override;
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
@ -32,19 +32,19 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF {
|
||||
void setPduType(cfdp::PduType pduType);
|
||||
void setSegmentMetadataFlag(cfdp::SegmentMetadataFlag);
|
||||
|
||||
size_t getPduDataFieldLen() const override;
|
||||
size_t getWholePduSize() const override;
|
||||
[[nodiscard]] size_t getPduDataFieldLen() const override;
|
||||
[[nodiscard]] 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;
|
||||
[[nodiscard]] cfdp::PduType getPduType() const override;
|
||||
[[nodiscard]] cfdp::Direction getDirection() const override;
|
||||
[[nodiscard]] cfdp::TransmissionMode getTransmissionMode() const override;
|
||||
[[nodiscard]] bool getCrcFlag() const override;
|
||||
[[nodiscard]] bool getLargeFileFlag() const override;
|
||||
[[nodiscard]] cfdp::SegmentationControl getSegmentationControl() const override;
|
||||
[[nodiscard]] cfdp::WidthInBytes getLenEntityIds() const override;
|
||||
[[nodiscard]] cfdp::WidthInBytes getLenSeqNum() const override;
|
||||
[[nodiscard]] cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
|
||||
[[nodiscard]] bool hasSegmentMetadataFlag() const override;
|
||||
void setSegmentationControl(cfdp::SegmentationControl);
|
||||
|
||||
void getSourceId(cfdp::EntityId& sourceId) const override;
|
@ -1,128 +0,0 @@
|
||||
#include "HeaderDeserializer.h"
|
||||
|
||||
#include <fsfw/serialize/SerializeAdapter.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 returnvalue::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 returnvalue::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;
|
||||
}
|
160
src/fsfw/cfdp/pdu/HeaderReader.cpp
Normal file
160
src/fsfw/cfdp/pdu/HeaderReader.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "PduHeaderReader.h"
|
||||
|
||||
PduHeaderReader::PduHeaderReader(const uint8_t *pduBuf, size_t maxSize) {
|
||||
setReadOnlyData(pduBuf, maxSize);
|
||||
}
|
||||
|
||||
ReturnValue_t PduHeaderReader::parseData() {
|
||||
if (pointers.rawPtr == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (maxSize < 7) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
pointers.fixedHeader =
|
||||
reinterpret_cast<PduHeaderFixedStruct *>(const_cast<uint8_t *>(pointers.rawPtr));
|
||||
sourceIdRaw = static_cast<uint8_t *>(&pointers.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);
|
||||
if (getWholePduSize() > PduHeaderReader::getHeaderSize()) {
|
||||
pointers.dataFieldStart = reinterpret_cast<const uint8_t *>(destIdRaw) + widthEntityIds;
|
||||
} else {
|
||||
pointers.dataFieldStart = nullptr;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PduHeaderReader::setData(uint8_t *dataPtr, size_t maxSize_, void *args) {
|
||||
if (dataPtr == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (maxSize_ < 7) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
pointers.rawPtr = dataPtr;
|
||||
maxSize = maxSize_;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t PduHeaderReader::getHeaderSize() const {
|
||||
if (pointers.fixedHeader != nullptr) {
|
||||
return getLenEntityIds() * 2 + getLenSeqNum() + 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t PduHeaderReader::getPduDataFieldLen() const {
|
||||
return (pointers.fixedHeader->pduDataFieldLenH << 8) | pointers.fixedHeader->pduDataFieldLenL;
|
||||
}
|
||||
|
||||
size_t PduHeaderReader::getWholePduSize() const {
|
||||
return getPduDataFieldLen() + PduHeaderReader::getHeaderSize();
|
||||
}
|
||||
|
||||
cfdp::PduType PduHeaderReader::getPduType() const {
|
||||
return static_cast<cfdp::PduType>((pointers.fixedHeader->firstByte >> 4) & 0x01);
|
||||
}
|
||||
|
||||
cfdp::Direction PduHeaderReader::getDirection() const {
|
||||
return static_cast<cfdp::Direction>((pointers.fixedHeader->firstByte >> 3) & 0x01);
|
||||
}
|
||||
|
||||
cfdp::TransmissionMode PduHeaderReader::getTransmissionMode() const {
|
||||
return static_cast<cfdp::TransmissionMode>((pointers.fixedHeader->firstByte >> 2) & 0x01);
|
||||
}
|
||||
|
||||
bool PduHeaderReader::getCrcFlag() const { return (pointers.fixedHeader->firstByte >> 1) & 0x01; }
|
||||
|
||||
bool PduHeaderReader::getLargeFileFlag() const { return pointers.fixedHeader->firstByte & 0x01; }
|
||||
|
||||
cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
|
||||
return static_cast<cfdp::SegmentationControl>((pointers.fixedHeader->fourthByte >> 7) & 0x01);
|
||||
}
|
||||
|
||||
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
|
||||
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
|
||||
}
|
||||
|
||||
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
|
||||
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
|
||||
}
|
||||
|
||||
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
|
||||
return static_cast<cfdp::SegmentMetadataFlag>((pointers.fixedHeader->fourthByte >> 3) & 0x01);
|
||||
}
|
||||
|
||||
void PduHeaderReader::getSourceId(cfdp::EntityId &sourceId) const {
|
||||
assignVarLenField(dynamic_cast<cfdp::VarLenField *>(&sourceId), getLenEntityIds(),
|
||||
this->sourceIdRaw);
|
||||
}
|
||||
|
||||
void PduHeaderReader::getDestId(cfdp::EntityId &destId) const {
|
||||
assignVarLenField(dynamic_cast<cfdp::VarLenField *>(&destId), getLenEntityIds(), this->destIdRaw);
|
||||
}
|
||||
|
||||
void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) const {
|
||||
assignVarLenField(dynamic_cast<cfdp::VarLenField *>(&seqNum), getLenSeqNum(), this->seqNumRaw);
|
||||
}
|
||||
|
||||
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
|
||||
void *sourcePtr) const {
|
||||
switch (width) {
|
||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||
auto *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 PduHeaderReader::getMaxSize() const { return maxSize; }
|
||||
|
||||
bool PduHeaderReader::hasSegmentMetadataFlag() const {
|
||||
if (this->getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t PduHeaderReader::setReadOnlyData(const uint8_t *dataPtr, size_t maxSize_) {
|
||||
return setData(const_cast<uint8_t *>(dataPtr), maxSize_, nullptr);
|
||||
}
|
||||
bool PduHeaderReader::isNull() const {
|
||||
return pointers.rawPtr == nullptr or pointers.fixedHeader == nullptr;
|
||||
}
|
||||
|
||||
PduHeaderReader::operator bool() const { return not isNull(); }
|
||||
|
||||
void PduHeaderReader::fillConfig(PduConfig &cfg) const {
|
||||
cfg.largeFile = getLargeFileFlag();
|
||||
cfg.crcFlag = getCrcFlag();
|
||||
cfg.mode = getTransmissionMode();
|
||||
cfg.direction = getDirection();
|
||||
getTransactionSeqNum(cfg.seqNum);
|
||||
getSourceId(cfg.sourceId);
|
||||
getDestId(cfg.destId);
|
||||
}
|
||||
|
||||
const uint8_t *PduHeaderReader::getPduDataField() const { return pointers.dataFieldStart; }
|
@ -1,117 +0,0 @@
|
||||
#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 returnvalue::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 != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = pduConf.seqNum.serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = pduConf.destId.serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return returnvalue::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 returnvalue::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;
|
||||
}
|
25
src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp
Normal file
25
src/fsfw/cfdp/pdu/KeepAlivePduCreator.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "KeepAlivePduCreator.h"
|
||||
|
||||
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
|
||||
updateDirectiveFieldLen();
|
||||
}
|
||||
|
||||
size_t KeepAlivePduCreator::getSerializedSize() const {
|
||||
return FileDirectiveCreator::getWholePduSize();
|
||||
}
|
||||
|
||||
void KeepAlivePduCreator::updateDirectiveFieldLen() {
|
||||
if (this->getLargeFileFlag()) {
|
||||
this->setDirectiveDataFieldLen(8);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t KeepAlivePduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||
}
|
22
src/fsfw/cfdp/pdu/KeepAlivePduCreator.h
Normal file
22
src/fsfw/cfdp/pdu/KeepAlivePduCreator.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
|
||||
#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
|
||||
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
|
||||
class KeepAlivePduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress);
|
||||
|
||||
void updateDirectiveFieldLen();
|
||||
|
||||
[[nodiscard]] 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_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */
|
@ -1,18 +0,0 @@
|
||||
#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 != returnvalue::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; }
|
@ -1,19 +0,0 @@
|
||||
#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_ */
|
18
src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp
Normal file
18
src/fsfw/cfdp/pdu/KeepAlivePduReader.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "KeepAlivePduReader.h"
|
||||
|
||||
KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize,
|
||||
cfdp::FileSize& progress)
|
||||
: FileDirectiveReader(pduBuf, maxSize), progress(progress) {}
|
||||
|
||||
ReturnValue_t KeepAlivePduReader::parseData() {
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
||||
size_t remLen = FileDirectiveReader::getWholePduSize() - currentIdx;
|
||||
const uint8_t* buffer = pointers.rawPtr + currentIdx;
|
||||
return progress.deSerialize(&buffer, &remLen, getEndianness());
|
||||
}
|
||||
|
||||
cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; }
|
19
src/fsfw/cfdp/pdu/KeepAlivePduReader.h
Normal file
19
src/fsfw/cfdp/pdu/KeepAlivePduReader.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_
|
||||
#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_
|
||||
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
|
||||
class KeepAlivePduReader : public FileDirectiveReader {
|
||||
public:
|
||||
KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress);
|
||||
|
||||
ReturnValue_t parseData() override;
|
||||
|
||||
cfdp::FileSize& getProgress();
|
||||
|
||||
private:
|
||||
cfdp::FileSize& progress;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */
|
@ -1,26 +0,0 @@
|
||||
#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 != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#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_ */
|
@ -1,49 +1,52 @@
|
||||
#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) {}
|
||||
cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
|
||||
cfdp::StringLv& destFileName)
|
||||
: MetadataInfo(fileSize, sourceFileName, destFileName) {
|
||||
this->closureRequested = closureRequested;
|
||||
this->checksumType = checksumType;
|
||||
}
|
||||
|
||||
void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray, size_t* optionsLen,
|
||||
size_t* maxOptionsLen) {
|
||||
this->optionsArray = optionsArray;
|
||||
if (maxOptionsLen != nullptr) {
|
||||
this->maxOptionsLen = *maxOptionsLen;
|
||||
MetadataInfo::MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
|
||||
cfdp::StringLv& destFileName)
|
||||
: fileSize(fileSize), sourceFileName(sourceFileName), destFileName(destFileName) {}
|
||||
|
||||
void MetadataInfo::setOptionsArray(cfdp::Tlv** optionsArray_, std::optional<size_t> optionsLen_,
|
||||
std::optional<size_t> maxOptionsLen_) {
|
||||
this->optionsArray = optionsArray_;
|
||||
if (maxOptionsLen_) {
|
||||
this->maxOptionsLen = maxOptionsLen_.value();
|
||||
}
|
||||
if (optionsLen != nullptr) {
|
||||
this->optionsLen = *optionsLen;
|
||||
if (optionsLen_) {
|
||||
this->optionsLen = optionsLen_.value();
|
||||
}
|
||||
}
|
||||
|
||||
cfdp::ChecksumType MetadataInfo::getChecksumType() const { return checksumType; }
|
||||
|
||||
void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType) {
|
||||
this->checksumType = checksumType;
|
||||
void MetadataInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
|
||||
checksumType = checksumType_;
|
||||
}
|
||||
|
||||
bool MetadataInfo::isClosureRequested() const { return closureRequested; }
|
||||
|
||||
void MetadataInfo::setClosureRequested(bool closureRequested) {
|
||||
this->closureRequested = closureRequested;
|
||||
void MetadataInfo::setClosureRequested(bool closureRequested_) {
|
||||
closureRequested = closureRequested_;
|
||||
}
|
||||
|
||||
cfdp::Lv& MetadataInfo::getDestFileName() { return destFileName; }
|
||||
cfdp::StringLv& MetadataInfo::getDestFileName() { return destFileName; }
|
||||
|
||||
cfdp::FileSize& MetadataInfo::getFileSize() { return fileSize; }
|
||||
|
||||
ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen,
|
||||
ReturnValue_t MetadataInfo::getOptions(cfdp::Tlv*** optionsArray_, size_t* optionsLen_,
|
||||
size_t* maxOptsLen) {
|
||||
if (optionsArray == nullptr or this->optionsArray == nullptr) {
|
||||
if (optionsArray_ == nullptr or optionsArray == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*optionsArray = this->optionsArray;
|
||||
if (optionsLen != nullptr) {
|
||||
*optionsLen = this->optionsLen;
|
||||
*optionsArray_ = optionsArray;
|
||||
if (optionsLen_ != nullptr) {
|
||||
*optionsLen_ = this->optionsLen;
|
||||
}
|
||||
if (maxOptsLen != nullptr) {
|
||||
*maxOptsLen = this->maxOptionsLen;
|
||||
@ -81,18 +84,20 @@ size_t MetadataInfo::getSerializedSize(bool fssLarge) {
|
||||
return size;
|
||||
}
|
||||
|
||||
void MetadataInfo::setDestFileName(cfdp::Lv& destFileName) { this->destFileName = destFileName; }
|
||||
void MetadataInfo::setDestFileName(cfdp::StringLv& destFileName_) {
|
||||
this->destFileName = destFileName_;
|
||||
}
|
||||
|
||||
void MetadataInfo::setSourceFileName(cfdp::Lv& sourceFileName) {
|
||||
this->sourceFileName = sourceFileName;
|
||||
void MetadataInfo::setSourceFileName(cfdp::StringLv& sourceFileName_) {
|
||||
this->sourceFileName = sourceFileName_;
|
||||
}
|
||||
|
||||
size_t MetadataInfo::getMaxOptionsLen() const { return maxOptionsLen; }
|
||||
|
||||
void MetadataInfo::setMaxOptionsLen(size_t maxOptionsLen) { this->maxOptionsLen = 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; }
|
||||
void MetadataInfo::setOptionsLen(size_t optionsLen_) { this->optionsLen = optionsLen_; }
|
||||
|
||||
cfdp::Lv& MetadataInfo::getSourceFileName() { return sourceFileName; }
|
||||
cfdp::StringLv& MetadataInfo::getSourceFileName() { return sourceFileName; }
|
||||
|
@ -1,45 +1,51 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
#include "fsfw/cfdp/tlv/Lv.h"
|
||||
#include "fsfw/cfdp/tlv/StringLv.h"
|
||||
#include "fsfw/cfdp/tlv/Tlv.h"
|
||||
|
||||
class MetadataInfo {
|
||||
public:
|
||||
MetadataInfo(cfdp::FileSize& fileSize, cfdp::StringLv& sourceFileName,
|
||||
cfdp::StringLv& destFileName);
|
||||
MetadataInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::FileSize& fileSize,
|
||||
cfdp::Lv& sourceFileName, cfdp::Lv& destFileName);
|
||||
cfdp::StringLv& sourceFileName, cfdp::StringLv& destFileName);
|
||||
|
||||
size_t getSerializedSize(bool fssLarge = false);
|
||||
|
||||
void setOptionsArray(cfdp::Tlv** optionsArray, size_t* optionsLen, size_t* maxOptionsLen);
|
||||
cfdp::ChecksumType getChecksumType() const;
|
||||
void setOptionsArray(cfdp::Tlv** optionsArray, std::optional<size_t> optionsLen,
|
||||
std::optional<size_t> maxOptionsLen);
|
||||
[[nodiscard]] cfdp::ChecksumType getChecksumType() const;
|
||||
void setChecksumType(cfdp::ChecksumType checksumType);
|
||||
bool isClosureRequested() const;
|
||||
[[nodiscard]] bool isClosureRequested() const;
|
||||
void setClosureRequested(bool closureRequested = false);
|
||||
|
||||
void setDestFileName(cfdp::Lv& destFileName);
|
||||
void setSourceFileName(cfdp::Lv& sourceFileName);
|
||||
void setDestFileName(cfdp::StringLv& destFileName);
|
||||
void setSourceFileName(cfdp::StringLv& sourceFileName);
|
||||
|
||||
cfdp::Lv& getDestFileName();
|
||||
cfdp::Lv& getSourceFileName();
|
||||
cfdp::StringLv& getDestFileName();
|
||||
cfdp::StringLv& getSourceFileName();
|
||||
cfdp::FileSize& getFileSize();
|
||||
|
||||
bool hasOptions() const;
|
||||
bool canHoldOptions() const;
|
||||
[[nodiscard]] bool hasOptions() const;
|
||||
[[nodiscard]] bool canHoldOptions() const;
|
||||
ReturnValue_t getOptions(cfdp::Tlv*** optionsArray, size_t* optionsLen, size_t* maxOptsLen);
|
||||
void setOptionsLen(size_t optionsLen);
|
||||
size_t getOptionsLen() const;
|
||||
[[nodiscard]] size_t getOptionsLen() const;
|
||||
void setMaxOptionsLen(size_t maxOptionsLen);
|
||||
size_t getMaxOptionsLen() const;
|
||||
[[nodiscard]] size_t getMaxOptionsLen() const;
|
||||
|
||||
private:
|
||||
bool closureRequested = false;
|
||||
cfdp::ChecksumType checksumType;
|
||||
cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
|
||||
cfdp::FileSize& fileSize;
|
||||
cfdp::Lv& sourceFileName;
|
||||
cfdp::Lv& destFileName;
|
||||
cfdp::StringLv& sourceFileName;
|
||||
cfdp::StringLv& destFileName;
|
||||
|
||||
cfdp::Tlv** optionsArray = nullptr;
|
||||
size_t optionsLen = 0;
|
||||
|
@ -1,22 +1,21 @@
|
||||
#include "MetadataPduSerializer.h"
|
||||
#include "MetadataPduCreator.h"
|
||||
|
||||
MetadataPduSerializer::MetadataPduSerializer(PduConfig &conf, MetadataInfo &info)
|
||||
: FileDirectiveSerializer(conf, cfdp::FileDirectives::METADATA, 5), info(info) {
|
||||
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) {
|
||||
updateDirectiveFieldLen();
|
||||
}
|
||||
|
||||
void MetadataPduSerializer::updateDirectiveFieldLen() {
|
||||
void MetadataPduCreator::updateDirectiveFieldLen() {
|
||||
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
|
||||
}
|
||||
|
||||
size_t MetadataPduSerializer::getSerializedSize() const {
|
||||
return FileDirectiveSerializer::getWholePduSize();
|
||||
size_t MetadataPduCreator::getSerializedSize() const {
|
||||
return FileDirectiveCreator::getWholePduSize();
|
||||
}
|
||||
|
||||
ReturnValue_t MetadataPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result =
|
||||
FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
23
src/fsfw/cfdp/pdu/MetadataPduCreator.h
Normal file
23
src/fsfw/cfdp/pdu/MetadataPduCreator.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
|
||||
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataInfo.h"
|
||||
|
||||
class MetadataPduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
MetadataPduCreator(PduConfig& conf, MetadataInfo& info);
|
||||
|
||||
void updateDirectiveFieldLen();
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
using FileDirectiveCreator::serialize;
|
||||
|
||||
private:
|
||||
MetadataInfo& info;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */
|
@ -1,17 +0,0 @@
|
||||
#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_ */
|
@ -1,17 +1,16 @@
|
||||
#include "MetadataPduDeserializer.h"
|
||||
#include "MetadataPduReader.h"
|
||||
|
||||
MetadataPduDeserializer::MetadataPduDeserializer(const uint8_t* pduBuf, size_t maxSize,
|
||||
MetadataInfo& info)
|
||||
: FileDirectiveDeserializer(pduBuf, maxSize), info(info) {}
|
||||
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info)
|
||||
: FileDirectiveReader(pduBuf, maxSize), info(info) {}
|
||||
|
||||
ReturnValue_t MetadataPduDeserializer::parseData() {
|
||||
ReturnValue_t result = FileDirectiveDeserializer::parseData();
|
||||
ReturnValue_t MetadataPduReader::parseData() {
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
|
||||
const uint8_t* buf = rawPtr + currentIdx;
|
||||
size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
|
||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
||||
const uint8_t* buf = pointers.rawPtr + currentIdx;
|
||||
size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx;
|
||||
if (remSize < 1) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
17
src/fsfw/cfdp/pdu/MetadataPduReader.h
Normal file
17
src/fsfw/cfdp/pdu/MetadataPduReader.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef FSFW_CFDP_PDU_METADATAPDUREADER_H_
|
||||
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataInfo.h"
|
||||
|
||||
class MetadataPduReader : public FileDirectiveReader {
|
||||
public:
|
||||
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
|
||||
|
||||
ReturnValue_t parseData() override;
|
||||
|
||||
private:
|
||||
MetadataInfo& info;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */
|
@ -1,22 +0,0 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAPDUSERIALIZER_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataInfo.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_ */
|
@ -26,7 +26,7 @@ bool NakInfo::hasSegmentRequests() const {
|
||||
}
|
||||
|
||||
bool NakInfo::canHoldSegmentRequests() const {
|
||||
if (this->segmentRequests != nullptr and maxSegmentRequestsLen > 0) {
|
||||
if (segmentRequests != nullptr and maxSegmentRequestsLen > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1,22 +1,19 @@
|
||||
#include "NakPduSerializer.h"
|
||||
#include "NakPduCreator.h"
|
||||
|
||||
NakPduSerializer::NakPduSerializer(PduConfig &pduConf, NakInfo &nakInfo)
|
||||
: FileDirectiveSerializer(pduConf, cfdp::FileDirectives::NAK, 0), nakInfo(nakInfo) {
|
||||
NakPduCreator::NakPduCreator(PduConfig &pduConf, NakInfo &nakInfo)
|
||||
: FileDirectiveCreator(pduConf, cfdp::FileDirective::NAK, 0), nakInfo(nakInfo) {
|
||||
updateDirectiveFieldLen();
|
||||
}
|
||||
|
||||
void NakPduSerializer::updateDirectiveFieldLen() {
|
||||
void NakPduCreator::updateDirectiveFieldLen() {
|
||||
this->setDirectiveDataFieldLen(nakInfo.getSerializedSize(getLargeFileFlag()));
|
||||
}
|
||||
|
||||
size_t NakPduSerializer::getSerializedSize() const {
|
||||
return FileDirectiveSerializer::getWholePduSize();
|
||||
}
|
||||
size_t NakPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); }
|
||||
|
||||
ReturnValue_t NakPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
ReturnValue_t NakPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result =
|
||||
FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
#ifndef FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_
|
||||
#ifndef FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_
|
||||
#define FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "NakInfo.h"
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
|
||||
class NakPduSerializer : public FileDirectiveSerializer {
|
||||
class NakPduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
/**
|
||||
*
|
||||
@ -18,9 +18,9 @@ class NakPduSerializer : public FileDirectiveSerializer {
|
||||
* @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);
|
||||
NakPduCreator(PduConfig& PduConf, NakInfo& nakInfo);
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
@ -35,4 +35,4 @@ class NakPduSerializer : public FileDirectiveSerializer {
|
||||
NakInfo& nakInfo;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ */
|
||||
#endif /* FSFW_CFDP_PDU_NAKPDUSERIALIZER_H_ */
|
@ -1,21 +0,0 @@
|
||||
#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_ */
|
@ -1,16 +1,16 @@
|
||||
#include "NakPduDeserializer.h"
|
||||
#include "NakPduReader.h"
|
||||
|
||||
NakPduDeserializer::NakPduDeserializer(const uint8_t* pduBuf, size_t maxSize, NakInfo& info)
|
||||
: FileDirectiveDeserializer(pduBuf, maxSize), nakInfo(info) {}
|
||||
NakPduReader::NakPduReader(const uint8_t* pduBuf, size_t maxSize, NakInfo& info)
|
||||
: FileDirectiveReader(pduBuf, maxSize), nakInfo(info) {}
|
||||
|
||||
ReturnValue_t NakPduDeserializer::parseData() {
|
||||
ReturnValue_t result = FileDirectiveDeserializer::parseData();
|
||||
ReturnValue_t NakPduReader::parseData() {
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
|
||||
const uint8_t* buffer = rawPtr + currentIdx;
|
||||
size_t remSize = FileDirectiveDeserializer::getWholePduSize() - currentIdx;
|
||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
||||
const uint8_t* buffer = pointers.rawPtr + currentIdx;
|
||||
size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx;
|
||||
if (remSize < 1) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user