Compare commits
31 Commits
mueller/ua
...
mueller/re
Author | SHA1 | Date | |
---|---|---|---|
af7ebd3564 | |||
a6ff3bb328 | |||
42a1e784c0 | |||
67b67de753 | |||
059e60cada | |||
9f83894d4c | |||
adcb646c9b | |||
16f8262a79 | |||
1a41d37f20 | |||
a3b9937f32 | |||
618f76ae78 | |||
ee2f8d6956 | |||
b11ae1c11d | |||
aea4e5d42c | |||
8d966de735 | |||
842f1b22af | |||
cb9c1806ef | |||
cdc431ebc5 | |||
7ab617accb | |||
e2d3158506 | |||
23c6145971 | |||
eafbab9c65 | |||
16bbc0f597 | |||
8d85da66f2 | |||
fb1d775b52 | |||
e8a5f1e095 | |||
f518bc53db | |||
b45b6b3758 | |||
83a2882f9d | |||
1b34b90ae0 | |||
77055a1579 |
98
CHANGELOG.md
98
CHANGELOG.md
@ -8,88 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
# [v6.0.0]
|
# [v5.0.0]
|
||||||
|
|
||||||
## Fixes
|
|
||||||
|
|
||||||
- Bugfix for Serial Buffer Stream: Setting `doActive` to false now
|
|
||||||
actually fully disables printing.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/680
|
|
||||||
- `TcpTmTcServer.cpp`: The server was actually not able to handle
|
|
||||||
CCSDS packets which were clumped together. This has been fixed now.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
|
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
- DHB TM handler `handleDeviceTM` renamed to `handleDeviceTm` and now takes
|
|
||||||
`util::DataWrapper` as the data input argument. This allows more flexibility in the possible
|
|
||||||
types of telemetry.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/669
|
|
||||||
- Add `util::DataWrapper` class inside the `util` module. This is a tagged union which allows
|
|
||||||
to specify raw data either as a classic C-style raw pointer and size or as a `SerializeIF`
|
|
||||||
pointer.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/668
|
|
||||||
- Add new `UnsignedByteField` class
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
|
||||||
|
|
||||||
## Changes
|
|
||||||
|
|
||||||
- Remove default secondary header argument for
|
|
||||||
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
|
||||||
`uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)`
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/689
|
|
||||||
- Removed `HasReturnvaluesIF` class in favor of `returnvalue` namespace with `OK` and `FAILED`
|
|
||||||
constants.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/659
|
|
||||||
- Overhaul of the TMTC stack, including various changes and improvements
|
|
||||||
for other modules
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/655
|
|
||||||
which also includes a migration guide
|
|
||||||
- Bump Catch2 dependency to regular version `v3.1.0`
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/678
|
|
||||||
- `SerialBufferAdapter`: Rename `setBuffer` to `setConstBuffer` and update
|
|
||||||
API to expect `const uint8_t*` accordingly.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/677
|
|
||||||
- Remove the following user includes from `fsfw/events/Event.h` and
|
|
||||||
`fsfw/returnvalues/returnvalue.h`:
|
|
||||||
- `#include "events/subsystemIdRanges.h"`
|
|
||||||
- `#include "returnvalues/classIds.h"`
|
|
||||||
The user has to include those themselves now
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/675
|
|
||||||
- `DeviceHandlerBase`: Set command sender before calling `buildCommandFromCommand`.
|
|
||||||
This allows finishing action commands immediately inside the function.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/672
|
|
||||||
- `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
|
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
@ -104,9 +23,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||||
- `SimpleRingBuffer::writeData` now checks if the amount is larger than the total size of the
|
|
||||||
Buffer and rejects such writeData calls with `returnvalue::FAILED`
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/586
|
|
||||||
- Major update for version handling, using `git describe` to fetch version information with git.
|
- Major update for version handling, using `git describe` to fetch version information with git.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
||||||
- Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules)
|
- Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules)
|
||||||
@ -222,6 +138,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
|||||||
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
||||||
Easiest solution for now: Keep this option OFF by default.
|
Easiest solution for now: Keep this option OFF by default.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
|
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
inside `fsfw/version.h`
|
inside `fsfw/version.h`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
@ -236,17 +153,6 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
- `Subsystem`: New API to add table and sequence entries
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
## HAL
|
|
||||||
|
|
||||||
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
|
|
||||||
lot more sense because each ComIF should be responsible for one SPI bus.
|
|
||||||
- SPI: Move the empty transfer to update the line polarity to separate function. This means
|
|
||||||
it is not automatically called when calling the setter function for SPI speed and mode.
|
|
||||||
The user should call this function after locking the CS mutex if multiple SPI devices with
|
|
||||||
differing speeds and modes are attached to one bus.
|
|
||||||
- SPI: Getter functions for SPI speed and mode.
|
|
||||||
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
|
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- TCP TMTC Server: `MutexGuard` was not created properly in
|
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||||
|
@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
|
|||||||
# Version file handling #
|
# Version file handling #
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
set(FSFW_VERSION_IF_GIT_FAILS 5)
|
set(FSFW_VERSION_IF_GIT_FAILS 4)
|
||||||
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
||||||
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
||||||
|
|
||||||
@ -74,15 +74,23 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
|
|||||||
set(FSFW_ETL_LIB_VERSION
|
set(FSFW_ETL_LIB_VERSION
|
||||||
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
|
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
|
||||||
CACHE STRING "ETL library exact version requirement")
|
CACHE STRING "ETL library exact version requirement")
|
||||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
|
||||||
|
|
||||||
set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
||||||
3
|
3
|
||||||
CACHE STRING "Catch2 library major version requirement")
|
CACHE STRING "Catch2 library major version requirement")
|
||||||
set(FSFW_CATCH2_LIB_VERSION
|
set(FSFW_CATCH2_LIB_VERSION
|
||||||
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
|
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5
|
||||||
CACHE STRING "Catch2 library exact version requirement")
|
CACHE STRING "Catch2 library exact version requirement")
|
||||||
|
|
||||||
|
set(FSFW_FMT_LIB_NAME fmt)
|
||||||
|
set(FSFW_FMT_LINK_TARGET fmt::fmt)
|
||||||
|
set(FSFW_FMT_LIB_MAJOR_VERSION
|
||||||
|
8
|
||||||
|
CACHE STRING "{fmt} library major version requirement")
|
||||||
|
set(FSFW_FMT_LIB_VERSION
|
||||||
|
${FSFW_FMT_LIB_MAJOR_VERSION}.1.1
|
||||||
|
CACHE STRING "{fmt} library exact version requirement")
|
||||||
|
|
||||||
# Keep this off by default for now. See PR:
|
# Keep this off by default for now. See PR:
|
||||||
# https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616 for information which
|
# https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616 for information which
|
||||||
# keeping this on by default is problematic
|
# keeping this on by default is problematic
|
||||||
@ -105,8 +113,7 @@ if(FSFW_GENERATE_SECTIONS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(FSFW_BUILD_TESTS
|
option(FSFW_BUILD_TESTS
|
||||||
"Build unittest binary in addition to static library. Requires Catch2"
|
"Build unittest binary in addition to static library" OFF)
|
||||||
OFF)
|
|
||||||
option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" 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)
|
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
||||||
if(FSFW_BUILD_TESTS)
|
if(FSFW_BUILD_TESTS)
|
||||||
@ -116,14 +123,9 @@ endif()
|
|||||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||||
# Options to exclude parts of the FSFW from compilation.
|
# Options to exclude parts of the FSFW from compilation.
|
||||||
option(FSFW_ADD_INTERNAL_TESTS "Add internal unit tests" ON)
|
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)
|
option(FSFW_ADD_HAL "Add Hardware Abstraction Layer" ON)
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add Linux peripheral drivers"
|
|
||||||
OFF)
|
|
||||||
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Attempt to add Linux GPIOD drivers" OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Optional sources
|
# Optional sources
|
||||||
option(FSFW_ADD_PUS "Compile with PUS sources" ON)
|
option(FSFW_ADD_PUS "Compile with PUS sources" ON)
|
||||||
option(FSFW_ADD_MONITORING "Compile with monitoring components" ON)
|
option(FSFW_ADD_MONITORING "Compile with monitoring components" ON)
|
||||||
@ -175,11 +177,11 @@ if(FSFW_BUILD_TESTS)
|
|||||||
|
|
||||||
project(${FSFW_TEST_TGT} CXX C)
|
project(${FSFW_TEST_TGT} CXX C)
|
||||||
add_executable(${FSFW_TEST_TGT})
|
add_executable(${FSFW_TEST_TGT})
|
||||||
|
|
||||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||||
TRUE)
|
TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FSFW_TESTS_GEN_COV)
|
if(FSFW_TESTS_GEN_COV)
|
||||||
message(STATUS "${MSG_PREFIX} Generating coverage data for the library")
|
message(STATUS "${MSG_PREFIX} Generating coverage data for the library")
|
||||||
message(STATUS "${MSG_PREFIX} Targets linking against ${LIB_FSFW_NAME} "
|
message(STATUS "${MSG_PREFIX} Targets linking against ${LIB_FSFW_NAME} "
|
||||||
@ -189,18 +191,15 @@ if(FSFW_BUILD_TESTS)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(
|
message(STATUS "${MSG_PREFIX} Finding and/or etl (Embedded Template Library)")
|
||||||
STATUS
|
|
||||||
"${MSG_PREFIX} Finding and/or providing etl library with version ${FSFW_ETL_LIB_MAJOR_VERSION}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check whether the user has already installed ETL first
|
# Check whether the user has already installed ETL first
|
||||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
|
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||||
# Not installed, so use FetchContent to download and provide etl
|
# Not installed, so use FetchContent to download and provide etl
|
||||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
|
"No ETL installation was found with find_package. Installing and providing "
|
||||||
"etl with FindPackage")
|
"etl with FindPackage")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
@ -212,6 +211,26 @@ if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
|||||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Finding and/or providing {fmt} formatting library")
|
||||||
|
|
||||||
|
# Check whether the user has already installed ETL first
|
||||||
|
find_package(fmt ${FSFW_FMT_LIB_MAJOR_VERSION} QUIET)
|
||||||
|
# Not installed, so use FetchContent to download and provide etl
|
||||||
|
if(NOT ${FSFW_FMT_LIB_NAME}_FOUND)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"No {fmt} installation was found with find_package. Installing and providing "
|
||||||
|
"{fmt} with FindPackage")
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
${FSFW_FMT_LIB_NAME}
|
||||||
|
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
|
||||||
|
GIT_TAG ${FSFW_FMT_LIB_VERSION})
|
||||||
|
|
||||||
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_FMT_LIB_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
# The documentation for FetchContent recommends declaring all the dependencies
|
# The documentation for FetchContent recommends declaring all the dependencies
|
||||||
# before making them available. We make all declared dependency available here
|
# before making them available. We make all declared dependency available here
|
||||||
# after their declaration
|
# after their declaration
|
||||||
@ -221,7 +240,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
|
|||||||
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
||||||
endif()
|
endif()
|
||||||
if(TARGET Catch2)
|
if(TARGET Catch2)
|
||||||
# Fixes regression -preview4, to be confirmed in later releases Related
|
# Fixes regression -preview4, to be confirmed in later releases. Related
|
||||||
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||||
endif()
|
endif()
|
||||||
@ -360,8 +379,7 @@ if(NOT FSFW_CONFIG_PATH)
|
|||||||
if(NOT FSFW_BUILD_DOCS)
|
if(NOT FSFW_BUILD_DOCS)
|
||||||
message(
|
message(
|
||||||
WARNING
|
WARNING
|
||||||
"${MSG_PREFIX} Flight Software Framework configuration path FSFW_CONFIG_PATH not set"
|
"${MSG_PREFIX} Flight Software Framework configuration path not set")
|
||||||
)
|
|
||||||
message(
|
message(
|
||||||
WARNING
|
WARNING
|
||||||
"${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..")
|
"${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..")
|
||||||
@ -455,9 +473,8 @@ target_include_directories(
|
|||||||
|
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
|
||||||
${COMPILER_FLAGS})
|
${COMPILER_FLAGS})
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ADDITIONAL_LINK_LIBS})
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ADDITIONAL_LINK_LIBS})
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${FSFW_ETL_LINK_TARGET})
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${FSFW_ETL_LINK_TARGET} ${FSFW_FMT_LINK_TARGET})
|
||||||
|
|
||||||
string(
|
string(
|
||||||
CONCAT
|
CONCAT
|
||||||
@ -467,6 +484,13 @@ string(
|
|||||||
"Target OSAL: ${FSFW_OS_NAME}\n"
|
"Target OSAL: ${FSFW_OS_NAME}\n"
|
||||||
"######################################################################\n")
|
"######################################################################\n")
|
||||||
|
|
||||||
|
# The additional / is important to remove the last character from the path. Note
|
||||||
|
# that it does not matter if the OS uses / or \, because we are only saving the
|
||||||
|
# path size.
|
||||||
|
string(LENGTH "${CMAKE_SOURCE_DIR}/" FSFW_SOURCE_PATH_SIZE)
|
||||||
|
target_compile_definitions(
|
||||||
|
${LIB_FSFW_NAME} PRIVATE "-DFSFW_SOURCE_PATH_SIZE=${FSFW_SOURCE_PATH_SIZE}")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${LIB_FSFW_NAME}
|
TARGET ${LIB_FSFW_NAME}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
|
@ -132,7 +132,7 @@ You can use the following commands inside the `fsfw` folder to set up the build
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir build-tests && cd build-tests
|
mkdir build-tests && cd build-tests
|
||||||
cmake -DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use `-DFSFW_OSAL=linux` on Linux systems.
|
You can also use `-DFSFW_OSAL=linux` on Linux systems.
|
||||||
@ -175,7 +175,7 @@ cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..
|
|||||||
Then you can generate the documentation using
|
Then you can generate the documentation using
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cmake --build . -- Sphinx -j
|
cmake --build . -j
|
||||||
```
|
```
|
||||||
|
|
||||||
You can find the generated documentation inside the `docs/sphinx` folder inside the build
|
You can find the generated documentation inside the `docs/sphinx` folder inside the build
|
||||||
|
@ -5,21 +5,16 @@ RUN apt-get --yes upgrade
|
|||||||
|
|
||||||
#tzdata is a dependency, won't install otherwise
|
#tzdata is a dependency, won't install otherwise
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz
|
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
|
||||||
|
|
||||||
RUN python3 -m pip install sphinx breathe
|
|
||||||
|
|
||||||
RUN git clone https://github.com/catchorg/Catch2.git && \
|
RUN git clone https://github.com/catchorg/Catch2.git && \
|
||||||
cd Catch2 && \
|
cd Catch2 && \
|
||||||
git checkout v3.1.0 && \
|
git checkout v3.0.0-preview5 && \
|
||||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||||
cmake --build build/ --target install
|
cmake --build build/ --target install
|
||||||
|
|
||||||
RUN git clone https://github.com/ETLCPP/etl.git && \
|
RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||||
cd etl && \
|
cd etl && \
|
||||||
git checkout 20.28.0 && \
|
git checkout 20.28.0 && \
|
||||||
cmake -B build . && \
|
cmake -B build . && \
|
||||||
cmake --install build/
|
cmake --install build/
|
||||||
|
|
||||||
#ssh needs a valid user to work
|
|
||||||
RUN adduser --uid 114 jenkins
|
|
||||||
|
50
automation/Jenkinsfile
vendored
50
automation/Jenkinsfile
vendored
@ -1,13 +1,9 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
environment {
|
environment {
|
||||||
BUILDDIR = 'cmake-build-tests'
|
BUILDDIR = 'build-tests'
|
||||||
DOCDDIR = 'cmake-build-documentation'
|
|
||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker { image 'fsfw-ci:d3'}
|
||||||
image 'fsfw-ci:d5'
|
|
||||||
args '--network host'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Clean') {
|
stage('Clean') {
|
||||||
@ -43,47 +39,5 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Documentation') {
|
|
||||||
when {
|
|
||||||
branch 'development'
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
dir(DOCDDIR) {
|
|
||||||
sh 'cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..'
|
|
||||||
sh 'make Sphinx'
|
|
||||||
sshagent(credentials: ['documentation-buildfix']) {
|
|
||||||
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/development/*'
|
|
||||||
sh 'scp -o StrictHostKeyChecking=no -r docs/sphinx/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/development'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dir(BUILDDIR) {
|
|
||||||
sshagent(credentials: ['documentation-buildfix']) {
|
|
||||||
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/coverage/development/*'
|
|
||||||
sh 'scp -o StrictHostKeyChecking=no -r fsfw-tests_coverage/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/coverage/development'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Master Documentation') {
|
|
||||||
when {
|
|
||||||
branch 'master'
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
dir(DOCDDIR) {
|
|
||||||
sh 'cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..'
|
|
||||||
sh 'make Sphinx'
|
|
||||||
sshagent(credentials: ['documentation-buildfix']) {
|
|
||||||
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/master/*'
|
|
||||||
sh 'scp -o StrictHostKeyChecking=no -r docs/sphinx/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/master'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dir(BUILDDIR) {
|
|
||||||
sshagent(credentials: ['documentation-buildfix']) {
|
|
||||||
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/coverage/master/*'
|
|
||||||
sh 'scp -o StrictHostKeyChecking=no -r fsfw-tests_coverage/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/coverage/master'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ FSFW to achieve that. The fsfw uses run-time type information but exceptions are
|
|||||||
# Failure Handling
|
# Failure Handling
|
||||||
|
|
||||||
Functions should return a defined `ReturnValue_t` to signal to the caller that something has
|
Functions should return a defined `ReturnValue_t` to signal to the caller that something has
|
||||||
gone wrong. Returnvalues must be unique. For this the function `returnvalue::makeCode`
|
gone wrong. Returnvalues must be unique. For this the function `HasReturnvaluesIF::makeReturnCode`
|
||||||
or the macro `MAKE_RETURN` can be used. The `CLASS_ID` is a unique id for that type of object.
|
or the macro `MAKE_RETURN` can be used. The `CLASS_ID` is a unique id for that type of object.
|
||||||
See `returnvalues/FwClassIds` folder. The user can add custom `CLASS_ID`s via the
|
See `returnvalues/FwClassIds` folder. The user can add custom `CLASS_ID`s via the
|
||||||
`fsfwconfig` folder.
|
`fsfwconfig` folder.
|
||||||
|
@ -144,7 +144,7 @@ ReturnValue_t GyroHandler::initializeLocalDataPool(localpool::DataPool &localDat
|
|||||||
new PoolEntry<uint8_t>({0}));
|
new PoolEntry<uint8_t>({0}));
|
||||||
|
|
||||||
poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false);
|
poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false);
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ in any case:
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
PoolReadGuard readHelper(&gyroData);
|
PoolReadGuard readHelper(&gyroData);
|
||||||
if(readHelper.getReadResult() == returnvalue::OK) {
|
if(readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||||
if(not gyroData.isValid()) {
|
if(not gyroData.isValid()) {
|
||||||
gyroData.setValidity(true, true);
|
gyroData.setValidity(true, true);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ API
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 4
|
:maxdepth: 4
|
||||||
|
|
||||||
api/cfdp
|
|
||||||
api/objectmanager
|
api/objectmanager
|
||||||
api/task
|
api/task
|
||||||
api/ipc
|
api/ipc
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
CFDP API
|
|
||||||
=================
|
|
||||||
|
|
||||||
``UserBase``
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. doxygenclass:: cfdp::UserBase
|
|
||||||
:members:
|
|
@ -3,7 +3,7 @@
|
|||||||
Returnvalue API
|
Returnvalue API
|
||||||
==================
|
==================
|
||||||
|
|
||||||
.. doxygenfile:: returnvalue.h
|
.. doxygenfile:: HasReturnvaluesIF.h
|
||||||
|
|
||||||
.. _fwclassids:
|
.. _fwclassids:
|
||||||
|
|
||||||
|
18
docs/conf.py
18
docs/conf.py
@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
project = "Flight Software Framework"
|
project = 'Flight Software Framework'
|
||||||
copyright = "2021, Institute of Space Systems (IRS)"
|
copyright = '2021, Institute of Space Systems (IRS)'
|
||||||
author = "Institute of Space Systems (IRS)"
|
author = 'Institute of Space Systems (IRS)'
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags
|
# The full version, including alpha/beta/rc tags
|
||||||
release = "5.0.0"
|
release = '2.0.1'
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
@ -30,17 +30,17 @@ release = "5.0.0"
|
|||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = ["breathe"]
|
extensions = [ "breathe" ]
|
||||||
|
|
||||||
breathe_default_project = "fsfw"
|
breathe_default_project = "fsfw"
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# 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
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
# This pattern also affects html_static_path and html_extra_path.
|
# 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 -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
@ -48,9 +48,9 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = "alabaster"
|
html_theme = 'alabaster'
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# 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,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = []
|
html_static_path = []
|
@ -75,11 +75,11 @@ and the respective source file with sensible default return values:
|
|||||||
void TestDeviceHandler::doShutDown() {}
|
void TestDeviceHandler::doShutDown() {}
|
||||||
|
|
||||||
ReturnValue_t TestDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
ReturnValue_t TestDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TestDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
ReturnValue_t TestDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDeviceHandler::fillCommandAndReplyMap() {}
|
void TestDeviceHandler::fillCommandAndReplyMap() {}
|
||||||
@ -87,17 +87,17 @@ and the respective source file with sensible default return values:
|
|||||||
ReturnValue_t TestDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
ReturnValue_t TestDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||||
const uint8_t* commandData,
|
const uint8_t* commandData,
|
||||||
size_t commandDataLen) {
|
size_t commandDataLen) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TestDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
ReturnValue_t TestDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
||||||
DeviceCommandId_t* foundId, size_t* foundLen) {
|
DeviceCommandId_t* foundId, size_t* foundLen) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TestDeviceHandler::interpretDeviceReply(DeviceCommandId_t id,
|
ReturnValue_t TestDeviceHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||||
const uint8_t* packet) {
|
const uint8_t* packet) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TestDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
|
uint32_t TestDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
|
||||||
@ -106,5 +106,5 @@ and the respective source file with sensible default return values:
|
|||||||
|
|
||||||
ReturnValue_t TestDeviceHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t TestDeviceHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
LocalDataPoolManager& poolManager) {
|
LocalDataPoolManager& poolManager) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ You can use the following commands inside the ``fsfw`` folder to set up the buil
|
|||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
mkdir build-tests && cd build-tests
|
mkdir build-tests && cd build-tests
|
||||||
cmake -DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host ..
|
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host ..
|
||||||
|
|
||||||
|
|
||||||
You can also use ``-DFSFW_OSAL=linux`` on Linux systems.
|
You can also use ``-DFSFW_OSAL=linux`` on Linux systems.
|
||||||
|
@ -7,20 +7,18 @@ Structure
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
The general structure is driven by the usage of interfaces provided by objects.
|
The general structure is driven by the usage of interfaces provided by objects.
|
||||||
The FSFW uses C++17 as baseline.
|
The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be
|
||||||
It also uses dynamic allocation during the initialization but provides
|
widely available, even with older compilers.
|
||||||
static containers during runtime.
|
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
|
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
||||||
standard containers.
|
Dynamic Allocation after initialization is discouraged and different solutions are provided in the
|
||||||
Dynamic Allocation after initialization is discouraged and different solutions
|
FSFW to achieve that. The fsfw uses run-time type information but exceptions are not allowed.
|
||||||
are provided in the FSFW to achieve that. The fsfw uses run-time type
|
|
||||||
information but will not throw exceptions.
|
|
||||||
|
|
||||||
Failure Handling
|
Failure Handling
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Functions should return a defined :cpp:type:`ReturnValue_t` to signal to the caller that something has
|
Functions should return a defined :cpp:type:`ReturnValue_t` to signal to the caller that something has
|
||||||
gone wrong. Returnvalues must be unique. For this the function :cpp:func:`returnvalue::makeCode`
|
gone wrong. Returnvalues must be unique. For this the function :cpp:func:`HasReturnvaluesIF::makeReturnCode`
|
||||||
or the :ref:`macro MAKE_RETURN_CODE <retvalapi>` can be used. The ``CLASS_ID`` is a unique ID for that type of object.
|
or the :ref:`macro MAKE_RETURN_CODE <retvalapi>` can be used. The ``CLASS_ID`` is a unique ID for that type of object.
|
||||||
See the :ref:`FSFW Class IDs file <fwclassids>`. The user can add custom ``CLASS_ID``\s via the
|
See the :ref:`FSFW Class IDs file <fwclassids>`. The user can add custom ``CLASS_ID``\s via the
|
||||||
``fsfwconfig`` folder.
|
``fsfwconfig`` folder.
|
||||||
|
@ -150,7 +150,7 @@ with a housekeeping service command.
|
|||||||
new PoolEntry<uint8_t>({0}));
|
new PoolEntry<uint8_t>({0}));
|
||||||
|
|
||||||
poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false);
|
poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false);
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Now, if we receive some sensor data and converted them into the right format,
|
Now, if we receive some sensor data and converted them into the right format,
|
||||||
@ -160,7 +160,7 @@ in any case:
|
|||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
PoolReadGuard readHelper(&gyroData);
|
PoolReadGuard readHelper(&gyroData);
|
||||||
if(readHelper.getReadResult() == returnvalue::OK) {
|
if(readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||||
if(not gyroData.isValid()) {
|
if(not gyroData.isValid()) {
|
||||||
gyroData.setValidity(true, true);
|
gyroData.setValidity(true, true);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "ServiceInterfaceBuffer.h"
|
#include "fsfw/serviceinterface/ServiceInterfaceBuffer.h"
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
|
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
|
||||||
@ -15,6 +16,8 @@
|
|||||||
// to be implemented by bsp
|
// to be implemented by bsp
|
||||||
extern "C" void printChar(const char*, bool errStream);
|
extern "C" void printChar(const char*, bool errStream);
|
||||||
|
|
||||||
|
#ifndef UT699
|
||||||
|
|
||||||
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble,
|
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble,
|
||||||
bool buffered, bool errStream, uint16_t port)
|
bool buffered, bool errStream, uint16_t port)
|
||||||
: isActive(true),
|
: isActive(true),
|
||||||
@ -55,9 +58,6 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addC
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
|
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
|
||||||
if (not isActive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char array[BUF_SIZE];
|
char array[BUF_SIZE];
|
||||||
uint32_t length = end - begin;
|
uint32_t length = end - begin;
|
||||||
if (length > sizeof(array)) {
|
if (length > sizeof(array)) {
|
||||||
@ -74,6 +74,8 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int ServiceInterfaceBuffer::overflow(int c) {
|
int ServiceInterfaceBuffer::overflow(int c) {
|
||||||
if (not buffered and this->isActive) {
|
if (not buffered and this->isActive) {
|
||||||
if (c != Traits::eof()) {
|
if (c != Traits::eof()) {
|
||||||
@ -167,4 +169,89 @@ void ServiceInterfaceBuffer::setAsciiColorPrefix(std::string colorPrefix) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#ifdef UT699
|
||||||
|
#include "../osal/rtems/Interrupt.h"
|
||||||
|
|
||||||
|
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
|
||||||
|
this->log_message = set_message;
|
||||||
|
this->isActive = true;
|
||||||
|
setp(buf, buf + BUF_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
|
||||||
|
char array[BUF_SIZE];
|
||||||
|
uint32_t length = end - begin;
|
||||||
|
if (length > sizeof(array)) {
|
||||||
|
length = sizeof(array);
|
||||||
|
}
|
||||||
|
memcpy(array, begin, length);
|
||||||
|
|
||||||
|
if (!Interrupt::isInterruptInProgress()) {
|
||||||
|
std::cout << array;
|
||||||
|
} else {
|
||||||
|
// Uncomment the following line if you need ISR debug output.
|
||||||
|
// printk(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // UT699
|
||||||
|
|
||||||
|
#ifdef ML505
|
||||||
|
#include <bsp_flp/network/networkconfig.h>
|
||||||
|
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port)
|
||||||
|
: isActive(true),
|
||||||
|
log_message(set_message),
|
||||||
|
udpSocket(0),
|
||||||
|
remoteAddressLength(sizeof(remoteAddress)) {
|
||||||
|
setp(buf, buf + BUF_SIZE);
|
||||||
|
memset((uint8_t*)&remoteAddress, 0, sizeof(remoteAddress));
|
||||||
|
remoteAddress.sin_family = AF_INET;
|
||||||
|
remoteAddress.sin_port = htons(port);
|
||||||
|
remoteAddress.sin_addr.s_addr = htonl(inet_addr("192.168.250.100"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
|
||||||
|
char array[BUF_SIZE];
|
||||||
|
uint32_t length = end - begin;
|
||||||
|
if (length > sizeof(array)) {
|
||||||
|
length = sizeof(array);
|
||||||
|
}
|
||||||
|
memcpy(array, begin, length);
|
||||||
|
|
||||||
|
if (udpSocket <= 0) {
|
||||||
|
initSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (udpSocket > 0) {
|
||||||
|
sendto(udpSocket, array, length, 0, (sockaddr*)&remoteAddress, sizeof(remoteAddress));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceInterfaceBuffer::initSocket() {
|
||||||
|
sockaddr_in address;
|
||||||
|
memset((uint8_t*)&address, 0, sizeof(address));
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_port = htons(0);
|
||||||
|
address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (socket < 0) {
|
||||||
|
printf("Error opening socket!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timeval timeout = {0, 20};
|
||||||
|
if (setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
|
||||||
|
printf("Error setting SO_RCVTIMEO socket options!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (setsockopt(udpSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
|
||||||
|
printf("Error setting SO_SNDTIMEO socket options!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bind(udpSocket, (sockaddr*)&address, sizeof(address)) < 0) {
|
||||||
|
printf("Error binding socket!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ML505
|
||||||
|
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
|
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
|
||||||
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
|
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
|
||||||
|
|
||||||
#include "fsfw/FSFW.h"
|
#include <FSFWConfig.h>
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
|
||||||
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
|
||||||
@ -10,6 +11,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#ifndef UT699
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the underlying stream buffer which implements the
|
* @brief This is the underlying stream buffer which implements the
|
||||||
* streambuf class and overloads the overflow() and sync() methods
|
* streambuf class and overloads the overflow() and sync() methods
|
||||||
@ -74,6 +77,85 @@ class ServiceInterfaceBuffer : public std::streambuf {
|
|||||||
bool crAdditionEnabled() const;
|
bool crAdditionEnabled() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UT699
|
||||||
|
class ServiceInterfaceBuffer : public std::basic_streambuf<char, std::char_traits<char> > {
|
||||||
|
friend class ServiceInterfaceStream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ServiceInterfaceBuffer(std::string set_message, uint16_t port);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool isActive;
|
||||||
|
// This is called when buffer becomes full. If
|
||||||
|
// buffer is not used, then this is called every
|
||||||
|
// time when characters are put to stream.
|
||||||
|
virtual int overflow(int c = Traits::eof());
|
||||||
|
|
||||||
|
// This function is called when stream is flushed,
|
||||||
|
// for example when std::endl is put to stream.
|
||||||
|
virtual int sync(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// For additional message information
|
||||||
|
std::string log_message;
|
||||||
|
// For EOF detection
|
||||||
|
typedef std::char_traits<char> Traits;
|
||||||
|
|
||||||
|
// Work in buffer mode. It is also possible to work without buffer.
|
||||||
|
static size_t const BUF_SIZE = 128;
|
||||||
|
char buf[BUF_SIZE];
|
||||||
|
|
||||||
|
// In this function, the characters are parsed.
|
||||||
|
void putChars(char const* begin, char const* end);
|
||||||
|
};
|
||||||
|
#endif // UT699
|
||||||
|
|
||||||
|
#ifdef ML505
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
class ServiceInterfaceBuffer : public std::basic_streambuf<char, std::char_traits<char> > {
|
||||||
|
friend class ServiceInterfaceStream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ServiceInterfaceBuffer(std::string set_message, uint16_t port);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool isActive;
|
||||||
|
// This is called when buffer becomes full. If
|
||||||
|
// buffer is not used, then this is called every
|
||||||
|
// time when characters are put to stream.
|
||||||
|
virtual int overflow(int c = Traits::eof());
|
||||||
|
|
||||||
|
// This function is called when stream is flushed,
|
||||||
|
// for example when std::endl is put to stream.
|
||||||
|
virtual int sync(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// For additional message information
|
||||||
|
std::string log_message;
|
||||||
|
// For EOF detection
|
||||||
|
typedef std::char_traits<char> Traits;
|
||||||
|
|
||||||
|
// Work in buffer mode. It is also possible to work without buffer.
|
||||||
|
static size_t const BUF_SIZE = 128;
|
||||||
|
char buf[BUF_SIZE];
|
||||||
|
|
||||||
|
// In this function, the characters are parsed.
|
||||||
|
void putChars(char const* begin, char const* end);
|
||||||
|
|
||||||
|
int udpSocket;
|
||||||
|
sockaddr_in remoteAddress;
|
||||||
|
socklen_t remoteAddressLength;
|
||||||
|
void initSocket();
|
||||||
|
};
|
||||||
|
#endif // ML505
|
||||||
|
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
|
||||||
#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ */
|
#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ */
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_
|
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_
|
||||||
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_
|
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_
|
||||||
|
|
||||||
|
#include <FSFWConfig.h>
|
||||||
|
|
||||||
#include "ServiceInterfaceBuffer.h"
|
#include "ServiceInterfaceBuffer.h"
|
||||||
#include "fsfw/FSFW.h"
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
|
||||||
@ -56,10 +57,10 @@ class ServiceInterfaceStream : public std::ostream {
|
|||||||
// Forward declaration of interface streams. These should be instantiated in
|
// Forward declaration of interface streams. These should be instantiated in
|
||||||
// main. They can then be used like std::cout or std::cerr.
|
// main. They can then be used like std::cout or std::cerr.
|
||||||
namespace sif {
|
namespace sif {
|
||||||
extern ServiceInterfaceStream debug;
|
// extern ServiceInterfaceStream debug;
|
||||||
extern ServiceInterfaceStream info;
|
// extern ServiceInterfaceStream info;
|
||||||
extern ServiceInterfaceStream warning;
|
// extern ServiceInterfaceStream warning;
|
||||||
extern ServiceInterfaceStream error;
|
// extern ServiceInterfaceStream error;
|
||||||
} // namespace sif
|
} // namespace sif
|
||||||
|
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
@ -4,10 +4,6 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// It is assumed the user has a subsystem and class ID list in some user header files.
|
|
||||||
// #include "events/subsystemIdRanges.h"
|
|
||||||
// #include "returnvalues/classIds.h"
|
|
||||||
|
|
||||||
//! Used to determine whether C++ ostreams are used which can increase
|
//! Used to determine whether C++ ostreams are used which can increase
|
||||||
//! the binary size significantly. If this is disabled,
|
//! the binary size significantly. If this is disabled,
|
||||||
//! the C stdio functions can be used alternatively
|
//! the C stdio functions can be used alternatively
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
#include <fsfw/events/EventManager.h>
|
#include <fsfw/events/EventManager.h>
|
||||||
#include <fsfw/health/HealthTable.h>
|
#include <fsfw/health/HealthTable.h>
|
||||||
|
#include <fsfw/tmtcpacket/pus/tm/TmPacketStored.h>
|
||||||
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||||
#include <fsfw/tmtcservices/PusServiceBase.h>
|
#include <fsfw/tmtcservices/PusServiceBase.h>
|
||||||
#include <fsfw/internalerror/InternalErrorReporter.h>
|
#include <fsfw/internalerror/InternalErrorReporter.h>
|
||||||
@ -34,15 +35,19 @@ void Factory::produceFsfwObjects(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Factory::setStaticFrameworkObjectIds() {
|
void Factory::setStaticFrameworkObjectIds() {
|
||||||
PusServiceBase::PUS_DISTRIBUTOR = objects::NO_OBJECT;
|
PusServiceBase::packetSource = objects::NO_OBJECT;
|
||||||
PusServiceBase::PACKET_DESTINATION = objects::NO_OBJECT;
|
PusServiceBase::packetDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
|
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
|
||||||
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
|
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
|
||||||
|
|
||||||
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||||
DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS;
|
DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS;
|
||||||
|
|
||||||
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
TmPacketBase::timeStamperId = objects::NO_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,15 +11,15 @@ ReturnValue_t pst::pollingSequenceInitDefault(
|
|||||||
|
|
||||||
/* Add polling sequence table here */
|
/* Add polling sequence table here */
|
||||||
|
|
||||||
if (thisSequence->checkSequence() == returnvalue::OK) {
|
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!"
|
sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef POLLINGSEQUENCEFACTORY_H_
|
#ifndef POLLINGSEQUENCEFACTORY_H_
|
||||||
#define POLLINGSEQUENCEFACTORY_H_
|
#define POLLINGSEQUENCEFACTORY_H_
|
||||||
|
|
||||||
#include <fsfw/returnvalues/returnvalue.h>
|
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
|
||||||
class FixedTimeslotTaskIF;
|
class FixedTimeslotTaskIF;
|
||||||
|
|
||||||
|
@ -3,17 +3,11 @@ if [[ ! -f README.md ]]; then
|
|||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
folder_list=(
|
|
||||||
"./src"
|
|
||||||
"./unittests"
|
|
||||||
)
|
|
||||||
|
|
||||||
cmake_fmt="cmake-format"
|
cmake_fmt="cmake-format"
|
||||||
file_selectors="-iname CMakeLists.txt"
|
file_selectors="-iname CMakeLists.txt"
|
||||||
if command -v ${cmake_fmt} &> /dev/null; then
|
if command -v ${cmake_fmt} &> /dev/null; then
|
||||||
${cmake_fmt} -i CMakeLists.txt
|
${cmake_fmt} -i CMakeLists.txt
|
||||||
find ./src ${file_selectors} | xargs ${cmake_fmt} -i
|
find ./src ${file_selectors} | xargs ${cmake_fmt} -i
|
||||||
find ./unittests ${file_selectors} | xargs ${cmake_fmt} -i
|
|
||||||
else
|
else
|
||||||
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
||||||
fi
|
fi
|
||||||
@ -21,10 +15,9 @@ fi
|
|||||||
cpp_format="clang-format"
|
cpp_format="clang-format"
|
||||||
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||||
if command -v ${cpp_format} &> /dev/null; then
|
if command -v ${cpp_format} &> /dev/null; then
|
||||||
for dir in ${folder_list[@]}; do
|
find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
echo "Auto-formatting ${dir} recursively"
|
find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
find ${dir} ${file_selectors} | xargs clang-format --style=file -i
|
find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
done
|
|
||||||
else
|
else
|
||||||
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||||
fi
|
fi
|
||||||
|
@ -13,7 +13,7 @@ from shutil import which
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
UNITTEST_FOLDER_NAME = "cmake-build-tests"
|
UNITTEST_FOLDER_NAME = "build-tests"
|
||||||
DOCS_FOLDER_NAME = "build-docs"
|
DOCS_FOLDER_NAME = "build-docs"
|
||||||
|
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-g",
|
"-g",
|
||||||
"--generators",
|
"--generators",
|
||||||
default="Ninja",
|
default = "Ninja",
|
||||||
action="store",
|
action="store",
|
||||||
help="CMake generators",
|
help="CMake generators",
|
||||||
)
|
)
|
||||||
@ -165,18 +165,10 @@ def create_tests_build_cfg(args):
|
|||||||
os.mkdir(UNITTEST_FOLDER_NAME)
|
os.mkdir(UNITTEST_FOLDER_NAME)
|
||||||
os.chdir(UNITTEST_FOLDER_NAME)
|
os.chdir(UNITTEST_FOLDER_NAME)
|
||||||
if args.windows:
|
if args.windows:
|
||||||
cmake_cmd = (
|
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \
|
||||||
'cmake -G "'
|
|
||||||
+ args.generators
|
|
||||||
+ '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \
|
|
||||||
-DGCOVR_PATH="py -m gcovr" ..'
|
-DGCOVR_PATH="py -m gcovr" ..'
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
cmake_cmd = (
|
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..'
|
||||||
'cmake -G "'
|
|
||||||
+ args.generators
|
|
||||||
+ '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..'
|
|
||||||
)
|
|
||||||
cmd_runner(cmake_cmd)
|
cmd_runner(cmake_cmd)
|
||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ add_subdirectory(thermal)
|
|||||||
add_subdirectory(timemanager)
|
add_subdirectory(timemanager)
|
||||||
add_subdirectory(tmtcpacket)
|
add_subdirectory(tmtcpacket)
|
||||||
add_subdirectory(tmtcservices)
|
add_subdirectory(tmtcservices)
|
||||||
add_subdirectory(filesystem)
|
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "fsfw/action.h"
|
#include "fsfw/action.h"
|
||||||
#include "fsfw/ipc/MessageQueueSenderIF.h"
|
#include "fsfw/ipc/MessageQueueSenderIF.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue)
|
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue)
|
||||||
: owner(setOwner), queueToUse(useThisQueue) {}
|
: owner(setOwner), queueToUse(useThisQueue) {}
|
||||||
@ -12,7 +12,7 @@ ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
|||||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||||
prepareExecution(command->getSender(), currentAction, ActionMessage::getStoreId(command));
|
prepareExecution(command->getSender(), currentAction, ActionMessage::getStoreId(command));
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return CommandMessage::UNKNOWN_COMMAND;
|
return CommandMessage::UNKNOWN_COMMAND;
|
||||||
}
|
}
|
||||||
@ -21,24 +21,18 @@ ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
|||||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||||
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
if (ipcStore == nullptr) {
|
if (ipcStore == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
if (queueToUse_ != nullptr) {
|
if (queueToUse_ != nullptr) {
|
||||||
setQueueToUse(queueToUse_);
|
setQueueToUse(queueToUse_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queueToUse == nullptr) {
|
if (queueToUse == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
FSFW_LOGW("{}", "initialize: No queue set\n");
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
sif::warning << "ActionHelper::initialize: No queue set" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("ActionHelper::initialize: No queue set\n");
|
|
||||||
#endif
|
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId,
|
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
@ -62,7 +56,7 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
|
|||||||
const uint8_t* dataPtr = nullptr;
|
const uint8_t* dataPtr = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
@ -75,7 +69,7 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
|
|||||||
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
}
|
}
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
@ -91,23 +85,16 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
|||||||
size_t maxSize = data->getSerializedSize();
|
size_t maxSize = data->getSerializedSize();
|
||||||
if (maxSize == 0) {
|
if (maxSize == 0) {
|
||||||
/* No error, there's simply nothing to report. */
|
/* No error, there's simply nothing to report. */
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, &dataPtr);
|
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, &dataPtr);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
FSFW_LOGWT("{}", "reportData: Getting free element from IPC store failed\n");
|
||||||
sif::warning << "ActionHelper::reportData: Getting free element from IPC store failed!"
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning(
|
|
||||||
"ActionHelper::reportData: Getting free element from IPC "
|
|
||||||
"store failed!\n");
|
|
||||||
#endif
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG);
|
result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -124,7 +111,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
|||||||
result = queueToUse->sendMessage(reportTo, &reply);
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -137,12 +124,8 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
|||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
store_address_t storeAddress;
|
store_address_t storeAddress;
|
||||||
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
FSFW_LOGWT("{}", "reportData: Adding data to IPC store failed\n");
|
||||||
sif::warning << "ActionHelper::reportData: Adding data to IPC store failed!" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("ActionHelper::reportData: Adding data to IPC store failed!\n");
|
|
||||||
#endif
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +141,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
|||||||
result = queueToUse->sendMessage(reportTo, &reply);
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -36,7 +36,7 @@ class ActionHelper {
|
|||||||
* send to the sender of the message automatically.
|
* send to the sender of the message automatically.
|
||||||
*
|
*
|
||||||
* @param command Pointer to a command message received by the owner
|
* @param command Pointer to a command message received by the owner
|
||||||
* @return returnvalue::OK if the message is a action message,
|
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
||||||
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||||
*/
|
*/
|
||||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||||
@ -45,7 +45,7 @@ class ActionHelper {
|
|||||||
* helper function
|
* helper function
|
||||||
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
||||||
* if queue was set in constructor
|
* if queue was set in constructor
|
||||||
* @return Returns returnvalue::OK if successful
|
* @return Returns RETURN_OK if successful
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||||
/**
|
/**
|
||||||
@ -58,7 +58,7 @@ class ActionHelper {
|
|||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId,
|
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
ReturnValue_t result = returnvalue::OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner to send a action completion message
|
* Function to be called by the owner to send a action completion message
|
||||||
* @param success Specify whether action was completed successfully or not.
|
* @param success Specify whether action was completed successfully or not.
|
||||||
@ -67,7 +67,7 @@ class ActionHelper {
|
|||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId,
|
void finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
ReturnValue_t result = returnvalue::OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner if an action does report data.
|
* Function to be called by the owner if an action does report data.
|
||||||
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
||||||
@ -75,7 +75,7 @@ class ActionHelper {
|
|||||||
* message to
|
* message to
|
||||||
* @param replyId ID of the executed command
|
* @param replyId ID of the executed command
|
||||||
* @param data Pointer to the data
|
* @param data Pointer to the data
|
||||||
* @return Returns returnvalue::OK if successful, otherwise failure code
|
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data,
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data,
|
||||||
bool hideSender = false);
|
bool hideSender = false);
|
||||||
@ -86,7 +86,7 @@ class ActionHelper {
|
|||||||
* message to
|
* message to
|
||||||
* @param replyId ID of the executed command
|
* @param replyId ID of the executed command
|
||||||
* @param data Pointer to the data
|
* @param data Pointer to the data
|
||||||
* @return Returns returnvalue::OK if successful, otherwise failure code
|
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, const uint8_t* data,
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, const uint8_t* data,
|
||||||
size_t dataSize, bool hideSender = false);
|
size_t dataSize, bool hideSender = false);
|
||||||
|
@ -25,7 +25,7 @@ store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
|||||||
|
|
||||||
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||||
ReturnValue_t result) {
|
ReturnValue_t result) {
|
||||||
if (result == returnvalue::OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
message->setCommand(STEP_SUCCESS);
|
message->setCommand(STEP_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
message->setCommand(STEP_FAILED);
|
message->setCommand(STEP_FAILED);
|
||||||
|
@ -33,12 +33,12 @@ class ActionMessage {
|
|||||||
static store_address_t getStoreId(const CommandMessage* message);
|
static store_address_t getStoreId(const CommandMessage* message);
|
||||||
|
|
||||||
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||||
ReturnValue_t result = returnvalue::OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
static uint8_t getStep(const CommandMessage* message);
|
static uint8_t getStep(const CommandMessage* message);
|
||||||
static ReturnValue_t getReturnCode(const CommandMessage* message);
|
static ReturnValue_t getReturnCode(const CommandMessage* message);
|
||||||
static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data);
|
static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data);
|
||||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid, bool success,
|
static void setCompletionReply(CommandMessage* message, ActionId_t fid, bool success,
|
||||||
ReturnValue_t result = returnvalue::OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
|
|
||||||
static void clear(CommandMessage* message);
|
static void clear(CommandMessage* message);
|
||||||
};
|
};
|
||||||
|
@ -16,12 +16,12 @@ ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId
|
|||||||
uint8_t *storePointer;
|
uint8_t *storePointer;
|
||||||
size_t maxSize = data->getSerializedSize();
|
size_t maxSize = data->getSerializedSize();
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &storePointer);
|
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &storePointer);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
result = data->serialize(&storePointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
result = data->serialize(&storePointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||||
@ -35,7 +35,7 @@ ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId
|
|||||||
}
|
}
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||||
@ -46,7 +46,7 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, ActionI
|
|||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
ActionMessage::setCommand(&command, actionId, storeId);
|
ActionMessage::setCommand(&command, actionId, storeId);
|
||||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
}
|
}
|
||||||
lastTarget = queueId;
|
lastTarget = queueId;
|
||||||
@ -57,44 +57,44 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, ActionI
|
|||||||
ReturnValue_t CommandActionHelper::initialize() {
|
ReturnValue_t CommandActionHelper::initialize() {
|
||||||
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
if (ipcStore == nullptr) {
|
if (ipcStore == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
queueToUse = owner->getCommandQueuePtr();
|
queueToUse = owner->getCommandQueuePtr();
|
||||||
if (queueToUse == nullptr) {
|
if (queueToUse == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||||
if (reply->getSender() != lastTarget) {
|
if (reply->getSender() != lastTarget) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
switch (reply->getCommand()) {
|
switch (reply->getCommand()) {
|
||||||
case ActionMessage::COMPLETION_SUCCESS:
|
case ActionMessage::COMPLETION_SUCCESS:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::COMPLETION_FAILED:
|
case ActionMessage::COMPLETION_FAILED:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getReturnCode(reply));
|
ActionMessage::getReturnCode(reply));
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::STEP_SUCCESS:
|
case ActionMessage::STEP_SUCCESS:
|
||||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStep(reply));
|
ActionMessage::getStep(reply));
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::STEP_FAILED:
|
case ActionMessage::STEP_FAILED:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply),
|
owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply),
|
||||||
ActionMessage::getReturnCode(reply));
|
ActionMessage::getReturnCode(reply));
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::DATA_REPLY:
|
case ActionMessage::DATA_REPLY:
|
||||||
extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply));
|
extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply));
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
default:
|
default:
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address
|
|||||||
const uint8_t *data = nullptr;
|
const uint8_t *data = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
owner->dataReceived(actionId, data, size);
|
owner->dataReceived(actionId, data, size);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "ActionMessage.h"
|
#include "ActionMessage.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "fsfw/serialize/SerializeIF.h"
|
#include "fsfw/serialize/SerializeIF.h"
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||||
|
|
||||||
@ -16,8 +16,8 @@ class CommandActionHelper {
|
|||||||
public:
|
public:
|
||||||
explicit CommandActionHelper(CommandsActionsIF* owner);
|
explicit CommandActionHelper(CommandsActionsIF* owner);
|
||||||
virtual ~CommandActionHelper();
|
virtual ~CommandActionHelper();
|
||||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
|
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
|
||||||
const uint8_t* data = nullptr, uint32_t size = 0);
|
uint32_t size);
|
||||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
ReturnValue_t handleReply(CommandMessage* reply);
|
ReturnValue_t handleReply(CommandMessage* reply);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "CommandActionHelper.h"
|
#include "CommandActionHelper.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to separate commanding actions of other objects.
|
* Interface to separate commanding actions of other objects.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "ActionMessage.h"
|
#include "ActionMessage.h"
|
||||||
#include "SimpleActionHelper.h"
|
#include "SimpleActionHelper.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
@ -53,7 +53,7 @@ class HasActionsIF {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||||
* -@c Not returnvalue::OK Step failure reply will be generated
|
* -@c Not RETURN_OK Step failure reply will be generated
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
const uint8_t* data, size_t size) = 0;
|
const uint8_t* data, size_t size) = 0;
|
||||||
|
@ -9,7 +9,7 @@ void SimpleActionHelper::step(ReturnValue_t result) {
|
|||||||
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||||
// method, which is not necessary here.
|
// method, which is not necessary here.
|
||||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction, result);
|
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction, result);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
resetHelper();
|
resetHelper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId
|
|||||||
const uint8_t* dataPtr = nullptr;
|
const uint8_t* dataPtr = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
@ -51,12 +51,12 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId
|
|||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case returnvalue::OK:
|
case HasReturnvaluesIF::RETURN_OK:
|
||||||
isExecuting = true;
|
isExecuting = true;
|
||||||
stepCount++;
|
stepCount++;
|
||||||
break;
|
break;
|
||||||
case HasActionsIF::EXECUTION_FINISHED:
|
case HasActionsIF::EXECUTION_FINISHED:
|
||||||
ActionMessage::setCompletionReply(&reply, actionId, true, returnvalue::OK);
|
ActionMessage::setCompletionReply(&reply, actionId, true, HasReturnvaluesIF::RETURN_OK);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -12,8 +12,8 @@ class SimpleActionHelper : public ActionHelper {
|
|||||||
public:
|
public:
|
||||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
~SimpleActionHelper() override;
|
~SimpleActionHelper() override;
|
||||||
void step(ReturnValue_t result = returnvalue::OK);
|
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
void finish(ReturnValue_t result = returnvalue::OK);
|
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
ReturnValue_t reportData(SerializeIF* data);
|
ReturnValue_t reportData(SerializeIF* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#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
|
|
52
src/fsfw/cfdp/CFDPHandler.cpp
Normal file
52
src/fsfw/cfdp/CFDPHandler.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "fsfw/cfdp/CFDPHandler.h"
|
||||||
|
|
||||||
|
#include "fsfw/cfdp/CFDPMessage.h"
|
||||||
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/serviceinterface.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) {
|
||||||
|
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
|
||||||
|
distributor = dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFDPHandler::~CFDPHandler() {}
|
||||||
|
|
||||||
|
ReturnValue_t CFDPHandler::initialize() {
|
||||||
|
ReturnValue_t result = SystemObject::initialize();
|
||||||
|
if (result != RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
this->distributor->registerHandler(this);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CFDPHandler::handleRequest(store_address_t storeId) {
|
||||||
|
FSFW_LOGDT("{}", "CFDPHandler::handleRequest\n");
|
||||||
|
|
||||||
|
// TODO read out packet from store using storeId
|
||||||
|
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CFDPHandler::performOperation(uint8_t opCode) {
|
||||||
|
ReturnValue_t status = RETURN_OK;
|
||||||
|
CommandMessage currentMessage;
|
||||||
|
for (status = this->requestQueue->receiveMessage(¤tMessage); status == RETURN_OK;
|
||||||
|
status = this->requestQueue->receiveMessage(¤tMessage)) {
|
||||||
|
store_address_t storeId = CFDPMessage::getStoreId(¤tMessage);
|
||||||
|
this->handleRequest(storeId);
|
||||||
|
}
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CFDPHandler::getIdentifier() { return 0; }
|
||||||
|
|
||||||
|
MessageQueueId_t CFDPHandler::getRequestQueue() { return this->requestQueue->getId(); }
|
63
src/fsfw/cfdp/CFDPHandler.h
Normal file
63
src/fsfw/cfdp/CFDPHandler.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef FSFW_CFDP_CFDPHANDLER_H_
|
||||||
|
#define FSFW_CFDP_CFDPHANDLER_H_
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.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,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
|
friend void(Factory::setStaticFrameworkObjectIds)();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CFDPHandler(object_id_t setObjectId, CFDPDistributor* distributor);
|
||||||
|
/**
|
||||||
|
* The destructor is empty.
|
||||||
|
*/
|
||||||
|
virtual ~CFDPHandler();
|
||||||
|
|
||||||
|
virtual ReturnValue_t handleRequest(store_address_t storeId);
|
||||||
|
|
||||||
|
virtual ReturnValue_t initialize() override;
|
||||||
|
virtual uint16_t getIdentifier() override;
|
||||||
|
MessageQueueId_t getRequestQueue() override;
|
||||||
|
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* This is a complete instance of the telecommand reception queue
|
||||||
|
* of the class. It is initialized on construction of the class.
|
||||||
|
*/
|
||||||
|
MessageQueueIF* requestQueue = nullptr;
|
||||||
|
|
||||||
|
CFDPDistributor* distributor = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current CFDP packet to be processed.
|
||||||
|
* It is deleted after handleRequest was executed.
|
||||||
|
*/
|
||||||
|
CFDPPacketStored currentPacket;
|
||||||
|
|
||||||
|
static object_id_t packetSource;
|
||||||
|
|
||||||
|
static object_id_t packetDestination;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* This constant sets the maximum number of packets accepted per call.
|
||||||
|
* Remember that one packet must be completely handled in one
|
||||||
|
* #handleRequest call.
|
||||||
|
*/
|
||||||
|
static const uint8_t CFDP_HANDLER_MAX_RECEPTION = 100;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_CFDP_CFDPHANDLER_H_ */
|
17
src/fsfw/cfdp/CFDPMessage.cpp
Normal file
17
src/fsfw/cfdp/CFDPMessage.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "CFDPMessage.h"
|
||||||
|
|
||||||
|
CFDPMessage::CFDPMessage() {}
|
||||||
|
|
||||||
|
CFDPMessage::~CFDPMessage() {}
|
||||||
|
|
||||||
|
void CFDPMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
|
||||||
|
message->setParameter(cfdpPacket.raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
store_address_t CFDPMessage::getStoreId(const CommandMessage *message) {
|
||||||
|
store_address_t storeAddressCFDPPacket;
|
||||||
|
storeAddressCFDPPacket = message->getParameter();
|
||||||
|
return storeAddressCFDPPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFDPMessage::clear(CommandMessage *message) {}
|
@ -5,14 +5,14 @@
|
|||||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||||
|
|
||||||
class CfdpMessage {
|
class CFDPMessage {
|
||||||
private:
|
private:
|
||||||
CfdpMessage();
|
CFDPMessage();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
|
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
|
||||||
|
|
||||||
virtual ~CfdpMessage();
|
virtual ~CFDPMessage();
|
||||||
static void setCommand(CommandMessage* message, store_address_t cfdpPacket);
|
static void setCommand(CommandMessage* message, store_address_t cfdpPacket);
|
||||||
|
|
||||||
static store_address_t getStoreId(const CommandMessage* message);
|
static store_address_t getStoreId(const CommandMessage* message);
|
@ -1,6 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE CfdpMessage.cpp CfdpDistributor.cpp
|
target_sources(${LIB_FSFW_NAME} PRIVATE CFDPHandler.cpp CFDPMessage.cpp)
|
||||||
VarLenFields.cpp helpers.cpp)
|
|
||||||
|
|
||||||
add_subdirectory(pdu)
|
add_subdirectory(pdu)
|
||||||
add_subdirectory(tlv)
|
add_subdirectory(tlv)
|
||||||
add_subdirectory(handler)
|
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
#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(); }
|
|
@ -1,76 +0,0 @@
|
|||||||
#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,17 +0,0 @@
|
|||||||
#include "CfdpMessage.h"
|
|
||||||
|
|
||||||
CfdpMessage::CfdpMessage() = default;
|
|
||||||
|
|
||||||
CfdpMessage::~CfdpMessage() = default;
|
|
||||||
|
|
||||||
void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
|
|
||||||
message->setParameter(cfdpPacket.raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {
|
|
||||||
store_address_t storeId;
|
|
||||||
storeId = static_cast<store_address_t>(message->getParameter());
|
|
||||||
return storeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfdpMessage::clear(CommandMessage *message) {}
|
|
@ -1,7 +1,5 @@
|
|||||||
#ifndef FSFW_CFDP_FILESIZE_H_
|
#ifndef FSFW_SRC_FSFW_CFDP_FILESIZE_H_
|
||||||
#define FSFW_CFDP_FILESIZE_H_
|
#define FSFW_SRC_FSFW_CFDP_FILESIZE_H_
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "fsfw/serialize/SerializeAdapter.h"
|
#include "fsfw/serialize/SerializeAdapter.h"
|
||||||
#include "fsfw/serialize/SerializeIF.h"
|
#include "fsfw/serialize/SerializeIF.h"
|
||||||
@ -10,11 +8,9 @@ namespace cfdp {
|
|||||||
|
|
||||||
struct FileSize : public SerializeIF {
|
struct FileSize : public SerializeIF {
|
||||||
public:
|
public:
|
||||||
FileSize() = default;
|
FileSize() : largeFile(false){};
|
||||||
|
|
||||||
explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
|
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,
|
ReturnValue_t serialize(bool isLarge, uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
Endianness streamEndianness) {
|
Endianness streamEndianness) {
|
||||||
@ -31,7 +27,7 @@ struct FileSize : public SerializeIF {
|
|||||||
return SerializeAdapter::serialize(&fileSize, buffer, size, maxSize, streamEndianness);
|
return SerializeAdapter::serialize(&fileSize, buffer, size, maxSize, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t getSerializedSize() const override {
|
size_t getSerializedSize() const override {
|
||||||
if (largeFile) {
|
if (largeFile) {
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
@ -47,29 +43,27 @@ struct FileSize : public SerializeIF {
|
|||||||
uint32_t sizeTmp = 0;
|
uint32_t sizeTmp = 0;
|
||||||
ReturnValue_t result =
|
ReturnValue_t result =
|
||||||
SerializeAdapter::deSerialize(&sizeTmp, buffer, size, streamEndianness);
|
SerializeAdapter::deSerialize(&sizeTmp, buffer, size, streamEndianness);
|
||||||
if (result == returnvalue::OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
fileSize = sizeTmp;
|
fileSize = sizeTmp;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t setFileSize(uint64_t fileSize_, std::optional<bool> largeFile_) {
|
ReturnValue_t setFileSize(uint64_t fileSize, bool largeFile) {
|
||||||
if (largeFile_) {
|
|
||||||
largeFile = largeFile_.value();
|
|
||||||
}
|
|
||||||
if (not largeFile and fileSize > UINT32_MAX) {
|
if (not largeFile and fileSize > UINT32_MAX) {
|
||||||
// TODO: emit warning here
|
// TODO: emit warning here
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
this->fileSize = fileSize_;
|
this->fileSize = fileSize;
|
||||||
return returnvalue::OK;
|
this->largeFile = largeFile;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool isLargeFile() const { return largeFile; }
|
bool isLargeFile() const { return largeFile; }
|
||||||
uint64_t getSize(bool *largeFile_ = nullptr) const {
|
uint64_t getSize(bool *largeFile = nullptr) const {
|
||||||
if (largeFile_ != nullptr) {
|
if (largeFile != nullptr) {
|
||||||
*largeFile_ = this->largeFile;
|
*largeFile = this->largeFile;
|
||||||
}
|
}
|
||||||
return fileSize;
|
return fileSize;
|
||||||
}
|
}
|
||||||
@ -81,4 +75,4 @@ struct FileSize : public SerializeIF {
|
|||||||
|
|
||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
|
||||||
#endif /* FSFW_CFDP_FILESIZE_H_ */
|
#endif /* FSFW_SRC_FSFW_CFDP_FILESIZE_H_ */
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
#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_ */
|
|
@ -7,37 +7,36 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "fsfw/returnvalues/FwClassIds.h"
|
#include "fsfw/returnvalues/FwClassIds.h"
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
namespace cfdp {
|
namespace cfdp {
|
||||||
|
|
||||||
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
|
static constexpr uint8_t VERSION_BITS = 0b00100000;
|
||||||
|
|
||||||
// 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 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_TLV_TYPE =
|
||||||
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 1);
|
||||||
static constexpr ReturnValue_t INVALID_PDU_DATAFIELD_LEN = returnvalue::makeCode(CFDP_CLASS_ID, 3);
|
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELDS =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 2);
|
||||||
|
static constexpr ReturnValue_t INVALID_PDU_DATAFIELD_LEN =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 3);
|
||||||
static constexpr ReturnValue_t INVALID_ACK_DIRECTIVE_FIELDS =
|
static constexpr ReturnValue_t INVALID_ACK_DIRECTIVE_FIELDS =
|
||||||
returnvalue::makeCode(CFDP_CLASS_ID, 4);
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 4);
|
||||||
//! Can not parse options. This can also occur because there are options
|
//! Can not parse options. This can also occur because there are options
|
||||||
//! available but the user did not pass a valid options array
|
//! available but the user did not pass a valid options array
|
||||||
static constexpr ReturnValue_t METADATA_CANT_PARSE_OPTIONS =
|
static constexpr ReturnValue_t METADATA_CANT_PARSE_OPTIONS =
|
||||||
returnvalue::makeCode(CFDP_CLASS_ID, 5);
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 5);
|
||||||
static constexpr ReturnValue_t NAK_CANT_PARSE_OPTIONS = returnvalue::makeCode(CFDP_CLASS_ID, 6);
|
static constexpr ReturnValue_t NAK_CANT_PARSE_OPTIONS =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 6);
|
||||||
static constexpr ReturnValue_t FINISHED_CANT_PARSE_FS_RESPONSES =
|
static constexpr ReturnValue_t FINISHED_CANT_PARSE_FS_RESPONSES =
|
||||||
returnvalue::makeCode(CFDP_CLASS_ID, 7);
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 6);
|
||||||
static constexpr ReturnValue_t FILESTORE_REQUIRES_SECOND_FILE =
|
static constexpr ReturnValue_t FILESTORE_REQUIRES_SECOND_FILE =
|
||||||
returnvalue::makeCode(CFDP_CLASS_ID, 8);
|
HasReturnvaluesIF::makeReturnCode(CFDP_CLASS_ID, 8);
|
||||||
//! Can not parse filestore response because user did not pass a valid instance
|
//! Can not parse filestore response because user did not pass a valid instance
|
||||||
//! or remaining size is invalid
|
//! or remaining size is invalid
|
||||||
static constexpr ReturnValue_t FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE =
|
static constexpr ReturnValue_t FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE =
|
||||||
returnvalue::makeCode(CFDP_CLASS_ID, 9);
|
HasReturnvaluesIF::makeReturnCode(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
|
//! Checksum types according to the SANA Checksum Types registry
|
||||||
//! https://sanaregistry.org/r/checksum_identifiers/
|
//! https://sanaregistry.org/r/checksum_identifiers/
|
||||||
@ -50,17 +49,17 @@ enum ChecksumType {
|
|||||||
NULL_CHECKSUM = 15
|
NULL_CHECKSUM = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PduType : uint8_t { FILE_DIRECTIVE = 0, FILE_DATA = 1 };
|
enum PduType : bool { FILE_DIRECTIVE = 0, FILE_DATA = 1 };
|
||||||
|
|
||||||
enum TransmissionMode : uint8_t { ACKNOWLEDGED = 0, UNACKNOWLEDGED = 1 };
|
enum TransmissionModes : bool { ACKNOWLEDGED = 0, UNACKNOWLEDGED = 1 };
|
||||||
|
|
||||||
enum SegmentMetadataFlag : bool { NOT_PRESENT = false, PRESENT = true };
|
enum SegmentMetadataFlag : bool { NOT_PRESENT = 0, PRESENT = 1 };
|
||||||
|
|
||||||
enum Direction : uint8_t { TOWARDS_RECEIVER = 0, TOWARDS_SENDER = 1 };
|
enum Direction : bool { TOWARDS_RECEIVER = 0, TOWARDS_SENDER = 1 };
|
||||||
|
|
||||||
enum SegmentationControl : bool {
|
enum SegmentationControl : bool {
|
||||||
NO_RECORD_BOUNDARIES_PRESERVATION = false,
|
NO_RECORD_BOUNDARIES_PRESERVATION = 0,
|
||||||
RECORD_BOUNDARIES_PRESERVATION = true
|
RECORD_BOUNDARIES_PRESERVATION = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
enum WidthInBytes : uint8_t {
|
enum WidthInBytes : uint8_t {
|
||||||
@ -70,9 +69,8 @@ enum WidthInBytes : uint8_t {
|
|||||||
FOUR_BYTES = 4,
|
FOUR_BYTES = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileDirective : uint8_t {
|
enum FileDirectives : uint8_t {
|
||||||
INVALID_DIRECTIVE = 0x0f,
|
INVALID_DIRECTIVE = 0x0f,
|
||||||
// The _DIRECTIVE suffix is mandatory here because of some nameclash!
|
|
||||||
EOF_DIRECTIVE = 0x04,
|
EOF_DIRECTIVE = 0x04,
|
||||||
FINISH = 0x05,
|
FINISH = 0x05,
|
||||||
ACK = 0x06,
|
ACK = 0x06,
|
||||||
@ -99,14 +97,6 @@ enum ConditionCode : uint8_t {
|
|||||||
CANCEL_REQUEST_RECEIVED = 0b1111
|
CANCEL_REQUEST_RECEIVED = 0b1111
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FaultHandlerCode {
|
|
||||||
RESERVED = 0b0000,
|
|
||||||
NOTICE_OF_CANCELLATION = 0b0001,
|
|
||||||
NOTICE_OF_SUSPENSION = 0b0010,
|
|
||||||
IGNORE_ERROR = 0b0011,
|
|
||||||
ABANDON_TRANSACTION = 0b0100
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AckTransactionStatus {
|
enum AckTransactionStatus {
|
||||||
UNDEFINED = 0b00,
|
UNDEFINED = 0b00,
|
||||||
ACTIVE = 0b01,
|
ACTIVE = 0b01,
|
||||||
@ -114,18 +104,18 @@ enum AckTransactionStatus {
|
|||||||
UNRECOGNIZED = 0b11
|
UNRECOGNIZED = 0b11
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileDeliveryCode { DATA_COMPLETE = 0, DATA_INCOMPLETE = 1 };
|
enum FinishedDeliveryCode { DATA_COMPLETE = 0, DATA_INCOMPLETE = 1 };
|
||||||
|
|
||||||
enum FileDeliveryStatus {
|
enum FinishedFileStatus {
|
||||||
DISCARDED_DELIBERATELY = 0,
|
DISCARDED_DELIBERATELY = 0,
|
||||||
DISCARDED_FILESTORE_REJECTION = 1,
|
DISCARDED_FILESTORE_REJECTION = 1,
|
||||||
RETAINED_IN_FILESTORE = 2,
|
RETAINED_IN_FILESTORE = 2,
|
||||||
FILE_STATUS_UNREPORTED = 3
|
FILE_STATUS_UNREPORTED = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PromptResponseRequired : uint8_t { PROMPT_NAK = 0, PROMPT_KEEP_ALIVE = 1 };
|
enum PromptResponseRequired : bool { PROMPT_NAK = 0, PROMPT_KEEP_ALIVE = 1 };
|
||||||
|
|
||||||
enum TlvType : uint8_t {
|
enum TlvTypes : uint8_t {
|
||||||
FILESTORE_REQUEST = 0x00,
|
FILESTORE_REQUEST = 0x00,
|
||||||
FILESTORE_RESPONSE = 0x01,
|
FILESTORE_RESPONSE = 0x01,
|
||||||
MSG_TO_USER = 0x02,
|
MSG_TO_USER = 0x02,
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
target_sources(
|
|
||||||
${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
|
|
||||||
FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp)
|
|
@ -1,134 +0,0 @@
|
|||||||
#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),
|
|
||||||
msgQueue(fsfwParams.msgQueue),
|
|
||||||
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)) {
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
#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, MessageQueueIF& msgQueue)
|
|
||||||
: objectId(objectId),
|
|
||||||
vfs(vfs),
|
|
||||||
packetDest(packetDest),
|
|
||||||
tcStore(tcStore),
|
|
||||||
tmStore(tmStore),
|
|
||||||
msgQueue(msgQueue) {}
|
|
||||||
object_id_t objectId{};
|
|
||||||
HasFileSystemIF& vfs;
|
|
||||||
AcceptsTelemetryIF& packetDest;
|
|
||||||
StorageManagerIF& tcStore;
|
|
||||||
StorageManagerIF& tmStore;
|
|
||||||
MessageQueueIF& msgQueue;
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
cfdp::DestHandler destHandler;
|
|
||||||
StorageManagerIF* tcStore = nullptr;
|
|
||||||
StorageManagerIF* tmStore = nullptr;
|
|
||||||
|
|
||||||
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
|
|
@ -1,480 +0,0 @@
|
|||||||
#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; }
|
|
@ -1,202 +0,0 @@
|
|||||||
#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
|
|
@ -1,51 +0,0 @@
|
|||||||
#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
|
|
@ -1,77 +0,0 @@
|
|||||||
#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
|
|
@ -1,35 +0,0 @@
|
|||||||
#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 +0,0 @@
|
|||||||
#include "SourceHandler.h"
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
|
|
||||||
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
|
|
||||||
|
|
||||||
class SourceHandler {};
|
|
||||||
|
|
||||||
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H
|
|
@ -1,12 +0,0 @@
|
|||||||
#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
|
|
@ -1,3 +0,0 @@
|
|||||||
#include "UserBase.h"
|
|
||||||
|
|
||||||
cfdp::UserBase::UserBase(HasFileSystemIF& vfs) : vfs(vfs) {}
|
|
@ -1,101 +0,0 @@
|
|||||||
#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
|
|
@ -1,9 +0,0 @@
|
|||||||
#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
|
|
@ -1,42 +0,0 @@
|
|||||||
#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
|
|
@ -1,50 +0,0 @@
|
|||||||
#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";
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#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"
|
#include "AckInfo.h"
|
||||||
|
|
||||||
AckInfo::AckInfo(cfdp::FileDirective ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
AckInfo::AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
||||||
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode)
|
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode)
|
||||||
: ackedDirective(ackedDirective),
|
: ackedDirective(ackedDirective),
|
||||||
ackedConditionCode(ackedConditionCode),
|
ackedConditionCode(ackedConditionCode),
|
||||||
transactionStatus(transactionStatus),
|
transactionStatus(transactionStatus),
|
||||||
directiveSubtypeCode(directiveSubtypeCode) {
|
directiveSubtypeCode(directiveSubtypeCode) {
|
||||||
if (ackedDirective == cfdp::FileDirective::FINISH) {
|
if (ackedDirective == cfdp::FileDirectives::FINISH) {
|
||||||
this->directiveSubtypeCode = 0b0001;
|
this->directiveSubtypeCode = 0b0001;
|
||||||
} else {
|
} else {
|
||||||
this->directiveSubtypeCode = 0b0000;
|
this->directiveSubtypeCode = 0b0000;
|
||||||
@ -17,16 +17,16 @@ cfdp::ConditionCode AckInfo::getAckedConditionCode() const { return ackedConditi
|
|||||||
|
|
||||||
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) {
|
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) {
|
||||||
this->ackedConditionCode = ackedConditionCode;
|
this->ackedConditionCode = ackedConditionCode;
|
||||||
if (ackedDirective == cfdp::FileDirective::FINISH) {
|
if (ackedDirective == cfdp::FileDirectives::FINISH) {
|
||||||
this->directiveSubtypeCode = 0b0001;
|
this->directiveSubtypeCode = 0b0001;
|
||||||
} else {
|
} else {
|
||||||
this->directiveSubtypeCode = 0b0000;
|
this->directiveSubtypeCode = 0b0000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::FileDirective AckInfo::getAckedDirective() const { return ackedDirective; }
|
cfdp::FileDirectives AckInfo::getAckedDirective() const { return ackedDirective; }
|
||||||
|
|
||||||
void AckInfo::setAckedDirective(cfdp::FileDirective ackedDirective) {
|
void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective) {
|
||||||
this->ackedDirective = ackedDirective;
|
this->ackedDirective = ackedDirective;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
class AckInfo {
|
class AckInfo {
|
||||||
public:
|
public:
|
||||||
AckInfo();
|
AckInfo();
|
||||||
AckInfo(cfdp::FileDirective ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
||||||
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0);
|
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0);
|
||||||
|
|
||||||
cfdp::ConditionCode getAckedConditionCode() const;
|
cfdp::ConditionCode getAckedConditionCode() const;
|
||||||
void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode);
|
void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode);
|
||||||
|
|
||||||
cfdp::FileDirective getAckedDirective() const;
|
cfdp::FileDirectives getAckedDirective() const;
|
||||||
void setAckedDirective(cfdp::FileDirective ackedDirective);
|
void setAckedDirective(cfdp::FileDirectives ackedDirective);
|
||||||
|
|
||||||
uint8_t getDirectiveSubtypeCode() const;
|
uint8_t getDirectiveSubtypeCode() const;
|
||||||
void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode);
|
void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode);
|
||||||
@ -22,7 +22,7 @@ class AckInfo {
|
|||||||
void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus);
|
void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cfdp::FileDirective ackedDirective = cfdp::FileDirective::INVALID_DIRECTIVE;
|
cfdp::FileDirectives ackedDirective = cfdp::FileDirectives::INVALID_DIRECTIVE;
|
||||||
cfdp::ConditionCode ackedConditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
|
cfdp::ConditionCode ackedConditionCode = cfdp::ConditionCode::NO_CONDITION_FIELD;
|
||||||
cfdp::AckTransactionStatus transactionStatus = cfdp::AckTransactionStatus::UNDEFINED;
|
cfdp::AckTransactionStatus transactionStatus = cfdp::AckTransactionStatus::UNDEFINED;
|
||||||
uint8_t directiveSubtypeCode = 0;
|
uint8_t directiveSubtypeCode = 0;
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
37
src/fsfw/cfdp/pdu/AckPduDeserializer.cpp
Normal file
37
src/fsfw/cfdp/pdu/AckPduDeserializer.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "AckPduDeserializer.h"
|
||||||
|
|
||||||
|
AckPduDeserializer::AckPduDeserializer(const uint8_t* pduBuf, size_t maxSize, AckInfo& info)
|
||||||
|
: FileDirectiveDeserializer(pduBuf, maxSize), info(info) {}
|
||||||
|
|
||||||
|
ReturnValue_t AckPduDeserializer::parseData() {
|
||||||
|
ReturnValue_t result = FileDirectiveDeserializer::parseData();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
|
||||||
|
if (currentIdx + 2 > this->maxSize) {
|
||||||
|
return SerializeIF::BUFFER_TOO_SHORT;
|
||||||
|
}
|
||||||
|
if (not checkAndSetCodes(rawPtr[currentIdx], rawPtr[currentIdx + 1])) {
|
||||||
|
return cfdp::INVALID_ACK_DIRECTIVE_FIELDS;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AckPduDeserializer::checkAndSetCodes(uint8_t firstByte, uint8_t secondByte) {
|
||||||
|
uint8_t ackedDirective = static_cast<cfdp::FileDirectives>(firstByte >> 4);
|
||||||
|
|
||||||
|
if (ackedDirective != cfdp::FileDirectives::EOF_DIRECTIVE and
|
||||||
|
ackedDirective != cfdp::FileDirectives::FINISH) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->info.setAckedDirective(static_cast<cfdp::FileDirectives>(ackedDirective));
|
||||||
|
uint8_t directiveSubtypeCode = firstByte & 0x0f;
|
||||||
|
if (directiveSubtypeCode != 0b0000 and directiveSubtypeCode != 0b0001) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->info.setDirectiveSubtypeCode(directiveSubtypeCode);
|
||||||
|
this->info.setAckedConditionCode(static_cast<cfdp::ConditionCode>(secondByte >> 4));
|
||||||
|
this->info.setTransactionStatus(static_cast<cfdp::AckTransactionStatus>(secondByte & 0x0f));
|
||||||
|
return true;
|
||||||
|
}
|
@ -2,21 +2,18 @@
|
|||||||
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_
|
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUDESERIALIZER_H_
|
||||||
|
|
||||||
#include "AckInfo.h"
|
#include "AckInfo.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
|
||||||
|
|
||||||
class AckPduReader : public FileDirectiveReader {
|
class AckPduDeserializer : public FileDirectiveDeserializer {
|
||||||
public:
|
public:
|
||||||
AckPduReader(const uint8_t* pduBuf, size_t maxSize, AckInfo& info);
|
AckPduDeserializer(const uint8_t* pduBuf, size_t maxSize, AckInfo& info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields
|
* - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields
|
||||||
*/
|
*/
|
||||||
ReturnValue_t parseData() override;
|
ReturnValue_t parseData();
|
||||||
|
|
||||||
static bool checkAckedDirectiveField(uint8_t firstPduDataByte,
|
|
||||||
cfdp::FileDirective& ackedDirective);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode);
|
bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode);
|
@ -1,45 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
36
src/fsfw/cfdp/pdu/AckPduSerializer.cpp
Normal file
36
src/fsfw/cfdp/pdu/AckPduSerializer.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "AckPduSerializer.h"
|
||||||
|
|
||||||
|
AckPduSerializer::AckPduSerializer(AckInfo &ackInfo, PduConfig &pduConf)
|
||||||
|
: FileDirectiveSerializer(pduConf, cfdp::FileDirectives::ACK, 2), ackInfo(ackInfo) {}
|
||||||
|
|
||||||
|
size_t AckPduSerializer::getSerializedSize() const {
|
||||||
|
return FileDirectiveSerializer::getWholePduSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t AckPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const {
|
||||||
|
ReturnValue_t result =
|
||||||
|
FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
cfdp::FileDirectives ackedDirective = ackInfo.getAckedDirective();
|
||||||
|
uint8_t directiveSubtypeCode = ackInfo.getDirectiveSubtypeCode();
|
||||||
|
cfdp::ConditionCode ackedConditionCode = ackInfo.getAckedConditionCode();
|
||||||
|
cfdp::AckTransactionStatus transactionStatus = ackInfo.getTransactionStatus();
|
||||||
|
if (ackedDirective != cfdp::FileDirectives::FINISH and
|
||||||
|
ackedDirective != cfdp::FileDirectives::EOF_DIRECTIVE) {
|
||||||
|
// TODO: better returncode
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
if (*size + 2 > maxSize) {
|
||||||
|
return SerializeIF::BUFFER_TOO_SHORT;
|
||||||
|
}
|
||||||
|
**buffer = ackedDirective << 4 | directiveSubtypeCode;
|
||||||
|
*buffer += 1;
|
||||||
|
*size += 1;
|
||||||
|
**buffer = ackedConditionCode << 4 | transactionStatus;
|
||||||
|
*buffer += 1;
|
||||||
|
*size += 1;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
#ifndef FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
#ifndef FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
||||||
#define FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
#define FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_
|
||||||
|
|
||||||
#include "AckInfo.h"
|
#include "AckInfo.h"
|
||||||
#include "FileDirectiveCreator.h"
|
#include "FileDirectiveDeserializer.h"
|
||||||
#include "FileDirectiveReader.h"
|
#include "FileDirectiveSerializer.h"
|
||||||
|
|
||||||
class AckPduCreator : public FileDirectiveCreator {
|
class AckPduSerializer : public FileDirectiveSerializer {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Serializer to pack ACK PDUs
|
* @brief Serializer to pack ACK PDUs
|
||||||
@ -16,9 +16,9 @@ class AckPduCreator : public FileDirectiveCreator {
|
|||||||
* @param transactionStatus
|
* @param transactionStatus
|
||||||
* @param pduConf
|
* @param pduConf
|
||||||
*/
|
*/
|
||||||
AckPduCreator(AckInfo& ackInfo, PduConfig& pduConf);
|
AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf);
|
||||||
|
|
||||||
[[nodiscard]] size_t getSerializedSize() const override;
|
size_t getSerializedSize() const override;
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
@ -27,4 +27,4 @@ class AckPduCreator : public FileDirectiveCreator {
|
|||||||
AckInfo& ackInfo;
|
AckInfo& ackInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */
|
#endif /* FSFW_SRC_FSFW_CFDP_PDU_ACKPDUSERIALIZER_H_ */
|
@ -1,29 +1,30 @@
|
|||||||
target_sources(
|
target_sources(
|
||||||
${LIB_FSFW_NAME}
|
${LIB_FSFW_NAME}
|
||||||
PRIVATE PduConfig.cpp
|
PRIVATE PduConfig.cpp
|
||||||
HeaderCreator.cpp
|
VarLenField.cpp
|
||||||
HeaderReader.cpp
|
HeaderSerializer.cpp
|
||||||
FileDirectiveReader.cpp
|
HeaderDeserializer.cpp
|
||||||
FileDirectiveCreator.cpp
|
FileDirectiveDeserializer.cpp
|
||||||
|
FileDirectiveSerializer.cpp
|
||||||
AckInfo.cpp
|
AckInfo.cpp
|
||||||
AckPduCreator.cpp
|
AckPduSerializer.cpp
|
||||||
AckPduReader.cpp
|
AckPduDeserializer.cpp
|
||||||
EofInfo.cpp
|
EofInfo.cpp
|
||||||
EofPduCreator.cpp
|
EofPduSerializer.cpp
|
||||||
EofPduReader.cpp
|
EofPduDeserializer.cpp
|
||||||
NakInfo.cpp
|
NakInfo.cpp
|
||||||
NakPduCreator.cpp
|
NakPduSerializer.cpp
|
||||||
NakPduReader.cpp
|
NakPduDeserializer.cpp
|
||||||
FinishedInfo.cpp
|
FinishedInfo.cpp
|
||||||
FinishedPduCreator.cpp
|
FinishedPduSerializer.cpp
|
||||||
FinishedPduReader.cpp
|
FinishedPduDeserializer.cpp
|
||||||
MetadataInfo.cpp
|
MetadataInfo.cpp
|
||||||
MetadataPduCreator.cpp
|
MetadataPduSerializer.cpp
|
||||||
MetadataPduReader.cpp
|
MetadataPduDeserializer.cpp
|
||||||
KeepAlivePduCreator.cpp
|
KeepAlivePduSerializer.cpp
|
||||||
KeepAlivePduReader.cpp
|
KeepAlivePduDeserializer.cpp
|
||||||
PromptPduCreator.cpp
|
PromptPduSerializer.cpp
|
||||||
PromptPduReader.cpp
|
PromptPduDeserializer.cpp
|
||||||
FileDataCreator.cpp
|
FileDataSerializer.cpp
|
||||||
FileDataReader.cpp
|
FileDataDeserializer.cpp
|
||||||
FileDataInfo.cpp)
|
FileDataInfo.cpp)
|
||||||
|
@ -7,16 +7,16 @@
|
|||||||
|
|
||||||
struct EofInfo {
|
struct EofInfo {
|
||||||
public:
|
public:
|
||||||
explicit EofInfo(EntityIdTlv* faultLoc = nullptr);
|
EofInfo(EntityIdTlv* faultLoc = nullptr);
|
||||||
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
|
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
|
||||||
EntityIdTlv* faultLoc = nullptr);
|
EntityIdTlv* faultLoc = nullptr);
|
||||||
|
|
||||||
size_t getSerializedSize(bool fssLarge = false);
|
size_t getSerializedSize(bool fssLarge = false);
|
||||||
|
|
||||||
[[nodiscard]] uint32_t getChecksum() const;
|
uint32_t getChecksum() const;
|
||||||
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
|
cfdp::ConditionCode getConditionCode() const;
|
||||||
|
|
||||||
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
|
EntityIdTlv* getFaultLoc() const;
|
||||||
cfdp::FileSize& getFileSize();
|
cfdp::FileSize& getFileSize();
|
||||||
void setChecksum(uint32_t checksum);
|
void setChecksum(uint32_t checksum);
|
||||||
void setConditionCode(cfdp::ConditionCode conditionCode);
|
void setConditionCode(cfdp::ConditionCode conditionCode);
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
#include "EofPduReader.h"
|
#include "EofPduDeserializer.h"
|
||||||
|
|
||||||
#include "fsfw/FSFW.h"
|
#include "fsfw/FSFW.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
EofPduReader::EofPduReader(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo)
|
EofPduDeserializer::EofPduDeserializer(const uint8_t* pduBuf, size_t maxSize, EofInfo& eofInfo)
|
||||||
: FileDirectiveReader(pduBuf, maxSize), info(eofInfo) {}
|
: FileDirectiveDeserializer(pduBuf, maxSize), info(eofInfo) {}
|
||||||
|
|
||||||
ReturnValue_t EofPduReader::parseData() {
|
ReturnValue_t EofPduDeserializer::parseData() {
|
||||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
ReturnValue_t result = FileDirectiveDeserializer::parseData();
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* bufPtr = pointers.rawPtr;
|
const uint8_t* bufPtr = rawPtr;
|
||||||
size_t expectedFileFieldLen = 4;
|
size_t expectedFileFieldLen = 4;
|
||||||
if (this->getLargeFileFlag()) {
|
if (this->getLargeFileFlag()) {
|
||||||
expectedFileFieldLen = 8;
|
expectedFileFieldLen = 8;
|
||||||
}
|
}
|
||||||
size_t currentIdx = FileDirectiveReader::getHeaderSize();
|
size_t currentIdx = FileDirectiveDeserializer::getHeaderSize();
|
||||||
size_t deserLen = maxSize;
|
size_t deserLen = maxSize;
|
||||||
if (maxSize < currentIdx + 5 + expectedFileFieldLen) {
|
if (maxSize < currentIdx + 5 + expectedFileFieldLen) {
|
||||||
return SerializeIF::STREAM_TOO_SHORT;
|
return SerializeIF::STREAM_TOO_SHORT;
|
||||||
@ -31,7 +31,7 @@ ReturnValue_t EofPduReader::parseData() {
|
|||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
auto endianness = getEndianness();
|
auto endianness = getEndianness();
|
||||||
result = SerializeAdapter::deSerialize(&checksum, &bufPtr, &deserLen, endianness);
|
result = SerializeAdapter::deSerialize(&checksum, &bufPtr, &deserLen, endianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
info.setChecksum(checksum);
|
info.setChecksum(checksum);
|
||||||
@ -44,24 +44,16 @@ ReturnValue_t EofPduReader::parseData() {
|
|||||||
result = SerializeAdapter::deSerialize(&fileSizeValue, &bufPtr, &deserLen, endianness);
|
result = SerializeAdapter::deSerialize(&fileSizeValue, &bufPtr, &deserLen, endianness);
|
||||||
info.setFileSize(fileSizeValue, false);
|
info.setFileSize(fileSizeValue, false);
|
||||||
}
|
}
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (info.getConditionCode() != cfdp::ConditionCode::NO_ERROR) {
|
if (info.getConditionCode() != cfdp::ConditionCode::NO_ERROR) {
|
||||||
EntityIdTlv* tlvPtr = info.getFaultLoc();
|
EntityIdTlv* tlvPtr = info.getFaultLoc();
|
||||||
if (tlvPtr == nullptr) {
|
if (tlvPtr == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
FSFW_LOGW("{}",
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
"parseData: Ca not deserialize fault location,"
|
||||||
sif::warning << "EofPduDeserializer::parseData: Ca not deserialize fault location,"
|
" given TLV pointer invalid\n");
|
||||||
" given TLV pointer invalid"
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
<< std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning(
|
|
||||||
"EofPduDeserializer::parseData: Ca not deserialize fault location,"
|
|
||||||
" given TLV pointer invalid");
|
|
||||||
#endif
|
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
}
|
||||||
result = tlvPtr->deSerialize(&bufPtr, &deserLen, endianness);
|
result = tlvPtr->deSerialize(&bufPtr, &deserLen, endianness);
|
||||||
}
|
}
|
17
src/fsfw/cfdp/pdu/EofPduDeserializer.h
Normal file
17
src/fsfw/cfdp/pdu/EofPduDeserializer.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/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,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/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,18 +1,22 @@
|
|||||||
#include "EofPduCreator.h"
|
#include "EofPduSerializer.h"
|
||||||
|
|
||||||
#include "fsfw/FSFW.h"
|
#include "fsfw/FSFW.h"
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
EofPduCreator::EofPduCreator(PduConfig &conf, EofInfo &info)
|
EofPduSerializer::EofPduSerializer(PduConfig &conf, EofInfo &info)
|
||||||
: FileDirectiveCreator(conf, cfdp::FileDirective::EOF_DIRECTIVE, 9), info(info) {
|
: FileDirectiveSerializer(conf, cfdp::FileDirectives::EOF_DIRECTIVE, 9), info(info) {
|
||||||
setDirectiveDataFieldLen(info.getSerializedSize(HeaderCreator::getLargeFileFlag()));
|
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t EofPduCreator::getSerializedSize() const { return FileDirectiveCreator::getWholePduSize(); }
|
size_t EofPduSerializer::getSerializedSize() const {
|
||||||
|
return FileDirectiveSerializer::getWholePduSize();
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t EofPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t EofPduSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
Endianness streamEndianness) const {
|
Endianness streamEndianness) const {
|
||||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
ReturnValue_t result =
|
||||||
if (result != returnvalue::OK) {
|
FileDirectiveSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (*size + 1 > maxSize) {
|
if (*size + 1 > maxSize) {
|
||||||
@ -23,7 +27,7 @@ ReturnValue_t EofPduCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
|||||||
*size += 1;
|
*size += 1;
|
||||||
uint32_t checksum = info.getChecksum();
|
uint32_t checksum = info.getChecksum();
|
||||||
result = SerializeAdapter::serialize(&checksum, buffer, size, maxSize, streamEndianness);
|
result = SerializeAdapter::serialize(&checksum, buffer, size, maxSize, streamEndianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (info.getFileSize().isLargeFile()) {
|
if (info.getFileSize().isLargeFile()) {
|
@ -2,20 +2,18 @@
|
|||||||
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_
|
#define FSFW_SRC_FSFW_CFDP_PDU_EOFPDUSERIALIZER_H_
|
||||||
|
|
||||||
#include "EofInfo.h"
|
#include "EofInfo.h"
|
||||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
|
||||||
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
|
#include "fsfw/cfdp/tlv/EntityIdTlv.h"
|
||||||
|
|
||||||
class EofPduCreator : public FileDirectiveCreator {
|
class EofPduSerializer : public FileDirectiveSerializer {
|
||||||
public:
|
public:
|
||||||
EofPduCreator(PduConfig& conf, EofInfo& info);
|
EofPduSerializer(PduConfig& conf, EofInfo& info);
|
||||||
|
|
||||||
[[nodiscard]] size_t getSerializedSize() const override;
|
size_t getSerializedSize() const override;
|
||||||
|
|
||||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const override;
|
Endianness streamEndianness) const override;
|
||||||
|
|
||||||
using FileDirectiveCreator::serialize;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EofInfo& info;
|
EofInfo& info;
|
||||||
};
|
};
|
@ -1,27 +0,0 @@
|
|||||||
#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_ */
|
|
48
src/fsfw/cfdp/pdu/FileDataDeserializer.cpp
Normal file
48
src/fsfw/cfdp/pdu/FileDataDeserializer.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "FileDataDeserializer.h"
|
||||||
|
|
||||||
|
FileDataDeserializer::FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize,
|
||||||
|
FileDataInfo& info)
|
||||||
|
: HeaderDeserializer(pduBuf, maxSize), info(info) {}
|
||||||
|
|
||||||
|
ReturnValue_t FileDataDeserializer::parseData() {
|
||||||
|
ReturnValue_t result = HeaderDeserializer::parseData();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
size_t currentIdx = HeaderDeserializer::getHeaderSize();
|
||||||
|
const uint8_t* buf = rawPtr + currentIdx;
|
||||||
|
size_t remSize = HeaderDeserializer::getWholePduSize() - currentIdx;
|
||||||
|
if (remSize < 1) {
|
||||||
|
return SerializeIF::STREAM_TOO_SHORT;
|
||||||
|
}
|
||||||
|
if (hasSegmentMetadataFlag()) {
|
||||||
|
info.setSegmentMetadataFlag(true);
|
||||||
|
info.setRecordContinuationState(static_cast<cfdp::RecordContinuationState>((*buf >> 6) & 0b11));
|
||||||
|
size_t segmentMetadataLen = *buf & 0b00111111;
|
||||||
|
info.setSegmentMetadataLen(segmentMetadataLen);
|
||||||
|
if (remSize < segmentMetadataLen + 1) {
|
||||||
|
return SerializeIF::STREAM_TOO_SHORT;
|
||||||
|
}
|
||||||
|
if (segmentMetadataLen > 0) {
|
||||||
|
buf += 1;
|
||||||
|
remSize -= 1;
|
||||||
|
info.setSegmentMetadata(buf);
|
||||||
|
buf += segmentMetadataLen;
|
||||||
|
remSize -= segmentMetadataLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = info.getOffset().deSerialize(&buf, &remSize, this->getEndianness());
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (remSize > 0) {
|
||||||
|
info.setFileData(buf, remSize);
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializeIF::Endianness FileDataDeserializer::getEndianness() const { return endianness; }
|
||||||
|
|
||||||
|
void FileDataDeserializer::setEndianness(SerializeIF::Endianness endianness) {
|
||||||
|
this->endianness = endianness;
|
||||||
|
}
|
@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
#include "../definitions.h"
|
#include "../definitions.h"
|
||||||
#include "FileDataInfo.h"
|
#include "FileDataInfo.h"
|
||||||
#include "PduHeaderReader.h"
|
#include "HeaderDeserializer.h"
|
||||||
|
|
||||||
class FileDataReader : public PduHeaderReader {
|
class FileDataDeserializer : public HeaderDeserializer {
|
||||||
public:
|
public:
|
||||||
FileDataReader(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info);
|
FileDataDeserializer(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info);
|
||||||
|
|
||||||
ReturnValue_t parseData() override;
|
ReturnValue_t parseData();
|
||||||
[[nodiscard]] SerializeIF::Endianness getEndianness() const;
|
SerializeIF::Endianness getEndianness() const;
|
||||||
void setEndianness(SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK);
|
void setEndianness(SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK);
|
||||||
|
|
||||||
private:
|
private:
|
@ -50,23 +50,23 @@ ReturnValue_t FileDataInfo::addSegmentMetadataInfo(cfdp::RecordContinuationState
|
|||||||
this->segmentMetadataFlag = cfdp::SegmentMetadataFlag::PRESENT;
|
this->segmentMetadataFlag = cfdp::SegmentMetadataFlag::PRESENT;
|
||||||
this->recContState = recContState;
|
this->recContState = recContState;
|
||||||
if (segmentMetadataLen > 63) {
|
if (segmentMetadataLen > 63) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
this->segmentMetadata = segmentMetadata;
|
this->segmentMetadata = segmentMetadata;
|
||||||
this->segmentMetadataLen = segmentMetadataLen;
|
this->segmentMetadataLen = segmentMetadataLen;
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *FileDataInfo::getFileData(size_t *fileSize_) const {
|
const uint8_t *FileDataInfo::getFileData(size_t *fileSize) const {
|
||||||
if (fileSize_ != nullptr) {
|
if (fileSize != nullptr) {
|
||||||
*fileSize_ = this->fileSize;
|
*fileSize = this->fileSize;
|
||||||
}
|
}
|
||||||
return fileData;
|
return fileData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
|
const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen) {
|
||||||
if (segmentMetadataLen_ != nullptr) {
|
if (segmentMetadataLen != nullptr) {
|
||||||
*segmentMetadataLen_ = this->segmentMetadataLen;
|
*segmentMetadataLen = this->segmentMetadataLen;
|
||||||
}
|
}
|
||||||
return segmentMetadata;
|
return segmentMetadata;
|
||||||
}
|
}
|
||||||
|
@ -6,25 +6,25 @@
|
|||||||
|
|
||||||
class FileDataInfo {
|
class FileDataInfo {
|
||||||
public:
|
public:
|
||||||
explicit FileDataInfo(cfdp::FileSize& offset);
|
FileDataInfo(cfdp::FileSize& offset);
|
||||||
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
|
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
|
||||||
|
|
||||||
[[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
|
size_t getSerializedSize(bool largeFile = false) const;
|
||||||
|
|
||||||
cfdp::FileSize& getOffset();
|
cfdp::FileSize& getOffset();
|
||||||
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
|
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
|
||||||
void setFileData(const uint8_t* fileData, size_t fileSize);
|
void setFileData(const uint8_t* fileData, size_t fileSize);
|
||||||
|
|
||||||
[[nodiscard]] cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const;
|
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const;
|
||||||
[[nodiscard]] cfdp::SegmentationControl getSegmentationControl() const;
|
cfdp::SegmentationControl getSegmentationControl() const;
|
||||||
[[nodiscard]] cfdp::RecordContinuationState getRecordContinuationState() const;
|
cfdp::RecordContinuationState getRecordContinuationState() const;
|
||||||
void setRecordContinuationState(cfdp::RecordContinuationState recContState);
|
void setRecordContinuationState(cfdp::RecordContinuationState recContState);
|
||||||
void setSegmentationControl(cfdp::SegmentationControl segCtrl);
|
void setSegmentationControl(cfdp::SegmentationControl segCtrl);
|
||||||
|
|
||||||
[[nodiscard]] size_t getSegmentMetadataLen() const;
|
size_t getSegmentMetadataLen() const;
|
||||||
void setSegmentMetadataLen(size_t len);
|
void setSegmentMetadataLen(size_t len);
|
||||||
void setSegmentMetadata(const uint8_t* ptr);
|
void setSegmentMetadata(const uint8_t* ptr);
|
||||||
[[nodiscard]] bool hasSegmentMetadata() const;
|
bool hasSegmentMetadata() const;
|
||||||
void setSegmentMetadataFlag(bool enable);
|
void setSegmentMetadataFlag(bool enable);
|
||||||
ReturnValue_t addSegmentMetadataInfo(cfdp::RecordContinuationState recContState,
|
ReturnValue_t addSegmentMetadataInfo(cfdp::RecordContinuationState recContState,
|
||||||
const uint8_t* segmentMetadata, size_t segmentMetadataLen);
|
const uint8_t* segmentMetadata, size_t segmentMetadataLen);
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
#include "FileDataReader.h"
|
|
||||||
|
|
||||||
FileDataReader::FileDataReader(const uint8_t* pduBuf, size_t maxSize, FileDataInfo& info)
|
|
||||||
: PduHeaderReader(pduBuf, maxSize), info(info) {}
|
|
||||||
|
|
||||||
ReturnValue_t FileDataReader::parseData() {
|
|
||||||
ReturnValue_t result = PduHeaderReader::parseData();
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (hasSegmentMetadataFlag()) {
|
|
||||||
info.setSegmentMetadataFlag(true);
|
|
||||||
info.setRecordContinuationState(static_cast<cfdp::RecordContinuationState>((*buf >> 6) & 0b11));
|
|
||||||
size_t segmentMetadataLen = *buf & 0b00111111;
|
|
||||||
info.setSegmentMetadataLen(segmentMetadataLen);
|
|
||||||
if (remSize < segmentMetadataLen + 1) {
|
|
||||||
return SerializeIF::STREAM_TOO_SHORT;
|
|
||||||
}
|
|
||||||
if (segmentMetadataLen > 0) {
|
|
||||||
buf += 1;
|
|
||||||
remSize -= 1;
|
|
||||||
info.setSegmentMetadata(buf);
|
|
||||||
buf += segmentMetadataLen;
|
|
||||||
remSize -= segmentMetadataLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = info.getOffset().deSerialize(&buf, &remSize, this->getEndianness());
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (remSize > 0) {
|
|
||||||
info.setFileData(buf, remSize);
|
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SerializeIF::Endianness FileDataReader::getEndianness() const { return endianness; }
|
|
||||||
|
|
||||||
void FileDataReader::setEndianness(SerializeIF::Endianness endianness_) {
|
|
||||||
endianness = endianness_;
|
|
||||||
}
|
|
@ -1,31 +1,28 @@
|
|||||||
#include "FileDataCreator.h"
|
#include "FileDataSerializer.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
FileDataCreator::FileDataCreator(PduConfig& conf, FileDataInfo& info)
|
FileDataSerializer::FileDataSerializer(PduConfig& conf, FileDataInfo& info)
|
||||||
: HeaderCreator(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()), info(info) {
|
: HeaderSerializer(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()),
|
||||||
|
info(info) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDataCreator::update() {
|
void FileDataSerializer::update() {
|
||||||
this->setSegmentMetadataFlag(info.getSegmentMetadataFlag());
|
this->setSegmentMetadataFlag(info.getSegmentMetadataFlag());
|
||||||
this->setSegmentationControl(info.getSegmentationControl());
|
this->setSegmentationControl(info.getSegmentationControl());
|
||||||
setPduDataFieldLen(info.getSerializedSize(this->getLargeFileFlag()));
|
setPduDataFieldLen(info.getSerializedSize(this->getLargeFileFlag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
ReturnValue_t FileDataSerializer::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
Endianness streamEndianness) const {
|
Endianness streamEndianness) const {
|
||||||
if (buffer == nullptr or size == nullptr) {
|
ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||||
return returnvalue::FAILED;
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
}
|
|
||||||
if (*size + getSerializedSize() > maxSize) {
|
|
||||||
return SerializeIF::BUFFER_TOO_SHORT;
|
|
||||||
}
|
|
||||||
ReturnValue_t result = HeaderCreator::serialize(buffer, size, maxSize, streamEndianness);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (*size + this->getSerializedSize() > maxSize) {
|
||||||
|
return SerializeIF::BUFFER_TOO_SHORT;
|
||||||
|
}
|
||||||
const uint8_t* readOnlyPtr = nullptr;
|
const uint8_t* readOnlyPtr = nullptr;
|
||||||
if (this->hasSegmentMetadataFlag()) {
|
if (this->hasSegmentMetadataFlag()) {
|
||||||
size_t segmentMetadataLen = info.getSegmentMetadataLen();
|
size_t segmentMetadataLen = info.getSegmentMetadataLen();
|
||||||
@ -39,7 +36,7 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
|
|||||||
}
|
}
|
||||||
cfdp::FileSize& offset = info.getOffset();
|
cfdp::FileSize& offset = info.getOffset();
|
||||||
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||||
if (result != returnvalue::OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
size_t fileSize = 0;
|
size_t fileSize = 0;
|
||||||
@ -50,9 +47,9 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
|
|||||||
std::memcpy(*buffer, readOnlyPtr, fileSize);
|
std::memcpy(*buffer, readOnlyPtr, fileSize);
|
||||||
*buffer += fileSize;
|
*buffer += fileSize;
|
||||||
*size += fileSize;
|
*size += fileSize;
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FileDataCreator::getSerializedSize() const {
|
size_t FileDataSerializer::getSerializedSize() const {
|
||||||
return HeaderCreator::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag());
|
return HeaderSerializer::getSerializedSize() + info.getSerializedSize(this->getLargeFileFlag());
|
||||||
}
|
}
|
23
src/fsfw/cfdp/pdu/FileDataSerializer.h
Normal file
23
src/fsfw/cfdp/pdu/FileDataSerializer.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
|
||||||
|
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATASERIALIZER_H_
|
||||||
|
|
||||||
|
#include "../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_ */
|
@ -1,39 +0,0 @@
|
|||||||
#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; }
|
|
@ -1,34 +0,0 @@
|
|||||||
#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_ */
|
|
49
src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp
Normal file
49
src/fsfw/cfdp/pdu/FileDirectiveDeserializer.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include "FileDirectiveDeserializer.h"
|
||||||
|
|
||||||
|
FileDirectiveDeserializer::FileDirectiveDeserializer(const uint8_t *pduBuf, size_t maxSize)
|
||||||
|
: HeaderDeserializer(pduBuf, maxSize) {}
|
||||||
|
|
||||||
|
cfdp::FileDirectives FileDirectiveDeserializer::getFileDirective() const { return fileDirective; }
|
||||||
|
|
||||||
|
ReturnValue_t FileDirectiveDeserializer::parseData() {
|
||||||
|
ReturnValue_t result = HeaderDeserializer::parseData();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (this->getPduDataFieldLen() < 1) {
|
||||||
|
return cfdp::INVALID_PDU_DATAFIELD_LEN;
|
||||||
|
}
|
||||||
|
if (FileDirectiveDeserializer::getWholePduSize() > maxSize) {
|
||||||
|
return SerializeIF::STREAM_TOO_SHORT;
|
||||||
|
}
|
||||||
|
size_t currentIdx = HeaderDeserializer::getHeaderSize();
|
||||||
|
if (not checkFileDirective(rawPtr[currentIdx])) {
|
||||||
|
return cfdp::INVALID_DIRECTIVE_FIELDS;
|
||||||
|
}
|
||||||
|
setFileDirective(static_cast<cfdp::FileDirectives>(rawPtr[currentIdx]));
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FileDirectiveDeserializer::getHeaderSize() const {
|
||||||
|
// return size of header plus the directive byte
|
||||||
|
return HeaderDeserializer::getHeaderSize() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileDirectiveDeserializer::checkFileDirective(uint8_t rawByte) {
|
||||||
|
if (rawByte < cfdp::FileDirectives::EOF_DIRECTIVE or
|
||||||
|
(rawByte > cfdp::FileDirectives::PROMPT and rawByte != cfdp::FileDirectives::KEEP_ALIVE)) {
|
||||||
|
// Invalid directive field. TODO: Custom returnvalue
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDirectiveDeserializer::setFileDirective(cfdp::FileDirectives fileDirective) {
|
||||||
|
this->fileDirective = fileDirective;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDirectiveDeserializer::setEndianness(SerializeIF::Endianness endianness) {
|
||||||
|
this->endianness = endianness;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializeIF::Endianness FileDirectiveDeserializer::getEndianness() const { return endianness; }
|
@ -2,7 +2,7 @@
|
|||||||
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_
|
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_
|
||||||
|
|
||||||
#include "../definitions.h"
|
#include "../definitions.h"
|
||||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
#include "fsfw/cfdp/pdu/HeaderDeserializer.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class is used to deserialize a PDU file directive header from raw memory.
|
* @brief This class is used to deserialize a PDU file directive header from raw memory.
|
||||||
@ -11,27 +11,28 @@
|
|||||||
* This is a zero-copy implementation and #parseData needs to be called to ensure the data is
|
* This is a zero-copy implementation and #parseData needs to be called to ensure the data is
|
||||||
* valid.
|
* valid.
|
||||||
*/
|
*/
|
||||||
class FileDirectiveReader : public PduHeaderReader {
|
class FileDirectiveDeserializer : public HeaderDeserializer {
|
||||||
public:
|
public:
|
||||||
FileDirectiveReader(const uint8_t* pduBuf, size_t maxSize);
|
FileDirectiveDeserializer(const uint8_t* pduBuf, size_t maxSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This needs to be called before accessing the PDU fields to avoid segmentation faults.
|
* This needs to be called before accessing the PDU fields to avoid segmentation faults.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t parseData() override;
|
virtual ReturnValue_t parseData();
|
||||||
[[nodiscard]] size_t getHeaderSize() const override;
|
size_t getHeaderSize() const;
|
||||||
|
|
||||||
[[nodiscard]] cfdp::FileDirective getFileDirective() const;
|
cfdp::FileDirectives getFileDirective() const;
|
||||||
|
|
||||||
void setEndianness(SerializeIF::Endianness endianness);
|
void setEndianness(SerializeIF::Endianness endianness);
|
||||||
[[nodiscard]] SerializeIF::Endianness getEndianness() const;
|
SerializeIF::Endianness getEndianness() const;
|
||||||
static bool checkFileDirective(uint8_t rawByte);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool checkFileDirective(uint8_t rawByte);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setFileDirective(cfdp::FileDirective fileDirective);
|
void setFileDirective(cfdp::FileDirectives fileDirective);
|
||||||
cfdp::FileDirective fileDirective = cfdp::FileDirective::INVALID_DIRECTIVE;
|
cfdp::FileDirectives fileDirective = cfdp::FileDirectives::INVALID_DIRECTIVE;
|
||||||
SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK;
|
SerializeIF::Endianness endianness = SerializeIF::Endianness::NETWORK;
|
||||||
};
|
};
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
#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; }
|
|
38
src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp
Normal file
38
src/fsfw/cfdp/pdu/FileDirectiveSerializer.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "FileDirectiveSerializer.h"
|
||||||
|
|
||||||
|
FileDirectiveSerializer::FileDirectiveSerializer(PduConfig &pduConf,
|
||||||
|
cfdp::FileDirectives directiveCode,
|
||||||
|
size_t directiveParamFieldLen)
|
||||||
|
: HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, directiveParamFieldLen + 1),
|
||||||
|
directiveCode(directiveCode) {}
|
||||||
|
|
||||||
|
size_t FileDirectiveSerializer::getSerializedSize() const {
|
||||||
|
return HeaderSerializer::getSerializedSize() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FileDirectiveSerializer::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const {
|
||||||
|
if (buffer == nullptr or size == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
if (FileDirectiveSerializer::getWholePduSize() > maxSize) {
|
||||||
|
return BUFFER_TOO_SHORT;
|
||||||
|
}
|
||||||
|
ReturnValue_t result = HeaderSerializer::serialize(buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*size >= maxSize) {
|
||||||
|
return BUFFER_TOO_SHORT;
|
||||||
|
}
|
||||||
|
**buffer = directiveCode;
|
||||||
|
*buffer += 1;
|
||||||
|
*size += 1;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDirectiveSerializer::setDirectiveDataFieldLen(size_t len) {
|
||||||
|
// Set length of data field plus 1 byte for the directive octet
|
||||||
|
HeaderSerializer::setPduDataFieldLen(len + 1);
|
||||||
|
}
|
28
src/fsfw/cfdp/pdu/FileDirectiveSerializer.h
Normal file
28
src/fsfw/cfdp/pdu/FileDirectiveSerializer.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_
|
||||||
|
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_
|
||||||
|
|
||||||
|
#include "fsfw/cfdp/pdu/HeaderSerializer.h"
|
||||||
|
|
||||||
|
class FileDirectiveSerializer : public HeaderSerializer {
|
||||||
|
public:
|
||||||
|
FileDirectiveSerializer(PduConfig& pduConf, cfdp::FileDirectives directiveCode,
|
||||||
|
size_t directiveParamFieldLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This only returns the size of the PDU header + 1 for the directive code octet.
|
||||||
|
* Use FileDirectiveSerializer::getWholePduSize to get the full packet length, assuming
|
||||||
|
* the length fields was set correctly
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
size_t getSerializedSize() const override;
|
||||||
|
|
||||||
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const override;
|
||||||
|
|
||||||
|
void setDirectiveDataFieldLen(size_t len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
cfdp::FileDirectives directiveCode = cfdp::FileDirectives::INVALID_DIRECTIVE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVESERIALIZER_H_ */
|
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
FinishedInfo::FinishedInfo() {}
|
FinishedInfo::FinishedInfo() {}
|
||||||
|
|
||||||
FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode, cfdp::FileDeliveryCode deliveryCode,
|
FinishedInfo::FinishedInfo(cfdp::ConditionCode conditionCode,
|
||||||
cfdp::FileDeliveryStatus fileStatus)
|
cfdp::FinishedDeliveryCode deliveryCode,
|
||||||
|
cfdp::FinishedFileStatus fileStatus)
|
||||||
: conditionCode(conditionCode), deliveryCode(deliveryCode), fileStatus(fileStatus) {}
|
: conditionCode(conditionCode), deliveryCode(deliveryCode), fileStatus(fileStatus) {}
|
||||||
|
|
||||||
size_t FinishedInfo::getSerializedSize() const {
|
size_t FinishedInfo::getSerializedSize() const {
|
||||||
@ -45,14 +46,14 @@ ReturnValue_t FinishedInfo::setFilestoreResponsesArray(FilestoreResponseTlv** fs
|
|||||||
if (maxFsResponsesLen != nullptr) {
|
if (maxFsResponsesLen != nullptr) {
|
||||||
this->fsResponsesMaxLen = *maxFsResponsesLen;
|
this->fsResponsesMaxLen = *maxFsResponsesLen;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FinishedInfo::getFilestoreResonses(FilestoreResponseTlv*** fsResponses,
|
ReturnValue_t FinishedInfo::getFilestoreResonses(FilestoreResponseTlv*** fsResponses,
|
||||||
size_t* fsResponsesLen,
|
size_t* fsResponsesLen,
|
||||||
size_t* fsResponsesMaxLen) {
|
size_t* fsResponsesMaxLen) {
|
||||||
if (fsResponses == nullptr) {
|
if (fsResponses == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
*fsResponses = this->fsResponses;
|
*fsResponses = this->fsResponses;
|
||||||
if (fsResponsesLen != nullptr) {
|
if (fsResponsesLen != nullptr) {
|
||||||
@ -61,7 +62,7 @@ ReturnValue_t FinishedInfo::getFilestoreResonses(FilestoreResponseTlv*** fsRespo
|
|||||||
if (fsResponsesMaxLen != nullptr) {
|
if (fsResponsesMaxLen != nullptr) {
|
||||||
*fsResponsesMaxLen = this->fsResponsesMaxLen;
|
*fsResponsesMaxLen = this->fsResponsesMaxLen;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinishedInfo::setFaultLocation(EntityIdTlv* faultLocation) {
|
void FinishedInfo::setFaultLocation(EntityIdTlv* faultLocation) {
|
||||||
@ -70,10 +71,10 @@ void FinishedInfo::setFaultLocation(EntityIdTlv* faultLocation) {
|
|||||||
|
|
||||||
ReturnValue_t FinishedInfo::getFaultLocation(EntityIdTlv** faultLocation) {
|
ReturnValue_t FinishedInfo::getFaultLocation(EntityIdTlv** faultLocation) {
|
||||||
if (this->faultLocation == nullptr) {
|
if (this->faultLocation == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
*faultLocation = this->faultLocation;
|
*faultLocation = this->faultLocation;
|
||||||
return returnvalue::OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::ConditionCode FinishedInfo::getConditionCode() const { return conditionCode; }
|
cfdp::ConditionCode FinishedInfo::getConditionCode() const { return conditionCode; }
|
||||||
@ -82,13 +83,13 @@ void FinishedInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
|
|||||||
this->conditionCode = conditionCode;
|
this->conditionCode = conditionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::FileDeliveryCode FinishedInfo::getDeliveryCode() const { return deliveryCode; }
|
cfdp::FinishedDeliveryCode FinishedInfo::getDeliveryCode() const { return deliveryCode; }
|
||||||
|
|
||||||
void FinishedInfo::setDeliveryCode(cfdp::FileDeliveryCode deliveryCode) {
|
void FinishedInfo::setDeliveryCode(cfdp::FinishedDeliveryCode deliveryCode) {
|
||||||
this->deliveryCode = deliveryCode;
|
this->deliveryCode = deliveryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfdp::FileDeliveryStatus FinishedInfo::getFileStatus() const { return fileStatus; }
|
cfdp::FinishedFileStatus FinishedInfo::getFileStatus() const { return fileStatus; }
|
||||||
|
|
||||||
void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) {
|
void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) {
|
||||||
this->fsResponsesLen = fsResponsesLen;
|
this->fsResponsesLen = fsResponsesLen;
|
||||||
@ -96,6 +97,6 @@ void FinishedInfo::setFilestoreResponsesArrayLen(size_t fsResponsesLen) {
|
|||||||
|
|
||||||
size_t FinishedInfo::getFsResponsesLen() const { return fsResponsesLen; }
|
size_t FinishedInfo::getFsResponsesLen() const { return fsResponsesLen; }
|
||||||
|
|
||||||
void FinishedInfo::setFileStatus(cfdp::FileDeliveryStatus fileStatus) {
|
void FinishedInfo::setFileStatus(cfdp::FinishedFileStatus fileStatus) {
|
||||||
this->fileStatus = fileStatus;
|
this->fileStatus = fileStatus;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user