Compare commits

..

42 Commits

Author SHA1 Message Date
2ca9eb4204 WIP 2023-02-09 15:54:32 +01:00
45b686a028 Merge remote-tracking branch 'origin/development' into mohr/windows 2023-02-08 22:08:55 +01:00
329e80e7ee enabling win unittests 2023-02-08 14:08:09 +01:00
3772db4753 group id conflict 2023-02-08 11:46:39 +01:00
3d13ead275 moved to newer wine 2023-02-07 21:56:06 +01:00
e7e9ce4baf one more warning suppressed in MSVC 2023-02-07 13:25:13 +01:00
e4c11f8107 fixing problem which causes a looooooong hang in CI by illegaly overrideing internal CMake Variable 2023-02-07 12:26:44 +01:00
270622a5f1 no coverage with clang so far; using correct path to push coverage data 2023-02-06 22:49:37 +01:00
4b52e5bec4 windows and clang builds in CI 2023-02-06 22:45:00 +01:00
efc2773f84 docker update for windows 2023-02-06 16:29:53 +01:00
87bb29a66a compiler parameter tuning 2023-02-06 13:10:50 +01:00
45963b2064 tuning win build 2023-01-27 17:26:03 +01:00
bc312243df clang -Weverything -Wno-gnu-anonymous-struct 2023-01-27 00:50:10 +01:00
9589d702dd windows unittests succeed 2023-01-26 18:14:35 +01:00
c66fab90f9 filesystem stuff works on linux/host 2023-01-26 17:05:25 +01:00
3e8446ba8b windows building again 2023-01-26 15:30:23 +01:00
e37af4fe70 format 2023-01-26 13:40:44 +01:00
941bf61f28 constant number of assertions in unittests 2023-01-26 13:26:11 +01:00
70fd9ff3e5 fixed impact of windows fixes on other builds 2023-01-26 12:33:39 +01:00
81c5b2ec95 Merge branch 'mohr/rtems' into windows 2023-01-26 11:55:16 +01:00
7426e10f82 clocks suck a little less 2023-01-26 11:33:40 +01:00
uli
123c81777a clocks suck 2023-01-26 00:01:40 +01:00
dcc28622a5 windows compiles, some unittests give exceptions 2023-01-25 23:54:46 +01:00
6d85fa155e cleaning up unittest build 2023-01-20 16:05:04 +01:00
e6af6200ae updating CI 2023-01-19 17:32:23 +01:00
5ca3e83934 working on rtems CI build 2023-01-19 16:46:43 +01:00
6adabb059a fixing rtems cmake config 2023-01-19 16:27:10 +01:00
5d0a5cd201 exiting qemu nonzero when tests fail 2023-01-19 14:47:40 +01:00
adb8483bb0 unittests for rtems working 2023-01-19 14:24:33 +01:00
fdfdce2fb0 compiling, crashing when run 2023-01-18 00:25:25 +01:00
90efb132d0 fixing rebase error 2023-01-16 12:41:23 +01:00
fe9804d922 format 2023-01-16 12:35:14 +01:00
a0eae66c35 checking if this helps docker build 2023-01-16 12:32:16 +01:00
e131480d5f two errors found by valgrind 2023-01-16 12:32:15 +01:00
90bafbb6de typos in Jenkinsfile 2023-01-16 12:31:54 +01:00
47d85fb61c finished freertos unittests, valgrind not happy yet 2023-01-16 12:31:53 +01:00
39dad5f45b unittests running but failing 2023-01-16 12:31:53 +01:00
a993c4e0d4 adding linux ci and fixing problems 2023-01-16 12:31:53 +01:00
fe9cc20d00 make get const 2023-01-16 12:31:53 +01:00
552a12a6ad updates for source sequence counter 2023-01-16 12:31:47 +01:00
13639feec6 FreeRTOS unittests building (but not running) 2023-01-16 12:30:36 +01:00
654de0f586 WIP 2023-01-16 12:30:36 +01:00
393 changed files with 3564 additions and 7800 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
# PyCharm and CLion # PyCharm and CLion
.idea/* /.idea/*
!/.idea/runConfigurations !/.idea/runConfigurations
!/.idea/cmake.xml !/.idea/cmake.xml
!/.idea/codeStyles !/.idea/codeStyles

3
.gitmodules vendored
View File

@ -0,0 +1,3 @@
[submodule "automation/msvc-wine"]
path = automation/msvc-wine
url = https://github.com/mstorsjo/msvc-wine

8
.idea/cmake.xml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Test" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON" NO_GENERATOR="true" />
</configurations>
</component>
</project>

View File

@ -8,86 +8,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
## Fixes # [v6.0.0]
- FreshDeviceHandlerBase did not initialize the fdirInstance
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
data with a size limited only by the size of `size_t`.
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
number fields stored the actual length of the field instead of the length minus 1 like specified
in the CFDP standard.
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field.
- Relative timeshift in the PUS time service.
## Changed
- The PUS time service now dumps the time before setting a new time and after having set the
time.
- HK generation is now countdown based.
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
- Health functions are virtual now.
- PUS Service Base request queue depth and maximum number of handled packets per cycle is now
configurable.
## Added
- `EventManager`: Add function to print all listeners.
## Changed
- `EventManager`: Queue depth is configurable now
# [v6.0.0] 2023-02-10
## Fixes ## Fixes
- Mode Service: Add allowed subservice
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
subservice not working properly.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
- Memory leak fixes for the TCP/IP TMTC bridge.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval - `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
seconds instead of uptime. seconds instead of uptime.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously, - HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
only the X scaling factor was used. only the X scaling factor was used.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity - DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing. to false correctly because the `read` and `write` calls were missing.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead - PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
of the correct unsegmented flags (0b11) as specified in the standard. of the correct unsegmented flags (0b11) as specified in the standard.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
- TC Scheduler Service 11: Add size and CRC check for contained TC. - TC Scheduler Service 11: Add size and CRC check for contained TC.
Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
- Only delete health table entry in `HealthHelper` destructor if - Only delete health table entry in `HealthHelper` destructor if
health table was set. health table was set.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator. - I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
Also properly reset the reply size for successfull transfers and erroneous transfers. Also properly reset the reply size for successfull transfers and erroneous transfers.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
@ -97,43 +35,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `TcpTmTcServer.cpp`: The server was actually not able to handle - `TcpTmTcServer.cpp`: The server was actually not able to handle
CCSDS packets which were clumped together. This has been fixed now. CCSDS packets which were clumped together. This has been fixed now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- various fixes related to linux Unittests and memory leaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
- small fix to allow teardown handling
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
- fix compiler warning for fixed array list copy ctor
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
- missing include
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
- defaultconfig did not build anymore
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
- hotfix
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
- small fix for helper
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
- missing retval conv
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
- DHB Countdown Bug
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
- doc corrections
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
- better error printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
- include correction
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
- better warning for missing include paths
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
- Service 11 regression
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
## Added ## Added
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice. - `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT` - `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
option on the TCP server. CTOR prototype has changed and expects an explicit option on the TCP server. CTOR prototype has changed and expects an explicit
@ -145,36 +49,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
- Add new `UnsignedByteField` class - Add new `UnsignedByteField` class
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
- publish documentation for development and master branch
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
- Add Linux HAL options
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
- Expand SerializeIF
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
- PUS Service 11: Additional Safety Check
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
- improvements for auto-formatter script
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
- provide a weak print char impl
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
## Removed
- now that doc server is up, remove markdown files
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
- remove bsp specific code
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
## Changes ## Changes
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
`HealthServiceCfg` now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now - `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
- Moved some container returnvalues to dedicated header and namespace - Moved some container returnvalues to dedicated header and namespace
so they can be used without template specification. to they can be used without template specification.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
- Remove default secondary header argument for - Remove default secondary header argument for
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and `uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
@ -204,41 +85,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects - `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*` a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
- 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
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`: - Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
- Make functions `const` where it makes sense - Make functions `const` where it makes sense
- Add `const char* getName const` abstract function - Add `const char* getName const` abstract function
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
- Generic TMTC Bridge Update - Move some generic `StorageManagerIF` implementations from `LocalPool` to
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734 interface itself so it can be re-used more easily. Also add new
- comment tweak to event parser can read everything abstract function `bool hasDataAtId(store_address_t storeId) const`.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
- CMakeLists file updates
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
- improve srv20 error messages
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
- I2C Linux: remove duplicate printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
- printout handling improvements
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
- vec getter, reset for content
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
- updates for source sequence counter
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
- SP reader getPacketData is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
- refactoring of serial drivers for linux
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
- Local Pool Update Remove Add Data Ignore Fault Argument
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
- Switch to new documentation server
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
- Windows Tweaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
- Refactor Local Pool API
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
- group MGM data in local pool vectors
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
## CFDP ## CFDP
@ -258,7 +116,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implementation without an extra component implementation without an extra component
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
# [v5.0.0] 2022-07-25 # [v5.0.0] 25.07.2022
## Changes ## Changes

View File

@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
# Version file handling # # Version file handling #
# ############################################################################## # ##############################################################################
set(FSFW_VERSION_IF_GIT_FAILS 6) set(FSFW_VERSION_IF_GIT_FAILS 5)
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)
@ -64,6 +64,13 @@ elseif(${CMAKE_CXX_STANDARD} LESS 17)
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support") "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Manually tweak MSVC to emit (about) the same warnings as clang and gcc on linux
# needs to be done here using add_compile_definitions() (as opposed to target_compile_definitions()) to be available for all binaries and libraries
add_compile_options("/permissive-" /wd4267 /wd4244 /wd4244 /wd4305 /wd4805 /wd4267 /wd4646 /wd4065 /wd4996 /Dand=&& /Dor=|| /Dnot=!)
add_compile_definitions(NOMINMAX)
endif()
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw") set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
set(FSFW_ETL_LIB_NAME etl) set(FSFW_ETL_LIB_NAME etl)
@ -72,7 +79,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
20 20
CACHE STRING "ETL library major version requirement") CACHE STRING "ETL library major version requirement")
set(FSFW_ETL_LIB_VERSION set(FSFW_ETL_LIB_VERSION
${FSFW_ETL_LIB_MAJOR_VERSION}.36.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_ETL_LINK_TARGET etl::etl)
@ -80,7 +87,7 @@ 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}.3.2 v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
CACHE STRING "Catch2 library exact version requirement") CACHE STRING "Catch2 library exact version requirement")
# Keep this off by default for now. See PR: # Keep this off by default for now. See PR:
@ -158,7 +165,7 @@ if(FSFW_BUILD_TESTS)
if(NOT Catch2_FOUND) if(NOT Catch2_FOUND)
message( message(
STATUS STATUS
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent." "${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
) )
include(FetchContent) include(FetchContent)
@ -174,6 +181,27 @@ if(FSFW_BUILD_TESTS)
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h) configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h) configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
if(FSFW_OSAL MATCHES "freertos")
message(STATUS "${MSG_PREFIX} Downloading FreeRTOS with FetchContent")
include(FetchContent)
set(FreeRTOS_PORT posix)
FetchContent_Declare(
FreeRTOS
GIT_REPOSITORY https://egit.irs.uni-stuttgart.de/fsfw/FreeRTOS-LTS
GIT_TAG develop
GIT_SUBMODULES FreeRTOS/FreeRTOS-Kernel)
FetchContent_MakeAvailable(FreeRTOS)
set(LIB_OS_NAME FreeRTOS)
target_include_directories(FreeRTOS PUBLIC unittests/testcfg/freertos)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(FreeRTOS PRIVATE ${CMAKE_THREAD_LIBS_INIT})
endif()
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)
@ -201,8 +229,8 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND) if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message( message(
STATUS STATUS
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent." "${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
) "etl with FindPackage")
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
@ -226,6 +254,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
# 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()
endif() endif()
set(FSFW_CORE_INC_PATH "inc") set(FSFW_CORE_INC_PATH "inc")
@ -360,6 +389,9 @@ if(FSFW_BUILD_TESTS)
endif() endif()
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
${LIB_FSFW_NAME}) ${LIB_FSFW_NAME})
if(FSFW_OSAL MATCHES "freertos")
target_link_libraries(${FSFW_TEST_TGT} PRIVATE FreeRTOS)
endif()
endif() endif()
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If # The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
@ -447,8 +479,47 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(COMPILER_FLAGS "/permissive-") set(FSFW_WARNING_FLAGS
-Weverything
-Wno-gnu-anonymous-struct
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-covered-switch-default
-Wno-padded
-Wno-documentation
-Wno-weak-vtables
-Wno-c++98-c++11-compat-binary-literal
-Wno-documentation-unknown-command
-Wno-reserved-macro-identifier
-Wno-global-constructors
-Wno-reserved-identifier
-Wno-switch-enum
-Werror
#WTH?
-Wno-ctad-maybe-unsupported
#WIP
-Wno-undefined-func-template
-Wno-suggest-destructor-override
-Wno-suggest-override
-Wno-inconsistent-missing-destructor-override
-Wno-extra-semi
#could be useful:
-Wno-sign-conversion
-Wno-implicit-int-conversion
-Wno-shorten-64-to-32
-Wno-double-promotion
-Wno-float-conversion
-Wno-implicit-int-float-conversion
-Wno-implicit-float-conversion
-Wno-shadow-field-in-constructor
-Wno-shadow-field
-Wno-shadow
-Wno-unused-parameter
)
endif() endif()
# Required include paths to compile the FSFW # Required include paths to compile the FSFW

View File

@ -5,7 +5,7 @@ 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 rsync RUN apt-get --yes install ca-certificates clang cmake doxygen g++ gcc git graphviz iputils-ping lcov make msitools nano ninja-build pip python3 python3-simplejson python3-six qemu-system-arm rsync valgrind wget winbind
RUN python3 -m pip install sphinx breathe RUN python3 -m pip install sphinx breathe
@ -21,9 +21,37 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
cmake -B build . && \ cmake -B build . && \
cmake --install build/ cmake --install build/
# install our own rtems build
RUN wget -qO- https://buggy.irs.uni-stuttgart.de/rtems_releases/rtems6-12.2.1.tar.bz2 | tar -xj -C /opt/
ENV PATH="$PATH:/opt/rtems/6/bin"
# install modern wine for MSVC, removing a conflicting file
RUN dpkg --add-architecture i386 && \
mkdir -pm755 /etc/apt/keyrings && \
wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key && \
wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/focal/winehq-focal.sources && \
apt-get update && \
apt-get --yes install winehq-stable
# silence wine
ENV WINEDEBUG=-all
# install MSVC using https://github.com/mstorsjo/msvc-wine
# see msvc-wine/LICENSE.txt
COPY msvc-wine/lowercase msvc-wine/fixinclude msvc-wine/install.sh msvc-wine/vsdownload.py ./
COPY msvc-wine/wrappers/* ./wrappers/
RUN PYTHONUNBUFFERED=1 ./vsdownload.py --accept-license --dest /opt/msvc && \
./install.sh /opt/msvc && \
rm lowercase fixinclude install.sh vsdownload.py && \
rm -rf wrappers
RUN wine64 wineboot --init && \
while pgrep wineserver > /dev/null; do sleep 1; done
#ssh needs a valid user to work #ssh needs a valid user to work
RUN adduser --uid 114 jenkins RUN addgroup -q --gid 117 jenkins && adduser -q --uid 114 --gid 117 jenkins
#add documentation server to known hosts #add documentation server to known hosts
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts

118
automation/Jenkinsfile vendored
View File

@ -2,86 +2,72 @@ pipeline {
environment { environment {
BUILDDIR_HOST = 'cmake-build-tests-host' BUILDDIR_HOST = 'cmake-build-tests-host'
BUILDDIR_LINUX = 'cmake-build-tests-linux' BUILDDIR_LINUX = 'cmake-build-tests-linux'
BUILDDIR_FREERTOS = 'cmake-build-tests-freertos'
BUILDDIR_RTEMS = 'cmake-build-tests-rtems'
BUILDDIR_WIN = 'cmake-build-tests-windows'
DOCDDIR = 'cmake-build-documentation' DOCDDIR = 'cmake-build-documentation'
} }
agent { agent {
docker { docker {
image 'fsfw-ci:d6' image 'fsfw-ci:d9'
args '--network host --sysctl fs.mqueue.msg_max=100' args '--network host --sysctl fs.mqueue.msg_max=100'
} }
} }
stages { stages {
stage('Host') { stage('Host-clang') {
stages{ steps {
stage('Clean') { sh 'rm -rf $BUILDDIR_HOST'
steps {
sh 'rm -rf $BUILDDIR_HOST' dir(BUILDDIR_HOST) {
} sh 'CC=clang CXX=clang++ cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
} sh 'cmake --build . -j4'
stage('Configure') { sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
steps {
dir(BUILDDIR_HOST) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
}
}
}
stage('Build') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake --build . -j4'
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR_HOST) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
} }
} }
} }
stage('Linux') { stage('Linux-gcc') {
stages{ steps {
stage('Clean') { sh 'rm -rf $BUILDDIR_LINUX'
steps {
sh 'rm -rf $BUILDDIR_LINUX' dir(BUILDDIR_LINUX) {
} sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4'
sh 'cmake --build . -- fsfw-tests_coverage -j4'
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
} }
stage('Configure') { }
steps { }
dir(BUILDDIR_LINUX) { stage('FreeRTOS-gcc') {
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..' steps {
} sh 'rm -rf $BUILDDIR_FREERTOS'
}
dir(BUILDDIR_FREERTOS) {
sh 'cmake -DFSFW_OSAL=freertos -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4'
sh './fsfw-tests'
//sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
} }
stage('Build') { }
steps { }
dir(BUILDDIR_LINUX) { stage('rtems-gcc') {
sh 'cmake --build . -j4' steps {
} sh 'rm -rf $BUILDDIR_RTEMS'
}
dir(BUILDDIR_RTEMS) {
sh 'cmake -DFSFW_OSAL=rtems -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=../unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake ..'
sh 'cmake --build . -j4'
sh 'qemu-system-aarch64 -no-reboot -nographic -serial mon:stdio -semihosting -machine virt,gic-version=3 -cpu cortex-a72 -m 4000 -kernel fsfw-tests'
} }
stage('Unittests') { }
steps { }
dir(BUILDDIR_LINUX) { stage('Host-msvc') {
sh 'cmake --build . -- fsfw-tests_coverage -j4' steps {
} sh 'rm -rf $BUILDDIR_WIN'
}
} dir(BUILDDIR_WIN) {
stage('Valgrind') { sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../unittests/testcfg/windows/cmake/x64-windows-toolchain.cmake -GNinja ..'
steps { sh 'cmake --build . -j4'
dir(BUILDDIR_LINUX) { sh 'wine64 fsfw-tests.exe'
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
} }
} }
} }

1
automation/msvc-wine Submodule

Submodule automation/msvc-wine added at 2d2d7db0b5

View File

@ -51,10 +51,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
html_theme = "alabaster" html_theme = "alabaster"
html_theme_options = { html_theme_options = {
"extra_nav_links": { "extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
"Impressum": "https://www.uni-stuttgart.de/impressum",
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
}
} }

View File

@ -1,110 +0,0 @@
#! /bin/python
import argparse
import json
import urllib.request
import re
from pathlib import Path
def main() -> None:
parser = argparse.ArgumentParser(
description="List undocumented PRs"
)
parser.add_argument("-v", "--version", type=str, required=True)
args = parser.parse_args()
match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version)
if not match:
print("invalid version")
exit(1)
version = "v" + match.group(1)
print("looking for milestone for " + version + " ...")
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json:
milestones = json.load(milestone_json)
if (len(milestones) == 0):
print("did not find any milestone")
exit(1)
if (len(milestones) > 1):
print("found multiple milestons")
milestone_title = milestones[0]['title']
milestone = str(milestones[0]['id'])
print("Using Milestone \""+ milestone_title + "\" with id " + milestone)
milestone_prs = []
page = 1
last_count = 1;
while last_count != 0:
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json:
pull_requests = json.load(pull_requests_json)
for pr in pull_requests:
milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']})
page += 1
last_count = len(pull_requests)
print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone")
print("looking for CHANGELOG.md ...")
path = Path(".")
files = list(path.glob("CHANGELOG.md"))
if (len(files) != 1):
files = list(path.glob("../CHANGELOG.md"))
if (len(files) != 1):
print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.")
exit(1)
print("Scanning CHANGELOG.md ...")
changelog_prs = []
with open(files[0]) as changelog:
line = changelog.readline()
while (line):
#print("line: " + line)
match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line)
if (match):
if match.group(1) == version:
#print("found version")
line = changelog.readline()
continue
else:
#print("done with " + match.group(1))
break
match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line)
if match:
changelog_prs.append(match.group(1))
line = changelog.readline()
print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md")
print("")
copy_array = changelog_prs.copy()
print("PRs in CHANGELOG.md that are not in Milestone:")
for pr in milestone_prs:
if pr['number'] in copy_array:
copy_array.remove(pr['number'])
for pr in copy_array:
print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr)
print("")
print("PRs in milestone that are not in CHANGELOG.md:")
for pr in milestone_prs:
if pr['number'] not in changelog_prs:
print("- " + pr['title'] + "\n PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number'])
main()

View File

@ -32,7 +32,6 @@ add_subdirectory(timemanager)
add_subdirectory(tmtcpacket) add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices) add_subdirectory(tmtcservices)
add_subdirectory(filesystem) add_subdirectory(filesystem)
add_subdirectory(util)
# Optional # Optional

View File

@ -59,24 +59,17 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) { store_address_t dataAddress) {
bool hasAdditionalData = false;
const uint8_t* dataPtr = nullptr; const uint8_t* dataPtr = nullptr;
size_t size = 0; size_t size = 0;
ReturnValue_t result; ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (dataAddress != store_address_t::invalid()) { if (result != returnvalue::OK) {
hasAdditionalData = true; CommandMessage reply;
result = ipcStore->getData(dataAddress, &dataPtr, &size); ActionMessage::setStepReply(&reply, actionId, 0, result);
if (result != returnvalue::OK) { queueToUse->sendMessage(commandedBy, &reply);
CommandMessage reply; return;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
} }
result = owner->executeAction(actionId, commandedBy, dataPtr, size); result = owner->executeAction(actionId, commandedBy, dataPtr, size);
if (hasAdditionalData) { ipcStore->deleteData(dataAddress);
ipcStore->deleteData(dataAddress);
}
if (result == HasActionsIF::EXECUTION_FINISHED) { if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, true, result); ActionMessage::setCompletionReply(&reply, actionId, true, result);

View File

@ -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);

View File

@ -2,9 +2,7 @@
#define FSFW_CFDP_H #define FSFW_CFDP_H
#include "cfdp/definitions.h" #include "cfdp/definitions.h"
#include "cfdp/handler/DestHandler.h"
#include "cfdp/handler/FaultHandlerBase.h" #include "cfdp/handler/FaultHandlerBase.h"
#include "cfdp/helpers.h"
#include "cfdp/tlv/Lv.h" #include "cfdp/tlv/Lv.h"
#include "cfdp/tlv/StringLv.h" #include "cfdp/tlv/StringLv.h"
#include "cfdp/tlv/Tlv.h" #include "cfdp/tlv/Tlv.h"

View File

@ -4,9 +4,8 @@ CfdpMessage::CfdpMessage() = default;
CfdpMessage::~CfdpMessage() = default; CfdpMessage::~CfdpMessage() = default;
void CfdpMessage::setPutRequest(CommandMessage *message, store_address_t putRequest) { void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
message->setCommand(PUT_REQUEST); message->setParameter(cfdpPacket.raw);
message->setParameter(putRequest.raw);
} }
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) { store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {

View File

@ -11,11 +11,9 @@ class CfdpMessage {
public: public:
static const uint8_t MESSAGE_ID = messagetypes::CFDP; static const uint8_t MESSAGE_ID = messagetypes::CFDP;
static const Command_t PUT_REQUEST = MAKE_COMMAND_ID(1);
static const Command_t CANCEL_REQUEST = MAKE_COMMAND_ID(1);
virtual ~CfdpMessage(); virtual ~CfdpMessage();
static void setPutRequest(CommandMessage* message, store_address_t putRequest); 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);

View File

@ -8,14 +8,11 @@
namespace cfdp { namespace cfdp {
/** struct FileSize : public SerializeIF {
* Helper type for the CFDP File Size Sensitive (FSS) fields.
*/
struct Fss : public SerializeIF {
public: public:
Fss() = default; FileSize() = default;
explicit Fss(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); }; explicit FileSize(uint64_t fileSize, bool isLarge = false) { setFileSize(fileSize, isLarge); };
[[nodiscard]] uint64_t value() const { return fileSize; } [[nodiscard]] uint64_t value() const { return fileSize; }
@ -24,7 +21,7 @@ struct Fss : public SerializeIF {
this->largeFile = isLarge; this->largeFile = isLarge;
return serialize(buffer, size, maxSize, streamEndianness); return serialize(buffer, size, maxSize, streamEndianness);
} }
using SerializeIF::serialize;
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 {
if (not largeFile) { if (not largeFile) {

View File

@ -4,7 +4,7 @@
#include "fsfw/serviceinterface.h" #include "fsfw/serviceinterface.h"
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() { cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
ReturnValue_t result = this->setValueAndWidth(width, value); ReturnValue_t result = this->setValue(width, value);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
#if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_DISABLE_PRINTOUT == 0
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -20,8 +20,8 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; } cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) { ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, uint64_t value_) {
switch (width_) { switch (widthInBytes) {
case (cfdp::WidthInBytes::ONE_BYTE): { case (cfdp::WidthInBytes::ONE_BYTE): {
if (value_ > UINT8_MAX) { if (value_ > UINT8_MAX) {
return returnvalue::FAILED; return returnvalue::FAILED;
@ -43,14 +43,11 @@ ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uin
this->value.fourBytes = value_; this->value.fourBytes = value_;
break; break;
} }
case (cfdp::WidthInBytes::EIGHT_BYTES): {
this->value.eightBytes = value_;
}
default: { default: {
break; break;
} }
} }
this->width = width_; this->width = widthInBytes;
return returnvalue::OK; return returnvalue::OK;
} }
@ -65,9 +62,6 @@ uint64_t cfdp::VarLenField::getValue() const {
case (cfdp::WidthInBytes::FOUR_BYTES): { case (cfdp::WidthInBytes::FOUR_BYTES): {
return value.fourBytes; return value.fourBytes;
} }
case (cfdp::WidthInBytes::EIGHT_BYTES): {
return value.eightBytes;
}
} }
return 0; return 0;
} }
@ -90,10 +84,6 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
case (cfdp::WidthInBytes::FOUR_BYTES): { case (cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness); return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
} }
case (cfdp::WidthInBytes::EIGHT_BYTES): {
return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize,
streamEndianness);
}
default: { default: {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
@ -108,16 +98,11 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui
return deSerialize(buffer, size, streamEndianness); return deSerialize(buffer, size, streamEndianness);
} }
ReturnValue_t cfdp::VarLenField::setValue(uint64_t value_) {
return setValueAndWidth(getWidth(), value_);
}
ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size, ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) { Endianness streamEndianness) {
switch (width) { switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): { case (cfdp::WidthInBytes::ONE_BYTE): {
value.oneByte = **buffer; value.oneByte = **buffer;
*buffer += 1;
*size += 1; *size += 1;
return returnvalue::OK; return returnvalue::OK;
} }
@ -127,9 +112,6 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
case (cfdp::WidthInBytes::FOUR_BYTES): { case (cfdp::WidthInBytes::FOUR_BYTES): {
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness); return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
} }
case (cfdp::WidthInBytes::EIGHT_BYTES): {
return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness);
}
default: { default: {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
@ -153,5 +135,3 @@ bool cfdp::VarLenField::operator==(const cfdp::VarLenField &other) const {
bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const { bool cfdp::VarLenField::operator!=(const cfdp::VarLenField &other) const {
return not(*this == other); return not(*this == other);
} }
void cfdp::VarLenField::setWidth(cfdp::WidthInBytes width_) { this->width = width_; }

View File

@ -31,9 +31,7 @@ class VarLenField : public SerializeIF {
bool operator!=(const VarLenField &other) const; bool operator!=(const VarLenField &other) const;
bool operator<(const VarLenField &other) const; bool operator<(const VarLenField &other) const;
ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value); ReturnValue_t setValue(cfdp::WidthInBytes, uint64_t value);
void setWidth(cfdp::WidthInBytes width);
ReturnValue_t setValue(uint64_t value);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override; Endianness streamEndianness) const override;
@ -53,9 +51,9 @@ class VarLenField : public SerializeIF {
return os; return os;
} }
#endif #endif
private: private:
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the using SerializeIF::deSerialize;
// compiler
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override; Endianness streamEndianness) override;
@ -67,7 +65,7 @@ template <typename T>
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField) cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) { : width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
static_assert((sizeof(T) % 2) == 0); static_assert((sizeof(T) % 2) == 0);
setValueAndWidth(width, byteField.getValue()); setValue(width, byteField.getValue());
} }
struct EntityId : public VarLenField { struct EntityId : public VarLenField {
@ -76,32 +74,6 @@ struct EntityId : public VarLenField {
template <typename T> template <typename T>
explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {} explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {} EntityId(cfdp::WidthInBytes width, size_t entityId) : VarLenField(width, entityId) {}
ReturnValue_t serializeAsLv(uint8_t **buffer, size_t *size, size_t maxSize) const {
if (buffer == nullptr or size == nullptr) {
return returnvalue::FAILED;
}
if (*size + 1 + getWidth() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = getWidth();
*buffer += 1;
*size += 1;
return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK);
}
ReturnValue_t deSerializeFromLv(const uint8_t **buffer, size_t *deserLen) {
if (buffer == nullptr or deserLen == nullptr) {
return returnvalue::FAILED;
}
if (*deserLen < 2) {
return SerializeIF::STREAM_TOO_SHORT;
}
auto width = static_cast<WidthInBytes>(**buffer);
*buffer += 1;
*deserLen -= 1;
return VarLenField::deSerialize(width, buffer, deserLen, SerializeIF::Endianness::NETWORK);
}
}; };
struct TransactionSeqNum : public VarLenField { struct TransactionSeqNum : public VarLenField {

View File

@ -9,6 +9,11 @@
#include "fsfw/returnvalues/FwClassIds.h" #include "fsfw/returnvalues/FwClassIds.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
namespace cfdp { namespace cfdp {
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5"; static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
@ -17,7 +22,7 @@ static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
static constexpr uint8_t CFDP_VERSION_2 = 0b001; static constexpr uint8_t CFDP_VERSION_2 = 0b001;
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5; static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP_BASE; 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 = returnvalue::makeCode(CFDP_CLASS_ID, 1);
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2); static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
@ -68,7 +73,6 @@ enum WidthInBytes : uint8_t {
ONE_BYTE = 1, ONE_BYTE = 1,
TWO_BYTES = 2, TWO_BYTES = 2,
FOUR_BYTES = 4, FOUR_BYTES = 4,
EIGHT_BYTES = 8
}; };
enum FileDirective : uint8_t { enum FileDirective : uint8_t {
@ -143,20 +147,6 @@ enum RecordContinuationState {
CONTAINS_START_AND_END = 0b11 CONTAINS_START_AND_END = 0b11
}; };
enum class ProxyOpMessageType : uint8_t {
PUT_REQUEST = 0x00,
MSG_TO_USR = 0x01,
FS_REQUEST = 0x02,
FAULT_HANDLER_OVERRIDE = 0x03,
TRANSMISSION_MODE = 0x04,
FLOW_LABEL = 0x05,
SEG_CTRL = 0x06,
PUT_RESPONSE = 0x07,
FS_RESPONSE = 0x08,
PUT_CANCEL = 0x09,
CLOSURE = 0x0b
};
} // namespace cfdp } // namespace cfdp
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */ #endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */

View File

@ -1,4 +1 @@
target_sources( target_sources(${LIB_FSFW_NAME} PRIVATE FaultHandlerBase.cpp UserBase.cpp)
${LIB_FSFW_NAME}
PRIVATE SourceHandler.cpp DestHandler.cpp PutRequest.cpp
ReservedMessageParser.cpp FaultHandlerBase.cpp UserBase.cpp)

View File

@ -1,574 +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),
msgToUserVec(params.maxTlvsInOnePdu),
transactionParams(params.maxFilenameLen),
destParams(std::move(params)),
fsfwParams(fsfwParams) {
transactionParams.pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
}
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::stateMachine() {
ReturnValue_t result;
uint8_t errorIdx = 0;
fsmRes.resetOfIteration();
if (fsmRes.step == TransactionStep::IDLE) {
for (auto infoIter = destParams.packetListRef.begin();
infoIter != destParams.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
destParams.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 = destParams.packetListRef.begin();
infoIter != destParams.packetListRef.end();) {
fsfwParams.tcStore->deleteData(infoIter->storeId);
infoIter++;
}
destParams.packetListRef.clear();
}
if (fsmRes.step != TransactionStep::IDLE) {
fsmRes.callStatus = CallStatus::CALL_AGAIN;
}
return updateFsmRes(errorIdx);
}
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
for (auto infoIter = destParams.packetListRef.begin();
infoIter != destParams.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
destParams.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
destParams.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 == CfdpState::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 (destParams.packetListRef.full()) {
return FAILED;
}
destParams.packetListRef.push_back(packet);
return OK;
}
ReturnValue_t cfdp::DestHandler::initialize() {
if (fsfwParams.tmStore == nullptr) {
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (fsfwParams.tmStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.tcStore == nullptr) {
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (fsfwParams.tcStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.msgQueue == nullptr) {
return FAILED;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
// Process metadata PDU
auto constAccessorPair = fsfwParams.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;
MetadataGenericInfo metadataInfo(transactionParams.fileSize);
MetadataPduReader reader(constAccessorPair.second.data(), constAccessorPair.second.size(),
metadataInfo, tlvVec.data(), tlvVec.size());
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);
}
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
// Process file data PDU
auto constAccessorPair = fsfwParams.tcStore->getData(info.storeId);
if (constAccessorPair.first != OK) {
// TODO: This is not a CFDP error. Event and/or warning?
return constAccessorPair.first;
}
FileDataInfo fdInfo;
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(transactionParams.destName.data(), fileSegmentLen);
fileOpParams.offset = fdInfo.getOffset().value();
if (destParams.cfg.indicCfg.fileSegmentRecvIndicRequired) {
FileSegmentRecvdParams segParams;
segParams.offset = fdInfo.getOffset().value();
segParams.id = transactionParams.transactionId;
segParams.length = fileSegmentLen;
segParams.recContState = fdInfo.getRecordContinuationState();
size_t segmentMetadatLen = 0;
auto* segMetadata = fdInfo.getSegmentMetadata(&segmentMetadatLen);
segParams.segmentMetadata = {segMetadata, segmentMetadatLen};
destParams.user.fileSegmentRecvdIndication(segParams);
}
result = destParams.user.vfs.writeToFile(fileOpParams, fileData);
if (result != returnvalue::OK) {
// TODO: Proper Error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
<< result << std::endl;
#endif
transactionParams.vfsErrorCount++;
if (transactionParams.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter
fsfwParams.eventReporter->forwardEvent(events::FILESTORE_ERROR,
static_cast<uint8_t>(fsmRes.step), result);
}
return result;
} else {
transactionParams.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
transactionParams.vfsErrorCount = 0;
}
if (fdInfo.getOffset().value() + fileSegmentLen > transactionParams.progress) {
transactionParams.progress = fdInfo.getOffset().value() + fileSegmentLen;
}
return result;
}
ReturnValue_t cfdp::DestHandler::handleEofPdu(const cfdp::PacketInfo& info) {
// Process EOF PDU
auto constAccessorPair = fsfwParams.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) {
transactionParams.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 > transactionParams.progress) {
// TODO: File size error
}
transactionParams.fileSize.setFileSize(fileSizeFromEof, std::nullopt);
}
if (destParams.cfg.indicCfg.eofRecvIndicRequired) {
destParams.user.eofRecvIndication(getTransactionId());
}
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
} else if (fsmRes.state == CfdpState::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 destParams.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(const MetadataPduReader& reader) {
if (fsmRes.state != CfdpState::IDLE) {
// According to standard, discard metadata PDU if we are busy
return OK;
}
ReturnValue_t result = OK;
size_t sourceNameSize = 0;
if (not reader.getSourceFileName().isEmpty()) {
const uint8_t* sourceNamePtr = reader.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
return FAILED;
}
std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
transactionParams.sourceName[sourceNameSize] = '\0';
}
size_t destNameSize = 0;
if (not reader.getDestFileName().isEmpty()) {
const uint8_t* destNamePtr = reader.getDestFileName().getValue(&destNameSize);
if (destNameSize + 1 > transactionParams.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
return FAILED;
}
std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
transactionParams.destName[destNameSize] = '\0';
}
transactionParams.metadataOnly = true;
// 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) {
transactionParams.metadataOnly = false;
FilesystemParams fparams(transactionParams.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
if (destParams.user.vfs.isDirectory(transactionParams.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
if (destParams.user.vfs.fileExists(fparams)) {
result = destParams.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
} else {
result = destParams.user.vfs.createFile(fparams);
if (result != OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
}
}
EntityId sourceId;
reader.getSourceId(sourceId);
if (not destParams.remoteCfgTable.getRemoteCfg(sourceId, &transactionParams.remoteCfg)) {
// TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__
<< ": No remote configuration found for destination ID "
<< transactionParams.pduConf.sourceId.getValue() << std::endl;
#endif
return FAILED;
}
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
fsmRes.state = CfdpState::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpState::BUSY_CLASS_2_ACKED;
}
if (transactionParams.metadataOnly) {
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
} else {
// Kind of ugly, make FSM working on packet per packet basis..
fsmRes.step = TransactionStep::TRANSACTION_START;
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
}
auto& info = reader.getGenericInfo();
transactionParams.checksumType = info.getChecksumType();
transactionParams.closureRequested = info.isClosureRequested();
reader.fillConfig(transactionParams.pduConf);
transactionParams.pduConf.direction = Direction::TOWARDS_SENDER;
transactionParams.transactionId.entityId = transactionParams.pduConf.sourceId;
transactionParams.transactionId.seqNum = transactionParams.pduConf.seqNum;
transactionParams.fileSize = info.getFileSize();
MetadataRecvdParams params(transactionParams.transactionId, transactionParams.pduConf.sourceId,
transactionParams.fileSize);
params.destFileName = transactionParams.destName.data();
params.sourceFileName = transactionParams.sourceName.data();
params.numberOfMsgsToUser = 0;
for (const auto& opt : tlvVec) {
if (opt.getType() == TlvType::MSG_TO_USER) {
msgToUserVec[params.numberOfMsgsToUser] =
MessageToUserTlv(opt.getValue(), opt.getLengthField());
params.numberOfMsgsToUser++;
}
}
params.msgsToUserArray = msgToUserVec.data();
destParams.user.metadataRecvdIndication(params);
return result;
}
cfdp::CfdpState cfdp::DestHandler::getCfdpState() const { return fsmRes.state; }
ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
ReturnValue_t result;
if (transactionParams.checksumType != ChecksumType::NULL_CHECKSUM) {
result = checksumVerification();
if (result != OK) {
// TODO: Warning / error handling?
}
} else {
transactionParams.conditionCode = ConditionCode::NO_ERROR;
}
result = noticeOfCompletion();
if (result != OK) {
}
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
if (transactionParams.closureRequested) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
} else {
finish();
}
} else if (fsmRes.state == CfdpState::BUSY_CLASS_2_ACKED) {
fsmRes.step = TransactionStep::SENDING_FINISHED_PDU;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
// A path may only have a maximum of 256 characters in CFDP, so this buffer should be sufficient
// for all use-cases.
char baseNameBuf[512]{};
FilesystemParams fparamsSrc(transactionParams.sourceName.data());
size_t baseNameLen = 0;
ReturnValue_t result = destParams.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf,
sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED;
}
// Destination name + slash + base name + null termination
if (destNameSize + 1 + baseNameLen + 1 > transactionParams.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
transactionParams.destName[destNameSize++] = '/';
std::memcpy(transactionParams.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
transactionParams.destName[destNameSize++] = '\0';
return OK;
}
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result,
const char* info) const {
fsfwParams.eventReporter->forwardEvent(event, static_cast<uint8_t>(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif
}
void cfdp::DestHandler::finish() {
transactionParams.reset();
destParams.packetListRef.clear();
fsmRes.state = CfdpState::IDLE;
fsmRes.step = TransactionStep::IDLE;
}
ReturnValue_t cfdp::DestHandler::checksumVerification() {
std::array<uint8_t, 1024> buf{};
etl::crc32 crcCalc;
uint64_t currentOffset = 0;
FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
while (currentOffset < transactionParams.fileSize.value()) {
uint64_t readLen;
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
readLen = transactionParams.fileSize.value() - currentOffset;
} else {
readLen = buf.size();
}
if (readLen > 0) {
params.offset = currentOffset;
params.size = readLen;
auto result = destParams.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 == transactionParams.crc) {
transactionParams.conditionCode = ConditionCode::NO_ERROR;
transactionParams.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
} else {
// TODO: Proper error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CRC check for file " << transactionParams.destName.data() << " failed"
<< std::endl;
#endif
transactionParams.conditionCode = ConditionCode::FILE_CHECKSUM_FAILURE;
}
return OK;
}
ReturnValue_t cfdp::DestHandler::noticeOfCompletion() {
if (destParams.cfg.indicCfg.transactionFinishedIndicRequired) {
TransactionFinishedParams params(
transactionParams.transactionId, transactionParams.conditionCode,
transactionParams.deliveryCode, transactionParams.deliveryStatus);
destParams.user.transactionFinishedIndication(params);
}
return OK;
}
ReturnValue_t cfdp::DestHandler::sendFinishedPdu() {
FinishedInfo info(transactionParams.conditionCode, transactionParams.deliveryCode,
transactionParams.deliveryStatus);
FinishPduCreator finishedPdu(transactionParams.pduConf, info);
store_address_t storeId;
uint8_t* dataPtr = nullptr;
ReturnValue_t result =
fsfwParams.tmStore->getFreeElement(&storeId, finishedPdu.getSerializedSize(), &dataPtr);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler:sendFinishedPdu: Getting store slot failed" << std::endl;
#endif
fsfwParams.eventReporter->forwardEvent(events::STORE_ERROR, result, 0);
return result;
}
size_t serLen = 0;
result = finishedPdu.serialize(dataPtr, serLen, finishedPdu.getSerializedSize());
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Serializing Finished PDU failed"
<< std::endl;
#endif
fsfwParams.eventReporter->forwardEvent(events::SERIALIZATION_ERROR, result, 0);
return result;
}
TmTcMessage msg(storeId);
result = fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &msg);
if (result != OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
#endif
fsfwParams.eventReporter->forwardEvent(events::MSG_QUEUE_ERROR, result, 0);
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 transactionParams.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) { fsfwParams.msgQueue = &queue; }
void cfdp::DestHandler::setEventReporter(EventReportingProxyIF& reporter) {
fsfwParams.eventReporter = &reporter;
}
const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const {
return destParams;
}
StorageManagerIF* cfdp::DestHandler::getTmStore() const { return fsfwParams.tmStore; }
StorageManagerIF* cfdp::DestHandler::getTcStore() const { return fsfwParams.tcStore; }

View File

@ -1,178 +0,0 @@
#ifndef FSFW_CFDP_CFDPDESTHANDLER_H
#define FSFW_CFDP_CFDPDESTHANDLER_H
#include <etl/list.h>
#include <etl/set.h>
#include <array>
#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/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/container/DynamicFIFO.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
namespace cfdp {
template <size_t SIZE>
using LostSegmentsList = etl::set<etl::pair<uint64_t, uint64_t>, SIZE>;
using LostSegmentsListBase = etl::iset<etl::pair<uint64_t, uint64_t>>;
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
// TODO: Actually, we can provide a better abstraction via interface, which
// allows using something like a bounded map. This simplifies
// the implementation significantly.
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 = 20;
size_t maxFilenameLen = 255;
};
class DestHandler {
public:
enum class TransactionStep : uint8_t {
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;
CfdpState state = CfdpState::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& stateMachine();
void setMsgQueue(MessageQueueIF& queue);
void setEventReporter(EventReportingProxyIF& reporter);
ReturnValue_t passPacket(PacketInfo packet);
ReturnValue_t initialize();
[[nodiscard]] CfdpState 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;
metadataOnly = false;
closureRequested = false;
vfsErrorCount = 0;
checksumType = ChecksumType::NULL_CHECKSUM;
}
bool metadataOnly = false;
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
bool closureRequested = false;
uint16_t vfsErrorCount = 0;
std::vector<char> sourceName;
std::vector<char> destName;
cfdp::Fss 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<MessageToUserTlv> msgToUserVec;
TransactionParams transactionParams;
DestHandlerParams destParams;
cfdp::FsfwParams fsfwParams;
FsmResult fsmRes;
ReturnValue_t startTransaction(const MetadataPduReader& reader);
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 tryBuildingAbsoluteDestName(size_t destNameSize);
ReturnValue_t sendFinishedPdu();
ReturnValue_t noticeOfCompletion();
ReturnValue_t checksumVerification();
void fileErrorHandler(Event event, ReturnValue_t result, const char* info) const;
const FsmResult& updateFsmRes(uint8_t errors);
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
void finish();
};
} // namespace cfdp
#endif // FSFW_CFDP_CFDPDESTHANDLER_H

View File

@ -1,201 +0,0 @@
#include "PutRequest.h"
using namespace returnvalue;
cfdp::PutRequest::PutRequest(cfdp::EntityId destId, const uint8_t *msgsToUser,
size_t msgsToUserTotalSize, const uint8_t *fsRequests,
size_t fsRequestsSize)
: destId(std::move(destId)),
metadataOnly(true),
msgsToUsersTotalSize(msgsToUserTotalSize),
msgsToUserStartPtr(msgsToUser),
fsRequestsTotalSize(fsRequestsSize),
fsRequestStartPtr(fsRequests) {}
cfdp::PutRequest::PutRequest(cfdp::EntityId destId, cfdp::StringLv &sourceName,
cfdp::StringLv &destName)
: destId(std::move(destId)), sourceName(std::move(sourceName)), destName(std::move(destName)) {}
[[nodiscard]] bool cfdp::PutRequest::isMetadataOnly() const { return metadataOnly; }
ReturnValue_t cfdp::PutRequest::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
if (buffer == nullptr or size == nullptr) {
return FAILED;
}
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
ReturnValue_t result = destId.serializeAsLv(buffer, size, maxSize);
if (result != OK) {
return result;
}
result = SerializeAdapter::serialize(&metadataOnly, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
if (!metadataOnly) {
result = sourceName.serialize(buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result = destName.serialize(buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&hasTransmissionMode, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&transmissionMode, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&hasClosureRequested, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
result =
SerializeAdapter::serialize(&closureRequested, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
}
result =
SerializeAdapter::serialize(&msgsToUsersTotalSize, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
std::memcpy(*buffer, msgsToUserStartPtr, msgsToUsersTotalSize);
*buffer += msgsToUsersTotalSize;
*size += msgsToUsersTotalSize;
result =
SerializeAdapter::serialize(&fsRequestsTotalSize, buffer, size, maxSize, streamEndianness);
if (result != OK) {
return result;
}
std::memcpy(*buffer, fsRequestStartPtr, fsRequestsTotalSize);
*buffer += fsRequestsTotalSize;
*size += fsRequestsTotalSize;
return OK;
}
ReturnValue_t cfdp::PutRequest::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
if (buffer == nullptr or size == nullptr) {
return FAILED;
}
ReturnValue_t result = destId.deSerializeFromLv(buffer, size);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&metadataOnly, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
if (!metadataOnly) {
result = sourceName.deSerialize(buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = destName.deSerialize(buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&hasTransmissionMode, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&transmissionMode, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&hasClosureRequested, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
result = SerializeAdapter::deSerialize(&closureRequested, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
}
result = SerializeAdapter::deSerialize(&msgsToUsersTotalSize, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
msgsToUserStartPtr = *buffer;
*buffer += msgsToUsersTotalSize;
*size += msgsToUsersTotalSize;
result = SerializeAdapter::deSerialize(&fsRequestsTotalSize, buffer, size, streamEndianness);
if (result != OK) {
return result;
}
fsRequestStartPtr = *buffer;
*buffer += fsRequestsTotalSize;
*size += fsRequestsTotalSize;
return OK;
}
size_t cfdp::PutRequest::getSerializedSize() const {
// Entity ID LV (1 leading size byte) and the metadata only flag.
size_t baseSize = 1 + destId.getSerializedSize() + 1;
if (!metadataOnly) {
baseSize += sourceName.getSerializedSize() + destName.getSerializedSize() + 4;
}
baseSize += sizeof(msgsToUsersTotalSize) + msgsToUsersTotalSize + sizeof(fsRequestsTotalSize) +
fsRequestsTotalSize;
return baseSize;
}
void cfdp::PutRequest::setSourceAndDestName(cfdp::StringLv &sourceName_,
cfdp::StringLv &destName_) {
metadataOnly = false;
this->sourceName = std::move(sourceName_);
this->destName = std::move(destName_);
}
const cfdp::StringLv &cfdp::PutRequest::getSourceName() const { return sourceName; }
const cfdp::StringLv &cfdp::PutRequest::getDestName() const { return destName; }
const cfdp::EntityId &cfdp::PutRequest::getDestId() const { return destId; }
void cfdp::PutRequest::setDestId(cfdp::EntityId id) { destId = std::move(id); }
void cfdp::PutRequest::setTransmissionMode(cfdp::TransmissionMode transmissionMode_) {
this->transmissionMode = transmissionMode_;
hasTransmissionMode = true;
}
void cfdp::PutRequest::clearTransmissionMode() { hasTransmissionMode = false; }
void cfdp::PutRequest::clearClosureRequest() { hasClosureRequested = false; }
void cfdp::PutRequest::setClosureRequest(bool closureRequested_) {
this->closureRequested = closureRequested_;
hasClosureRequested = true;
}
const uint8_t *cfdp::PutRequest::getMessagesToUser(size_t &totalSize) {
totalSize = this->msgsToUsersTotalSize;
return msgsToUserStartPtr;
}
bool cfdp::PutRequest::getClosureRequested(bool &closureRequested_) const {
if (hasClosureRequested) {
closureRequested_ = this->closureRequested;
}
return hasClosureRequested;
}
bool cfdp::PutRequest::getTransmissionMode(cfdp::TransmissionMode &mode) const {
if (hasTransmissionMode) {
mode = static_cast<cfdp::TransmissionMode>(this->transmissionMode);
}
return hasTransmissionMode;
}

View File

@ -1,82 +0,0 @@
#pragma once
#include <optional>
#include <vector>
#include "fsfw/cfdp/VarLenFields.h"
#include "fsfw/cfdp/tlv/FilestoreRequestTlv.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
namespace cfdp {
class PutRequest : public SerializeIF {
public:
/**
* Metadata only constructor.
* @param destId
* @param msgsToUser
* @param msgsToUserTotalSize
* @param fsRequests
* @param fsRequestsSize
*/
PutRequest(EntityId destId, const uint8_t* msgsToUser, size_t msgsToUserTotalSize,
const uint8_t* fsRequests, size_t fsRequestsSize);
/**
* Put request to initiate file transfers. By default, the transmission mode and closure requested
* parameter are not present, thereby being derived from the remote configuration for a
* particular destination ID.
* @param destId
* @param sourceName
* @param destName
*/
PutRequest(EntityId destId, cfdp::StringLv& sourceName, cfdp::StringLv& destName);
/**
* Default constructor for deserialization.
*/
PutRequest() = default;
[[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
[[nodiscard]] size_t getSerializedSize() const override;
void setSourceAndDestName(cfdp::StringLv& sourceName, cfdp::StringLv& destName);
[[nodiscard]] const cfdp::StringLv& getSourceName() const;
[[nodiscard]] const cfdp::StringLv& getDestName() const;
void setTransmissionMode(cfdp::TransmissionMode transmissionMode);
void clearTransmissionMode();
void setClosureRequest(bool closureRequested);
void clearClosureRequest();
const uint8_t* getMessagesToUser(size_t& msgSize);
[[nodiscard]] bool isMetadataOnly() const;
bool getTransmissionMode(TransmissionMode& mode) const;
bool getClosureRequested(bool& closureRequested) const;
[[nodiscard]] const EntityId& getDestId() const;
void setDestId(EntityId id);
private:
EntityId destId;
uint8_t metadataOnly = true;
// Transaction parameters. Omitted if the put request is metadata only.
cfdp::StringLv sourceName;
cfdp::StringLv destName;
bool hasTransmissionMode = false;
uint8_t transmissionMode = TransmissionMode::UNACKNOWLEDGED;
bool hasClosureRequested = false;
uint8_t closureRequested = false;
// Metadata
size_t msgsToUsersTotalSize = 0;
const uint8_t* msgsToUserStartPtr = nullptr;
size_t fsRequestsTotalSize = 0;
const uint8_t* fsRequestStartPtr = nullptr;
};
} // namespace cfdp

View File

@ -16,7 +16,7 @@ class RemoteConfigTableIF {
*/ */
class OneRemoteConfigProvider : public RemoteConfigTableIF { class OneRemoteConfigProvider : public RemoteConfigTableIF {
public: public:
explicit OneRemoteConfigProvider(RemoteEntityCfg& cfg) : cfg(cfg) {} explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override { bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
if (remoteId != cfg.remoteId) { if (remoteId != cfg.remoteId) {
@ -27,7 +27,7 @@ class OneRemoteConfigProvider : public RemoteConfigTableIF {
} }
private: private:
RemoteEntityCfg& cfg; RemoteEntityCfg cfg;
}; };
} // namespace cfdp } // namespace cfdp

View File

@ -1,74 +0,0 @@
#include "ReservedMessageParser.h"
#include "fsfw/cfdp/CfdpMessage.h"
#include "fsfw/cfdp/handler/PutRequest.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/QueueFactory.h"
using namespace returnvalue;
cfdp::ReservedMessageParser::ReservedMessageParser(StorageManagerIF& ipcStore,
MessageQueueIF& msgQueue,
MessageQueueId_t userDestination)
: msgQueue(msgQueue), ipcStore(ipcStore), userDestination(userDestination) {}
ReturnValue_t cfdp::ReservedMessageParser::parse(const MessageToUserTlv* msgsToUserArray,
size_t numMsgToUser) {
ReturnValue_t result = returnvalue::OK;
cfdp::StringLv sourceFileName;
cfdp::StringLv destFileName;
PutRequest putRequest;
const uint8_t* currentPtr = nullptr;
size_t deserSize = 0;
bool needToSendPutRequest = false;
for (size_t idx = 0; idx < numMsgToUser; idx++) {
if (&msgsToUserArray[idx] == nullptr) {
continue;
}
uint8_t messageType = 0;
if (msgsToUserArray[idx].isReservedCfdpMessage(messageType, &currentPtr, deserSize)) {
if (messageType == static_cast<uint8_t>(ProxyOpMessageType::PUT_REQUEST)) {
EntityId entityIdLv;
result = entityIdLv.deSerializeFromLv(&currentPtr, &deserSize);
if (result != returnvalue::OK) {
return result;
}
putRequest.setDestId(entityIdLv);
result =
sourceFileName.deSerialize(&currentPtr, &deserSize, SerializeIF::Endianness::NETWORK);
if (result != OK) {
return result;
}
result =
destFileName.deSerialize(&currentPtr, &deserSize, SerializeIF::Endianness::NETWORK);
if (result != OK) {
return result;
}
putRequest.setSourceAndDestName(sourceFileName, destFileName);
needToSendPutRequest = true;
}
}
}
if (needToSendPutRequest) {
store_address_t storeId;
uint8_t* dataPtr;
result = ipcStore.getFreeElement(&storeId, putRequest.getSerializedSize(), &dataPtr);
if (result != OK) {
return result;
}
size_t serLen = 0;
result = putRequest.serialize(&dataPtr, &serLen, putRequest.getSerializedSize(),
SerializeIF::Endianness::MACHINE);
if (result != OK) {
return result;
}
CommandMessage msg;
CfdpMessage::setPutRequest(&msg, storeId);
result = msgQueue.sendMessage(userDestination, &msg);
if (result != OK) {
return result;
}
}
return OK;
}

View File

@ -1,27 +0,0 @@
#pragma once
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
namespace cfdp {
/**
* This class parses messages to user for special CFDP messages and converts them to appropriate
* CFDP requests sent via the IPC store where applicable. It also provides an API to retrieve
* custom messages which are not special CFDP messages from a provided bytestream.
*/
class ReservedMessageParser {
public:
ReservedMessageParser(StorageManagerIF& ipcStore, MessageQueueIF& msgQueue,
MessageQueueId_t userDestination);
ReturnValue_t parse(const MessageToUserTlv* msgsToUserArray, size_t numMsgsToUser);
private:
MessageQueueIF& msgQueue;
StorageManagerIF& ipcStore;
MessageQueueId_t userDestination;
};
} // namespace cfdp

View File

@ -1,376 +0,0 @@
#include "SourceHandler.h"
#include <etl/crc32.h>
#include <array>
#include "fsfw/cfdp/pdu/EofPduCreator.h"
#include "fsfw/cfdp/pdu/FileDataCreator.h"
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
#include "fsfw/filesystem/HasFileSystemIF.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/objectmanager.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams)
: sourceParams(std::move(params)), fsfwParams(fsfwParams) {
// The entity ID portion of the transaction ID will always remain fixed.
transactionParams.id.entityId = sourceParams.cfg.localId;
transactionParams.pduConf.sourceId = sourceParams.cfg.localId;
if (sourceParams.seqCountProvider.bitWidth() == 8) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
} else if (sourceParams.seqCountProvider.bitWidth() == 16) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::TWO_BYTES);
} else if (sourceParams.seqCountProvider.bitWidth() == 32) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::FOUR_BYTES);
} else if (sourceParams.seqCountProvider.bitWidth() == 64) {
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::EIGHT_BYTES);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "cfdp::SourceHandler: Seq count provider bit width "
<< sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl;
#else
sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n",
sourceParams.seqCountProvider.bitWidth());
#endif
// Yeah, what am I supposed to do here? Can't throw an exception in the FSFW..
transactionParams.pduConf.seqNum.setWidth(cfdp::WidthInBytes::ONE_BYTE);
}
transactionParams.pduConf.seqNum.setValue(0);
}
cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
ReturnValue_t result;
if (step == TransactionStep::IDLE) {
step = TransactionStep::TRANSACTION_START;
}
if (step == TransactionStep::TRANSACTION_START) {
sourceParams.user.transactionIndication(transactionParams.id);
result = checksumGeneration();
if (result != OK) {
addError(result);
}
step = TransactionStep::SENDING_METADATA;
}
if (step == TransactionStep::SENDING_METADATA) {
result = prepareAndSendMetadataPdu();
if (result != OK) {
addError(result);
}
fsmResult.callStatus = CallStatus::CALL_AGAIN;
return fsmResult;
}
if (step == TransactionStep::SENDING_FILE_DATA) {
bool noFdPdu = false;
result = prepareAndSendNextFileDataPdu(noFdPdu);
if (result == OK and !noFdPdu) {
fsmResult.callStatus = CallStatus::CALL_AGAIN;
return fsmResult;
}
}
if (step == TransactionStep::SENDING_EOF) {
result = prepareAndSendEofPdu();
if (result != OK) {
addError(result);
}
if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
sourceParams.user.eofSentIndication(transactionParams.id);
}
if (transactionParams.closureRequested) {
step = TransactionStep::WAIT_FOR_FINISH;
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
} else {
step = TransactionStep::NOTICE_OF_COMPLETION;
fsmResult.callStatus = CallStatus::CALL_AGAIN;
}
return fsmResult;
}
if (step == TransactionStep::WAIT_FOR_FINISH) {
// TODO: In case this is a request with closure, wait for finish.
// Done, issue notice of completion
step = TransactionStep::NOTICE_OF_COMPLETION;
}
if (step == TransactionStep::NOTICE_OF_COMPLETION) {
noticeOfCompletion();
reset();
}
return fsmResult;
}
const cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() {
fsmResult.packetsSent = 0;
fsmResult.errors = 0;
fsmResult.callStatus = CallStatus::DONE;
if (state == cfdp::CfdpState::IDLE) {
return fsmResult;
}
if (state == cfdp::CfdpState::BUSY_CLASS_1_NACKED) {
return fsmNacked();
}
return fsmResult;
}
ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
if (transactionParams.fileSize.value() == 0) {
// NULL checksum for empty file.
transactionParams.crc = 0;
return OK;
}
std::array<uint8_t, 1024> buf{};
etl::crc32 crcCalc;
uint64_t currentOffset = 0;
FileOpParams params(transactionParams.sourceName.data(), transactionParams.fileSize.value());
while (currentOffset < transactionParams.fileSize.value()) {
uint64_t readLen;
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
readLen = transactionParams.fileSize.value() - currentOffset;
} else {
readLen = buf.size();
}
if (readLen > 0) {
params.offset = currentOffset;
params.size = readLen;
auto result = sourceParams.user.vfs.readFromFile(params, buf.data(), buf.size());
if (result != OK) {
addError(result);
return FAILED;
}
crcCalc.add(buf.begin(), buf.begin() + readLen);
}
currentOffset += readLen;
}
transactionParams.crc = crcCalc.value();
return OK;
}
ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg) {
if (state != CfdpState::IDLE) {
return SOURCE_TRANSACTION_PENDING;
}
if (cfg.remoteId != putRequest.getDestId()) {
return WRONG_REMOTE_CFG_ENTITY_ID;
}
if (putRequest.getSourceName().getValueLen() == 0) {
return SOURCE_NAME_EMPTY;
}
if (putRequest.getDestName().getValueLen() == 0) {
return DEST_NAME_EMPTY;
}
const char* srcNamePtr = putRequest.getSourceName().getCString(transactionParams.sourceNameSize);
const char* destNamePtr = putRequest.getDestName().getCString(transactionParams.destNameSize);
std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
// Add 0 termination. The source and dest name size can not be larger than UINT8_MAX, so this
// operation is safe.
transactionParams.sourceName[transactionParams.sourceNameSize] = '\0';
transactionParams.destName[transactionParams.destNameSize] = '\0';
FilesystemParams params(transactionParams.sourceName.data());
if (!sourceParams.user.vfs.fileExists(params)) {
return FILE_DOES_NOT_EXIST;
}
if (cfg.maxFileSegmentLen > fileBuf.size() or cfg.maxFileSegmentLen == 0) {
return FILE_SEGMENT_LEN_INVALID;
}
// If transmission mode is not set, use default transmission mode for the remote entity.
if (not putRequest.getTransmissionMode(transactionParams.pduConf.mode)) {
transactionParams.pduConf.mode = cfg.defaultTransmissionMode;
}
// If closure request field is not set, use default option for the remote entity.
if (not putRequest.getClosureRequested(transactionParams.closureRequested)) {
transactionParams.closureRequested = cfg.closureRequested;
}
const EntityId& destId = putRequest.getDestId();
// The width of the source and destination ID must be the same. Use the larger ID value to
// ensure the width is large enough for both IDs
if (destId.getWidth() > transactionParams.pduConf.sourceId.getWidth()) {
transactionParams.pduConf.destId = destId;
transactionParams.pduConf.sourceId.setWidth(destId.getWidth());
} else {
transactionParams.pduConf.destId.setValueAndWidth(transactionParams.pduConf.sourceId.getWidth(),
destId.getValue());
}
// Only used for PDU forwarding, file is sent to file receiver regularly here.
transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER;
transactionParams.pduConf.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement());
transactionParams.id.seqNum = transactionParams.pduConf.seqNum;
if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) {
state = cfdp::CfdpState::BUSY_CLASS_2_ACKED;
} else if (transactionParams.pduConf.mode == TransmissionMode::UNACKNOWLEDGED) {
state = cfdp::CfdpState::BUSY_CLASS_1_NACKED;
}
step = TransactionStep::IDLE;
uint64_t fileSize = 0;
sourceParams.user.vfs.getFileSize(params, fileSize);
transactionParams.pduConf.largeFile = false;
if (fileSize > UINT32_MAX) {
transactionParams.pduConf.largeFile = true;
}
if (fileSize == 0) {
transactionParams.checksumType = ChecksumType::NULL_CHECKSUM;
} else {
transactionParams.checksumType = ChecksumType::CRC_32;
}
transactionParams.fileSize.setFileSize(fileSize, transactionParams.pduConf.largeFile);
transactionParams.progress = 0;
transactionParams.remoteCfg = cfg;
return OK;
}
ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() {
cfdp::StringLv sourceName(transactionParams.sourceName.data(), transactionParams.sourceNameSize);
cfdp::StringLv destName(transactionParams.destName.data(), transactionParams.destNameSize);
auto metadataInfo =
MetadataGenericInfo(transactionParams.closureRequested, transactionParams.checksumType,
transactionParams.fileSize);
auto metadataPdu =
MetadataPduCreator(transactionParams.pduConf, metadataInfo, sourceName, destName, nullptr, 0);
ReturnValue_t result = sendGenericPdu(metadataPdu);
if (result != OK) {
return result;
}
// Advance FSM if everything works
step = TransactionStep::SENDING_FILE_DATA;
return OK;
}
ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu(bool& noFileDataPdu) {
cfdp::Fss offset(transactionParams.progress);
uint64_t readLen;
uint64_t fileSize = transactionParams.fileSize.value();
noFileDataPdu = false;
if (fileSize == 0) {
// We are done, no need to send file data PDUs for an empty file.
step = TransactionStep::SENDING_EOF;
noFileDataPdu = true;
return OK;
}
if (fileSize < transactionParams.remoteCfg.maxFileSegmentLen) {
readLen = transactionParams.fileSize.value();
} else {
if (transactionParams.progress + transactionParams.remoteCfg.maxFileSegmentLen > fileSize) {
readLen = fileSize - transactionParams.progress;
} else {
readLen = transactionParams.remoteCfg.maxFileSegmentLen;
}
}
FileOpParams fileParams(transactionParams.sourceName.data(), readLen);
fileParams.offset = transactionParams.progress;
ReturnValue_t result =
sourceParams.user.vfs.readFromFile(fileParams, fileBuf.data(), fileBuf.size());
if (result != returnvalue::OK) {
addError(result);
return result;
}
auto fileDataInfo = FileDataInfo(offset, fileBuf.data(), readLen);
auto fileDataPdu = FileDataCreator(transactionParams.pduConf, fileDataInfo);
result = sendGenericPdu(fileDataPdu);
if (result != OK) {
return result;
}
transactionParams.progress += readLen;
if (transactionParams.progress >= fileSize) {
// Advance FSM after all file data PDUs were sent.
step = TransactionStep::SENDING_EOF;
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() {
auto eofInfo =
EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize);
auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo);
ReturnValue_t result = sendGenericPdu(eofPdu);
if (result != OK) {
return result;
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::initialize() {
if (fsfwParams.tmStore == nullptr) {
fsfwParams.tmStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (fsfwParams.tmStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.tcStore == nullptr) {
fsfwParams.tcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (fsfwParams.tcStore == nullptr) {
return FAILED;
}
}
if (fsfwParams.msgQueue == nullptr) {
return FAILED;
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
uint8_t* dataPtr;
store_address_t storeId;
ReturnValue_t result =
fsfwParams.tmStore->getFreeElement(&storeId, pdu.getSerializedSize(), &dataPtr);
if (result != OK) {
addError(result);
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
if (result == StorageManagerIF::DATA_STORAGE_FULL) {
return TM_STORE_FULL;
}
return result;
}
size_t serializedLen = 0;
result = pdu.serializeBe(dataPtr, serializedLen, pdu.getSerializedSize());
if (result != OK) {
addError(result);
return result;
}
TmTcMessage tmMsg(storeId);
result =
fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg);
if (result != OK) {
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
}
if (result == MessageQueueIF::FULL) {
return TARGET_MSG_QUEUE_FULL;
} else if (result == OK) {
fsmResult.packetsSent += 1;
}
return result;
}
ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() {
if (sourceParams.cfg.indicCfg.transactionFinishedIndicRequired) {
cfdp::TransactionFinishedParams params(transactionParams.id, ConditionCode::NO_ERROR,
FileDeliveryCode::DATA_COMPLETE,
FileDeliveryStatus::RETAINED_IN_FILESTORE);
sourceParams.user.transactionFinishedIndication(params);
}
return OK;
}
ReturnValue_t cfdp::SourceHandler::reset() {
step = TransactionStep::IDLE;
state = cfdp::CfdpState::IDLE;
fsmResult.callStatus = CallStatus::DONE;
transactionParams.reset();
return OK;
}
cfdp::CfdpState cfdp::SourceHandler::getState() const { return state; }
cfdp::SourceHandler::TransactionStep cfdp::SourceHandler::getStep() const { return step; }
void cfdp::SourceHandler::addError(ReturnValue_t error) {
if (fsmResult.errors < fsmResult.errorCodes.size()) {
fsmResult.errorCodes[fsmResult.errors] = error;
fsmResult.errors++;
fsmResult.result = error;
}
}

View File

@ -1,110 +0,0 @@
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
#include <cstdint>
#include <vector>
#include "UserBase.h"
#include "defs.h"
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/handler/PutRequest.h"
#include "fsfw/cfdp/handler/mib.h"
#include "fsfw/events/EventReportingProxyIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
#include "fsfw/util/ProvidesSeqCountIF.h"
namespace cfdp {
struct SourceHandlerParams {
SourceHandlerParams(LocalEntityCfg cfg, UserBase& user, ProvidesSeqCountIF& seqCountProvider)
: cfg(std::move(cfg)), user(user), seqCountProvider(seqCountProvider) {}
LocalEntityCfg cfg;
UserBase& user;
ProvidesSeqCountIF& seqCountProvider;
};
class SourceHandler {
public:
enum class TransactionStep : uint8_t {
IDLE = 0,
TRANSACTION_START = 1,
SENDING_METADATA = 3,
SENDING_FILE_DATA = 4,
SENDING_EOF = 5,
WAIT_FOR_ACK = 6,
WAIT_FOR_FINISH = 7,
NOTICE_OF_COMPLETION = 8
};
struct FsmResult {
public:
ReturnValue_t result = returnvalue::OK;
CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
CfdpState state = CfdpState::IDLE;
uint32_t packetsSent = 0;
uint8_t errors = 0;
std::array<ReturnValue_t, 3> errorCodes = {};
};
SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams);
[[nodiscard]] CfdpState getState() const;
[[nodiscard]] TransactionStep getStep() const;
/**
* Pass a put request to the source handler, which might initiate a CFDP transaction and start
* the state machine
* @return
*/
ReturnValue_t transactionStart(PutRequest& putRequest, RemoteEntityCfg& cfg);
const FsmResult& stateMachine();
ReturnValue_t initialize();
private:
struct TransactionParams {
uint32_t crc{};
std::array<char, UINT8_MAX + 1> sourceName{};
size_t sourceNameSize = 0;
std::array<char, UINT8_MAX + 1> destName{};
size_t destNameSize = 0;
cfdp::Fss fileSize;
size_t progress = 0;
bool closureRequested = false;
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
RemoteEntityCfg remoteCfg;
PduConfig pduConf;
cfdp::TransactionId id{};
void reset() {
sourceNameSize = 0;
destNameSize = 0;
fileSize.setFileSize(0, false);
progress = 0;
closureRequested = false;
}
} transactionParams;
cfdp::CfdpState state = cfdp::CfdpState::IDLE;
TransactionStep step = TransactionStep::IDLE;
std::array<uint8_t, 4096> fileBuf{};
SourceHandlerParams sourceParams;
cfdp::FsfwParams fsfwParams;
FsmResult fsmResult;
FsmResult& fsmNacked();
ReturnValue_t checksumGeneration();
ReturnValue_t prepareAndSendMetadataPdu();
ReturnValue_t prepareAndSendNextFileDataPdu(bool& noFileDataPdu);
ReturnValue_t prepareAndSendEofPdu();
ReturnValue_t noticeOfCompletion();
ReturnValue_t reset();
[[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu);
void addError(ReturnValue_t error);
};
} // namespace cfdp
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H

View File

@ -6,7 +6,6 @@
#include <vector> #include <vector>
#include "StatusReportIF.h" #include "StatusReportIF.h"
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/VarLenFields.h" #include "fsfw/cfdp/VarLenFields.h"
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h" #include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
#include "fsfw/cfdp/tlv/MessageToUserTlv.h" #include "fsfw/cfdp/tlv/MessageToUserTlv.h"
@ -28,14 +27,14 @@ struct TransactionFinishedParams {
}; };
struct MetadataRecvdParams { struct MetadataRecvdParams {
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId, Fss fileSize) MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId)
: id(id), sourceId(sourceId), fileSize(std::move(fileSize)) {} : id(id), sourceId(sourceId) {}
const TransactionId& id; const TransactionId& id;
const EntityId& sourceId; const EntityId& sourceId;
Fss fileSize{}; uint64_t fileSize = 0;
const char* sourceFileName = ""; const char* sourceFileName = "";
const char* destFileName = ""; const char* destFileName = "";
size_t numberOfMsgsToUser = 0; size_t msgsToUserLen = 0;
const MessageToUserTlv* msgsToUserArray = nullptr; const MessageToUserTlv* msgsToUserArray = nullptr;
}; };
@ -66,10 +65,10 @@ struct FileSegmentRecvdParams {
*/ */
class UserBase { class UserBase {
friend class DestHandler; friend class DestHandler;
friend class SourceHandler;
public: public:
explicit UserBase(HasFileSystemIF& vfs); explicit UserBase(HasFileSystemIF& vfs);
virtual ~UserBase() = default;
virtual void transactionIndication(const TransactionId& id) = 0; virtual void transactionIndication(const TransactionId& id) = 0;
virtual void eofSentIndication(const TransactionId& id) = 0; virtual void eofSentIndication(const TransactionId& id) = 0;

View File

@ -1,76 +1,9 @@
#ifndef FSFW_CFDP_HANDLER_DEFS_H #ifndef FSFW_CFDP_HANDLER_DEFS_H
#define FSFW_CFDP_HANDLER_DEFS_H #define FSFW_CFDP_HANDLER_DEFS_H
#include <etl/list.h>
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
namespace cfdp { namespace cfdp {
enum class CfdpState { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED }; enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP; }
static constexpr uint8_t CID = CLASS_ID::CFDP_HANDLER;
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;
};
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;
};
template <size_t SIZE>
using PacketInfoList = etl::list<PacketInfo, SIZE>;
using PacketInfoListBase = etl::ilist<PacketInfo>;
enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
namespace events {
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
//! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode.
static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent(SSID, 5, severity::LOW);
} // namespace events
static constexpr ReturnValue_t SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0);
static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = returnvalue::makeCode(CID, 1);
static constexpr ReturnValue_t FILE_SEGMENT_LEN_INVALID = returnvalue::makeCode(CID, 2);
static constexpr ReturnValue_t SOURCE_NAME_EMPTY = returnvalue::makeCode(CID, 3);
static constexpr ReturnValue_t DEST_NAME_EMPTY = returnvalue::makeCode(CID, 4);
static constexpr ReturnValue_t WRONG_REMOTE_CFG_ENTITY_ID = returnvalue::makeCode(CID, 5);
static constexpr ReturnValue_t TARGET_MSG_QUEUE_FULL = returnvalue::makeCode(CID, 6);
static constexpr ReturnValue_t TM_STORE_FULL = returnvalue::makeCode(CID, 7);
} // namespace cfdp
#endif // FSFW_CFDP_HANDLER_DEFS_H #endif // FSFW_CFDP_HANDLER_DEFS_H

View File

@ -27,15 +27,14 @@ struct LocalEntityCfg {
}; };
struct RemoteEntityCfg { struct RemoteEntityCfg {
RemoteEntityCfg() = default;
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {} explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
EntityId remoteId; EntityId remoteId;
size_t maxFileSegmentLen = 1024; size_t maxFileSegmentLen = 2048;
bool closureRequested = false; bool closureRequested = false;
bool crcOnTransmission = false; bool crcOnTransmission = false;
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED; TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM; ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
uint8_t version = CFDP_VERSION_2; const uint8_t version = CFDP_VERSION_2;
}; };
} // namespace cfdp } // namespace cfdp

View File

@ -1,6 +1,6 @@
#include "helpers.h" #include "helpers.h"
const char* COND_CODE_STRINGS[14] = {"Unknown", static const char* COND_CODE_STRINGS[14] = {"Unknown",
"No Error", "No Error",
"Positive ACK Limit Reached", "Positive ACK Limit Reached",
"Keep Alive Limit Reached", "Keep Alive Limit Reached",

View File

@ -17,7 +17,7 @@ target_sources(
FinishedInfo.cpp FinishedInfo.cpp
FinishedPduCreator.cpp FinishedPduCreator.cpp
FinishedPduReader.cpp FinishedPduReader.cpp
MetadataGenericInfo.cpp MetadataInfo.cpp
MetadataPduCreator.cpp MetadataPduCreator.cpp
MetadataPduReader.cpp MetadataPduReader.cpp
KeepAlivePduCreator.cpp KeepAlivePduCreator.cpp

View File

@ -1,13 +1,8 @@
#include "EofInfo.h" #include "EofInfo.h"
#include <utility> EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
EntityIdTlv* faultLoc) EntityIdTlv* faultLoc)
: conditionCode(conditionCode), : conditionCode(conditionCode), checksum(checksum), fileSize(fileSize), faultLoc(faultLoc) {}
checksum(checksum),
fileSize(std::move(fileSize)),
faultLoc(faultLoc) {}
EofInfo::EofInfo(EntityIdTlv* faultLoc) EofInfo::EofInfo(EntityIdTlv* faultLoc)
: conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD), : conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
@ -21,15 +16,15 @@ cfdp::ConditionCode EofInfo::getConditionCode() const { return conditionCode; }
EntityIdTlv* EofInfo::getFaultLoc() const { return faultLoc; } EntityIdTlv* EofInfo::getFaultLoc() const { return faultLoc; }
cfdp::Fss& EofInfo::getFileSize() { return fileSize; } cfdp::FileSize& EofInfo::getFileSize() { return fileSize; }
void EofInfo::setChecksum(uint32_t checksum_) { this->checksum = checksum_; } void EofInfo::setChecksum(uint32_t checksum) { this->checksum = checksum; }
void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode_) { void EofInfo::setConditionCode(cfdp::ConditionCode conditionCode) {
this->conditionCode = conditionCode_; this->conditionCode = conditionCode;
} }
void EofInfo::setFaultLoc(EntityIdTlv* faultLoc_) { this->faultLoc = faultLoc_; } void EofInfo::setFaultLoc(EntityIdTlv* faultLoc) { this->faultLoc = faultLoc; }
size_t EofInfo::getSerializedSize(bool fssLarge) { size_t EofInfo::getSerializedSize(bool fssLarge) {
// Condition code + spare + 4 byte checksum // Condition code + spare + 4 byte checksum
@ -47,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
return size; return size;
} }
ReturnValue_t EofInfo::setFileSize(size_t fileSize_, bool isLarge) { ReturnValue_t EofInfo::setFileSize(uint64_t fileSize, bool isLarge) {
return this->fileSize.setFileSize(fileSize_, isLarge); return this->fileSize.setFileSize(fileSize, isLarge);
} }

View File

@ -1,14 +1,14 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_ #ifndef FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_ #define FSFW_SRC_FSFW_CFDP_PDU_EOFINFO_H_
#include "../Fss.h" #include "../FileSize.h"
#include "../definitions.h" #include "../definitions.h"
#include "fsfw/cfdp/tlv/EntityIdTlv.h" #include "fsfw/cfdp/tlv/EntityIdTlv.h"
struct EofInfo { struct EofInfo {
public: public:
explicit EofInfo(EntityIdTlv* faultLoc = nullptr); explicit EofInfo(EntityIdTlv* faultLoc = nullptr);
EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss 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);
@ -17,16 +17,16 @@ struct EofInfo {
[[nodiscard]] cfdp::ConditionCode getConditionCode() const; [[nodiscard]] cfdp::ConditionCode getConditionCode() const;
[[nodiscard]] EntityIdTlv* getFaultLoc() const; [[nodiscard]] EntityIdTlv* getFaultLoc() const;
cfdp::Fss& getFileSize(); cfdp::FileSize& getFileSize();
void setChecksum(uint32_t checksum); void setChecksum(uint32_t checksum);
void setConditionCode(cfdp::ConditionCode conditionCode); void setConditionCode(cfdp::ConditionCode conditionCode);
void setFaultLoc(EntityIdTlv* faultLoc); void setFaultLoc(EntityIdTlv* faultLoc);
ReturnValue_t setFileSize(size_t size, bool isLarge); ReturnValue_t setFileSize(uint64_t size, bool isLarge);
private: private:
cfdp::ConditionCode conditionCode; cfdp::ConditionCode conditionCode;
uint32_t checksum; uint32_t checksum;
cfdp::Fss fileSize; cfdp::FileSize fileSize;
EntityIdTlv* faultLoc = nullptr; EntityIdTlv* faultLoc = nullptr;
}; };

View File

@ -37,7 +37,7 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
*buffer += segmentMetadataLen; *buffer += segmentMetadataLen;
*size += segmentMetadataLen; *size += segmentMetadataLen;
} }
cfdp::Fss& 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 != returnvalue::OK) {
return result; return result;

View File

@ -1,9 +1,9 @@
#include "FileDataInfo.h" #include "FileDataInfo.h"
#include <utility> FileDataInfo::FileDataInfo(cfdp::FileSize &offset, const uint8_t *fileData, size_t fileSize)
: offset(offset), fileData(fileData), fileSize(fileSize) {}
FileDataInfo::FileDataInfo(cfdp::Fss offset, const uint8_t *fileData, size_t fileSize) FileDataInfo::FileDataInfo(cfdp::FileSize &offset) : offset(offset) {}
: offset(std::move(offset)), fileData(fileData), fileSize(fileSize) {}
void FileDataInfo::setSegmentMetadataFlag(bool enable) { void FileDataInfo::setSegmentMetadataFlag(bool enable) {
if (enable) { if (enable) {
@ -71,7 +71,7 @@ const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
return segmentMetadata; return segmentMetadata;
} }
cfdp::Fss &FileDataInfo::getOffset() { return offset; } cfdp::FileSize &FileDataInfo::getOffset() { return offset; }
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) { void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
this->recContState = recContState; this->recContState = recContState;

View File

@ -1,17 +1,17 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_ #ifndef FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_ #define FSFW_SRC_FSFW_CFDP_PDU_FILEDATAINFO_H_
#include <fsfw/cfdp/Fss.h> #include <fsfw/cfdp/FileSize.h>
#include <fsfw/cfdp/definitions.h> #include <fsfw/cfdp/definitions.h>
class FileDataInfo { class FileDataInfo {
public: public:
FileDataInfo() = default; explicit FileDataInfo(cfdp::FileSize& offset);
FileDataInfo(cfdp::Fss 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; [[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
cfdp::Fss& 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);
@ -33,7 +33,7 @@ class FileDataInfo {
private: private:
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT; cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION; cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
cfdp::Fss offset; cfdp::FileSize& offset;
const uint8_t* fileData = nullptr; const uint8_t* fileData = nullptr;
size_t fileSize = 0; size_t fileSize = 0;
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END; cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;

View File

@ -1,5 +1,10 @@
#include "FinishedPduReader.h" #include "FinishedPduReader.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info) FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {} : FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}

View File

@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
*buffer += 1; *buffer += 1;
**buffer = pduDataFieldLen & 0x00ff; **buffer = pduDataFieldLen & 0x00ff;
*buffer += 1; *buffer += 1;
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) | **buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1); pduConf.seqNum.getWidth();
*buffer += 1; *buffer += 1;
*size += 4; *size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness); ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);

View File

@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
} }
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const { cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1); return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
} }
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const { cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1); return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
} }
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const { cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
@ -103,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons
} }
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width, void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
void *sourcePtr) { void *sourcePtr) const {
switch (width) { switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): { case (cfdp::WidthInBytes::ONE_BYTE): {
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr); auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
field->setValueAndWidth(width, *fieldTyped); field->setValue(width, *fieldTyped);
break; break;
} }
case (cfdp::WidthInBytes::TWO_BYTES): { case (cfdp::WidthInBytes::TWO_BYTES): {
@ -115,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
size_t deserSize = 0; size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize, SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK); SerializeIF::Endianness::NETWORK);
field->setValueAndWidth(width, fieldTyped); field->setValue(width, fieldTyped);
break; break;
} }
case (cfdp::WidthInBytes::FOUR_BYTES): { case (cfdp::WidthInBytes::FOUR_BYTES): {
@ -123,15 +123,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
size_t deserSize = 0; size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize, SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK); SerializeIF::Endianness::NETWORK);
field->setValueAndWidth(width, fieldTyped); field->setValue(width, fieldTyped);
break;
}
case (cfdp::WidthInBytes::EIGHT_BYTES): {
uint64_t fieldTyped = 0;
size_t deserSize = 0;
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
SerializeIF::Endianness::NETWORK);
field->setValueAndWidth(width, fieldTyped);
break; break;
} }
} }

View File

@ -1,6 +1,6 @@
#include "KeepAlivePduCreator.h" #include "KeepAlivePduCreator.h"
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::Fss &progress) KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress)
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) { : FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
updateDirectiveFieldLen(); updateDirectiveFieldLen();
} }

View File

@ -1,12 +1,12 @@
#ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ #ifndef FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ #define FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_
#include "fsfw/cfdp/Fss.h" #include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" #include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
class KeepAlivePduCreator : public FileDirectiveCreator { class KeepAlivePduCreator : public FileDirectiveCreator {
public: public:
KeepAlivePduCreator(PduConfig& conf, cfdp::Fss& progress); KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress);
void updateDirectiveFieldLen(); void updateDirectiveFieldLen();
@ -16,7 +16,7 @@ class KeepAlivePduCreator : public FileDirectiveCreator {
Endianness streamEndianness) const override; Endianness streamEndianness) const override;
private: private:
cfdp::Fss& progress; cfdp::FileSize& progress;
}; };
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */ #endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */

View File

@ -1,6 +1,7 @@
#include "KeepAlivePduReader.h" #include "KeepAlivePduReader.h"
KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress) KeepAlivePduReader::KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize,
cfdp::FileSize& progress)
: FileDirectiveReader(pduBuf, maxSize), progress(progress) {} : FileDirectiveReader(pduBuf, maxSize), progress(progress) {}
ReturnValue_t KeepAlivePduReader::parseData() { ReturnValue_t KeepAlivePduReader::parseData() {
@ -14,4 +15,4 @@ ReturnValue_t KeepAlivePduReader::parseData() {
return progress.deSerialize(&buffer, &remLen, getEndianness()); return progress.deSerialize(&buffer, &remLen, getEndianness());
} }
cfdp::Fss& KeepAlivePduReader::getProgress() { return progress; } cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; }

View File

@ -1,19 +1,19 @@
#ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_ #ifndef FSFW_CFDP_PDU_KEEPALIVEREADER_H_
#define FSFW_CFDP_PDU_KEEPALIVEREADER_H_ #define FSFW_CFDP_PDU_KEEPALIVEREADER_H_
#include "fsfw/cfdp/Fss.h" #include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/pdu/FileDirectiveReader.h" #include "fsfw/cfdp/pdu/FileDirectiveReader.h"
class KeepAlivePduReader : public FileDirectiveReader { class KeepAlivePduReader : public FileDirectiveReader {
public: public:
KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::Fss& progress); KeepAlivePduReader(const uint8_t* pduBuf, size_t maxSize, cfdp::FileSize& progress);
ReturnValue_t parseData() override; ReturnValue_t parseData() override;
cfdp::Fss& getProgress(); cfdp::FileSize& getProgress();
private: private:
cfdp::Fss& progress; cfdp::FileSize& progress;
}; };
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */ #endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */

View File

@ -1,35 +0,0 @@
#include "MetadataGenericInfo.h"
MetadataGenericInfo::MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType,
cfdp::Fss fileSize)
: MetadataGenericInfo(std::move(fileSize)) {
this->closureRequested = closureRequested;
this->checksumType = checksumType;
}
MetadataGenericInfo::MetadataGenericInfo(cfdp::Fss fileSize) : fileSize(std::move(fileSize)) {}
cfdp::ChecksumType MetadataGenericInfo::getChecksumType() const { return checksumType; }
void MetadataGenericInfo::setChecksumType(cfdp::ChecksumType checksumType_) {
checksumType = checksumType_;
}
bool MetadataGenericInfo::isClosureRequested() const { return closureRequested; }
void MetadataGenericInfo::setClosureRequested(bool closureRequested_) {
closureRequested = closureRequested_;
}
const cfdp::Fss& MetadataGenericInfo::getFileSize() const { return fileSize; }
size_t MetadataGenericInfo::getSerializedSize(bool fssLarge) {
// 1 byte + minimal FSS 4 bytes
size_t size = 5;
if (fssLarge) {
size += 4;
}
return size;
}
cfdp::Fss& MetadataGenericInfo::getMutFileSize() { return fileSize; }

View File

@ -1,35 +0,0 @@
#ifndef FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#define FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_
#include <optional>
#include "fsfw/cfdp/Fss.h"
#include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/tlv/Lv.h"
#include "fsfw/cfdp/tlv/StringLv.h"
#include "fsfw/cfdp/tlv/Tlv.h"
class MetadataGenericInfo {
public:
MetadataGenericInfo() = default;
explicit MetadataGenericInfo(cfdp::Fss fileSize);
MetadataGenericInfo(bool closureRequested, cfdp::ChecksumType checksumType, cfdp::Fss fileSize);
static size_t getSerializedSize(bool fssLarge = false);
[[nodiscard]] cfdp::ChecksumType getChecksumType() const;
void setChecksumType(cfdp::ChecksumType checksumType);
[[nodiscard]] bool isClosureRequested() const;
void setClosureRequested(bool closureRequested = false);
[[nodiscard]] const cfdp::Fss& getFileSize() const;
cfdp::Fss& getMutFileSize();
private:
bool closureRequested = false;
cfdp::ChecksumType checksumType = cfdp::ChecksumType::NULL_CHECKSUM;
cfdp::Fss fileSize;
};
#endif /* FSFW_SRC_FSFW_CFDP_PDU_METADATAINFO_H_ */

View File

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

View File

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

View File

@ -1,26 +1,12 @@
#include "MetadataPduCreator.h" #include "MetadataPduCreator.h"
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataGenericInfo &info, MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info)
cfdp::StringLv &srcFileName, cfdp::StringLv &destFileName, : FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) {
cfdp::Tlv **optionsArray, size_t optionsLen)
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5),
info(info),
srcFileName(srcFileName),
destFileName(destFileName),
optionsArray(optionsArray),
optionsLen(optionsLen) {
updateDirectiveFieldLen(); updateDirectiveFieldLen();
} }
void MetadataPduCreator::updateDirectiveFieldLen() { void MetadataPduCreator::updateDirectiveFieldLen() {
size_t dirFieldLen = MetadataGenericInfo::getSerializedSize(HeaderCreator::getLargeFileFlag()) + setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
srcFileName.getSerializedSize() + destFileName.getSerializedSize();
if (optionsLen > 0 and optionsArray != nullptr) {
for (size_t idx = 0; idx < optionsLen; idx++) {
dirFieldLen += optionsArray[idx]->getSerializedSize();
}
}
setDirectiveDataFieldLen(dirFieldLen);
} }
size_t MetadataPduCreator::getSerializedSize() const { size_t MetadataPduCreator::getSerializedSize() const {
@ -43,18 +29,21 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
result = srcFileName.serialize(buffer, size, maxSize, streamEndianness); result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
result = destFileName.serialize(buffer, size, maxSize, streamEndianness); result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
if (optionsLen > 0 and optionsArray != nullptr) { if (info.hasOptions()) {
for (size_t idx = 0; idx < optionsLen; idx++) { cfdp::Tlv **optsArray = nullptr;
result = optionsArray[idx]->serialize(buffer, size, maxSize, streamEndianness); size_t optsLen = 0;
info.getOptions(&optsArray, &optsLen, nullptr);
for (size_t idx = 0; idx < optsLen; idx++) {
result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
@ -62,5 +51,3 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
} }
return result; return result;
} }
const cfdp::StringLv &MetadataPduCreator::getSourceFileName() const { return srcFileName; }
const cfdp::StringLv &MetadataPduCreator::getDestFileName() const { return destFileName; }

View File

@ -2,30 +2,22 @@
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ #define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" #include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h" #include "fsfw/cfdp/pdu/MetadataInfo.h"
class MetadataPduCreator : public FileDirectiveCreator { class MetadataPduCreator : public FileDirectiveCreator {
public: public:
MetadataPduCreator(PduConfig& conf, MetadataGenericInfo& info, cfdp::StringLv& srcFileName, MetadataPduCreator(PduConfig& conf, MetadataInfo& info);
cfdp::StringLv& destFileName, cfdp::Tlv** optionsArray, size_t optionsLen);
void updateDirectiveFieldLen(); void updateDirectiveFieldLen();
[[nodiscard]] size_t getSerializedSize() const override; [[nodiscard]] size_t getSerializedSize() const override;
const cfdp::StringLv& getSourceFileName() const;
const cfdp::StringLv& getDestFileName() const;
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; using FileDirectiveCreator::serialize;
private: private:
MetadataGenericInfo& info; MetadataInfo& info;
cfdp::StringLv& srcFileName;
cfdp::StringLv& destFileName;
cfdp::Tlv** optionsArray;
size_t optionsLen;
}; };
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */ #endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */

View File

@ -1,15 +1,9 @@
#include "MetadataPduReader.h" #include "MetadataPduReader.h"
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info)
MetadataGenericInfo& info, cfdp::Tlv* optionsArray, : FileDirectiveReader(pduBuf, maxSize), info(info) {}
size_t optArrayMaxSize)
: FileDirectiveReader(pduBuf, maxSize),
info(info),
optionArray(optionsArray),
optionArrayMaxSize(optArrayMaxSize) {}
ReturnValue_t MetadataPduReader::parseData() { ReturnValue_t MetadataPduReader::parseData() {
parsedOptions = 0;
ReturnValue_t result = FileDirectiveReader::parseData(); ReturnValue_t result = FileDirectiveReader::parseData();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
@ -25,43 +19,39 @@ ReturnValue_t MetadataPduReader::parseData() {
remSize -= 1; remSize -= 1;
buf += 1; buf += 1;
auto endianness = getEndianness(); auto endianness = getEndianness();
result = info.getMutFileSize().deSerialize(&buf, &remSize, endianness); result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
result = srcFileName.deSerialize(&buf, &remSize, endianness); result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
result = destFileName.deSerialize(&buf, &remSize, endianness); result = info.getDestFileName().deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
info.setOptionsLen(0);
if (remSize > 0) { if (remSize > 0) {
if (optionArrayMaxSize == 0 or optionArray == nullptr) { if (not info.canHoldOptions()) {
return cfdp::METADATA_CANT_PARSE_OPTIONS; return cfdp::METADATA_CANT_PARSE_OPTIONS;
} }
cfdp::Tlv** optionsArray = nullptr;
size_t optsMaxLen = 0;
size_t optsIdx = 0; size_t optsIdx = 0;
info.getOptions(&optionsArray, nullptr, &optsMaxLen);
while (remSize > 0) { while (remSize > 0) {
if (optsIdx > optionArrayMaxSize) { if (optsIdx > optsMaxLen) {
return cfdp::METADATA_CANT_PARSE_OPTIONS; return cfdp::METADATA_CANT_PARSE_OPTIONS;
} }
result = optionArray[optsIdx].deSerialize(&buf, &remSize, endianness); result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
optsIdx++; optsIdx++;
} }
parsedOptions = optsIdx; info.setOptionsLen(optsIdx);
} }
return result; return result;
} }
size_t MetadataPduReader::getNumberOfParsedOptions() const { return parsedOptions; }
const cfdp::StringLv& MetadataPduReader::getSourceFileName() const { return srcFileName; }
const cfdp::StringLv& MetadataPduReader::getDestFileName() const { return destFileName; }
const MetadataGenericInfo& MetadataPduReader::getGenericInfo() const { return info; }

View File

@ -2,28 +2,16 @@
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_ #define FSFW_CFDP_PDU_METADATAPDUREADER_H_
#include "fsfw/cfdp/pdu/FileDirectiveReader.h" #include "fsfw/cfdp/pdu/FileDirectiveReader.h"
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h" #include "fsfw/cfdp/pdu/MetadataInfo.h"
class MetadataPduReader : public FileDirectiveReader { class MetadataPduReader : public FileDirectiveReader {
public: public:
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataGenericInfo& info, MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
cfdp::Tlv* optionsArray, size_t optArrayMaxSize);
ReturnValue_t parseData() override; ReturnValue_t parseData() override;
[[nodiscard]] const MetadataGenericInfo& getGenericInfo() const;
[[nodiscard]] const cfdp::StringLv& getSourceFileName() const;
[[nodiscard]] const cfdp::StringLv& getDestFileName() const;
[[nodiscard]] size_t getNumberOfParsedOptions() const;
private: private:
cfdp::StringLv srcFileName; MetadataInfo& info;
cfdp::StringLv destFileName;
MetadataGenericInfo& info;
cfdp::Tlv* optionArray;
size_t optionArrayMaxSize;
size_t parsedOptions = 0;
}; };
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */ #endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */

View File

@ -1,6 +1,6 @@
#include "NakInfo.h" #include "NakInfo.h"
NakInfo::NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope) NakInfo::NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope)
: startOfScope(startOfScope), endOfScope(endOfScope) {} : startOfScope(startOfScope), endOfScope(endOfScope) {}
size_t NakInfo::getSerializedSize(bool fssLarge) { size_t NakInfo::getSerializedSize(bool fssLarge) {
@ -57,9 +57,9 @@ void NakInfo::setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmen
} }
} }
cfdp::Fss& NakInfo::getStartOfScope() { return startOfScope; } cfdp::FileSize& NakInfo::getStartOfScope() { return startOfScope; }
cfdp::Fss& NakInfo::getEndOfScope() { return endOfScope; } cfdp::FileSize& NakInfo::getEndOfScope() { return endOfScope; }
size_t NakInfo::getSegmentRequestsLen() const { return segmentRequestsLen; } size_t NakInfo::getSegmentRequestsLen() const { return segmentRequestsLen; }

View File

@ -3,21 +3,21 @@
#include <utility> #include <utility>
#include "fsfw/cfdp/Fss.h" #include "fsfw/cfdp/FileSize.h"
class NakInfo { class NakInfo {
public: public:
using SegmentRequest = std::pair<cfdp::Fss, cfdp::Fss>; using SegmentRequest = std::pair<cfdp::FileSize, cfdp::FileSize>;
NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope); NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope);
void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen, void setSegmentRequests(SegmentRequest* segmentRequests, size_t* segmentRequestLen,
size_t* maxSegmentRequestLen); size_t* maxSegmentRequestLen);
size_t getSerializedSize(bool fssLarge = false); size_t getSerializedSize(bool fssLarge = false);
cfdp::Fss& getStartOfScope(); cfdp::FileSize& getStartOfScope();
cfdp::Fss& getEndOfScope(); cfdp::FileSize& getEndOfScope();
bool hasSegmentRequests() const; bool hasSegmentRequests() const;
bool canHoldSegmentRequests() const; bool canHoldSegmentRequests() const;
@ -31,8 +31,8 @@ class NakInfo {
void setSegmentRequestLen(size_t readLen); void setSegmentRequestLen(size_t readLen);
private: private:
cfdp::Fss startOfScope; cfdp::FileSize startOfScope;
cfdp::Fss endOfScope; cfdp::FileSize endOfScope;
SegmentRequest* segmentRequests = nullptr; SegmentRequest* segmentRequests = nullptr;
size_t segmentRequestsLen = 0; size_t segmentRequestsLen = 0;
size_t maxSegmentRequestsLen = 0; size_t maxSegmentRequestsLen = 0;

View File

@ -4,7 +4,7 @@
#include <vector> #include <vector>
#include "NakInfo.h" #include "NakInfo.h"
#include "fsfw/cfdp/Fss.h" #include "fsfw/cfdp/FileSize.h"
#include "fsfw/cfdp/definitions.h" #include "fsfw/cfdp/definitions.h"
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h" #include "fsfw/cfdp/pdu/FileDirectiveCreator.h"

View File

@ -105,8 +105,7 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
* @return * @return
*/ */
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override; ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const;
void* sourcePtr);
void* sourceIdRaw = nullptr; void* sourceIdRaw = nullptr;
void* seqNumRaw = nullptr; void* seqNumRaw = nullptr;
void* destIdRaw = nullptr; void* destIdRaw = nullptr;

View File

@ -8,5 +8,4 @@ target_sources(
StringLv.cpp StringLv.cpp
FlowLabelTlv.cpp FlowLabelTlv.cpp
MessageToUserTlv.cpp MessageToUserTlv.cpp
FaultHandlerOverrideTlv.cpp FaultHandlerOverrideTlv.cpp)
ReservedMessageCreator.cpp)

View File

@ -23,8 +23,7 @@ class EntityIdTlv : public TlvIF {
*/ */
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness); ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse using SerializeIF::deSerialize;
// the compiler
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -26,6 +26,7 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
*/ */
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness); ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -29,8 +29,7 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
*/ */
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness); ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse using SerializeIF::deSerialize;
// the compiler
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -14,6 +14,23 @@ cfdp::Lv::Lv(const std::vector<uint8_t>& data) : value(data.data(), data.size(),
cfdp::Lv::Lv() : value(static_cast<uint8_t*>(nullptr), 0, true) {} cfdp::Lv::Lv() : value(static_cast<uint8_t*>(nullptr), 0, true) {}
cfdp::Lv::Lv(const Lv& other)
: value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
if (other.value.getSerializedSize() - 1 > 0) {
zeroLen = false;
}
}
cfdp::Lv& cfdp::Lv::operator=(const Lv& other) {
size_t otherSize = 0;
auto* otherVal = const_cast<uint8_t*>(other.getValue(&otherSize));
if (otherVal == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setConstBuffer(otherVal, otherSize);
return *this;
}
ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const { Endianness streamEndianness) const {
if (maxSize < 1) { if (maxSize < 1) {
@ -32,8 +49,10 @@ ReturnValue_t cfdp::Lv::serialize(uint8_t** buffer, size_t* size, size_t maxSize
} }
size_t cfdp::Lv::getSerializedSize() const { size_t cfdp::Lv::getSerializedSize() const {
if (zeroLen or value.getConstBuffer() == nullptr) { if (zeroLen) {
return 1; return 1;
} else if (value.getConstBuffer() == nullptr) {
return 0;
} }
return value.getSerializedSize(); return value.getSerializedSize();
} }
@ -66,34 +85,7 @@ ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size,
const uint8_t* cfdp::Lv::getValue(size_t* size) const { const uint8_t* cfdp::Lv::getValue(size_t* size) const {
if (size != nullptr) { if (size != nullptr) {
// Length without length field // Length without length field
*size = getSerializedSize() - 1; *size = value.getSerializedSize() - 1;
} }
return value.getConstBuffer(); return value.getConstBuffer();
} }
cfdp::Lv::Lv(cfdp::Lv&& other) noexcept
: value(other.value.getConstBuffer(), other.value.getSerializedSize() - 1, true) {
if (other.value.getSerializedSize() - 1 > 0) {
zeroLen = false;
}
// Leave other class in intact state.
other.zeroLen = false;
other.value = SerialBufferAdapter<uint8_t>();
}
cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
size_t otherSize = 0;
this->zeroLen = false;
auto* otherVal = const_cast<uint8_t*>(other.getValue(&otherSize));
if (otherVal == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setConstBuffer(otherVal, otherSize);
// Leave other class in intact state.
other.zeroLen = false;
other.value = SerialBufferAdapter<uint8_t>();
return *this;
}
size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }
bool cfdp::Lv::isEmpty() const { return zeroLen; }

View File

@ -18,12 +18,8 @@ class Lv : public SerializeIF {
Lv(const uint8_t* value, size_t size); Lv(const uint8_t* value, size_t size);
Lv(); Lv();
// Semantically, this class is a zero-copy helper, so the copy ctor and copy assigment do not Lv(const Lv&);
// really make sense here. Lv& operator=(const Lv&);
Lv(const Lv&) = delete;
Lv& operator=(const Lv&) = delete;
Lv(Lv&&) noexcept;
Lv& operator=(Lv&&) noexcept;
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;
@ -40,8 +36,6 @@ class Lv : public SerializeIF {
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;
size_t getValueLen() const;
/** /**
* Get value field and its size. * Get value field and its size.
* @param size Optionally retrieve size. Size will be the size of the actual value field * @param size Optionally retrieve size. Size will be the size of the actual value field
@ -50,8 +44,6 @@ class Lv : public SerializeIF {
*/ */
const uint8_t* getValue(size_t* size) const; const uint8_t* getValue(size_t* size) const;
bool isEmpty() const;
private: private:
bool zeroLen = true; bool zeroLen = true;
SerialBufferAdapter<uint8_t> value; SerialBufferAdapter<uint8_t> value;

View File

@ -7,22 +7,3 @@ MessageToUserTlv::MessageToUserTlv() : Tlv() {}
MessageToUserTlv::MessageToUserTlv(const std::vector<uint8_t>& data) MessageToUserTlv::MessageToUserTlv(const std::vector<uint8_t>& data)
: Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {} : Tlv(cfdp::TlvType::MSG_TO_USER, data.data(), data.size()) {}
MessageToUserTlv::MessageToUserTlv(const uint8_t* value, size_t size)
: Tlv(cfdp::TlvType::MSG_TO_USER, value, size) {}
bool MessageToUserTlv::isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
size_t& msgLen) const {
if (cfdp::Tlv::getLengthField() < 5) {
return false;
}
if (std::strncmp(reinterpret_cast<const char*>(getValue()), "cfdp", 4) == 0) {
messageType = getValue()[4];
if (msgDataStart != nullptr) {
*msgDataStart = getValue() + 5;
}
msgLen = cfdp::Tlv::getSerializedSize() - 5;
return true;
}
return false;
}

View File

@ -9,12 +9,8 @@ class MessageToUserTlv : public cfdp::Tlv {
public: public:
MessageToUserTlv(); MessageToUserTlv();
MessageToUserTlv(uint8_t* value, size_t size); MessageToUserTlv(uint8_t* value, size_t size);
MessageToUserTlv(const uint8_t* value, size_t size);
explicit MessageToUserTlv(const std::vector<uint8_t>& data); explicit MessageToUserTlv(const std::vector<uint8_t>& data);
bool isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
size_t& msgLen) const;
private: private:
}; };

View File

@ -1,39 +0,0 @@
#include "ReservedMessageCreator.h"
cfdp::ReservedMessageCreator::ReservedMessageCreator(uint8_t messageType, uint8_t *msgData,
size_t msgLen)
: messageType(messageType), msgData(msgData), msgSize(msgLen) {}
ReturnValue_t cfdp::ReservedMessageCreator::serialize(
uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = TlvType::MSG_TO_USER;
*buffer += 1;
*size += 1;
**buffer = getSerializedSize() - 2;
*size += 1;
*buffer += 1;
std::memcpy(*buffer, MSG_HEADER, 4);
*buffer += 4;
*size += 4;
**buffer = messageType;
*buffer += 1;
*size += 1;
std::memcpy(*buffer, msgData, msgSize);
*buffer += msgSize;
*size += msgSize;
return returnvalue::OK;
}
size_t cfdp::ReservedMessageCreator::getSerializedSize() const {
// 2 bytes type and length, 4 bytes CFDP, 1 byte reserved message type, message data.
return 2 + 5 + msgSize;
}
ReturnValue_t cfdp::ReservedMessageCreator::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
return returnvalue::FAILED;
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "Tlv.h"
namespace cfdp {
class ReservedMessageCreator : public SerializeIF {
public:
static constexpr char MSG_HEADER[] = "cfdp";
ReservedMessageCreator(uint8_t messageType, uint8_t *msgData, size_t msgLen);
[[nodiscard]] 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(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
private:
uint8_t messageType;
uint8_t *msgData;
size_t msgSize;
};
} // namespace cfdp

View File

@ -7,12 +7,3 @@ cfdp::StringLv::StringLv(const char* filename, size_t len)
: Lv(reinterpret_cast<const uint8_t*>(filename), len) {} : Lv(reinterpret_cast<const uint8_t*>(filename), len) {}
cfdp::StringLv::StringLv() : Lv() {} cfdp::StringLv::StringLv() : Lv() {}
const char* cfdp::StringLv::getCString(size_t& fileSize) const {
return reinterpret_cast<const char*>(getValue(&fileSize));
}
std::string cfdp::StringLv::getString() const {
size_t fileSize;
return {getCString(fileSize), fileSize};
}

View File

@ -13,8 +13,6 @@ class StringLv : public Lv {
explicit StringLv(const std::string& fileName); explicit StringLv(const std::string& fileName);
explicit StringLv(const char* filename, size_t len); explicit StringLv(const char* filename, size_t len);
const char* getCString(size_t& fileSize) const;
std::string getString() const;
// Delete the move constructor to avoid passing in a temporary // Delete the move constructor to avoid passing in a temporary
StringLv(const std::string&&) = delete; StringLv(const std::string&&) = delete;
}; };

View File

@ -54,7 +54,6 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
return STREAM_TOO_SHORT; return STREAM_TOO_SHORT;
} }
rawData = *buffer;
uint8_t rawType = **buffer; uint8_t rawType = **buffer;
if (not checkType(rawType)) { if (not checkType(rawType)) {
return INVALID_TLV_TYPE; return INVALID_TLV_TYPE;
@ -103,5 +102,3 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; } uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }
void cfdp::Tlv::setType(TlvType type) { this->type = type; } void cfdp::Tlv::setType(TlvType type) { this->type = type; }
const uint8_t *cfdp::Tlv::getRawData() const { return rawData; }

View File

@ -47,7 +47,6 @@ class Tlv : public TlvIF {
void setValue(uint8_t *value, size_t len); void setValue(uint8_t *value, size_t len);
[[nodiscard]] const uint8_t *getValue() const; [[nodiscard]] const uint8_t *getValue() const;
[[nodiscard]] const uint8_t *getRawData() const;
void setType(TlvType type); void setType(TlvType type);
[[nodiscard]] TlvType getType() const override; [[nodiscard]] TlvType getType() const override;
[[nodiscard]] uint8_t getLengthField() const override; [[nodiscard]] uint8_t getLengthField() const override;
@ -56,7 +55,6 @@ class Tlv : public TlvIF {
bool checkType(uint8_t rawType); bool checkType(uint8_t rawType);
bool zeroLen = true; bool zeroLen = true;
const uint8_t *rawData = nullptr;
TlvType type = TlvType::INVALID_TLV; TlvType type = TlvType::INVALID_TLV;
SerialBufferAdapter<uint8_t> value; SerialBufferAdapter<uint8_t> value;
}; };

View File

@ -8,7 +8,7 @@
template <typename Tp> template <typename Tp>
class BinaryNode { class BinaryNode {
public: public:
BinaryNode(Tp* setValue) : value(setValue), left(NULL), right(NULL), parent(NULL) {} BinaryNode(Tp* setValue) : value(setValue), left(nullptr), right(nullptr), parent(nullptr) {}
Tp* value; Tp* value;
BinaryNode* left; BinaryNode* left;
BinaryNode* right; BinaryNode* right;
@ -23,31 +23,31 @@ class ExplicitNodeIterator {
typedef Tp value_type; typedef Tp value_type;
typedef Tp* pointer; typedef Tp* pointer;
typedef Tp& reference; typedef Tp& reference;
ExplicitNodeIterator() : element(NULL) {} ExplicitNodeIterator() : element(nullptr) {}
ExplicitNodeIterator(_Node* node) : element(node) {} ExplicitNodeIterator(_Node* node) : element(node) {}
BinaryNode<Tp>* element; BinaryNode<Tp>* element;
_Self up() { return _Self(element->parent); } _Self up() { return _Self(element->parent); }
_Self left() { _Self left() {
if (element != NULL) { if (element != nullptr) {
return _Self(element->left); return _Self(element->left);
} else { } else {
return _Self(NULL); return _Self(nullptr);
} }
} }
_Self right() { _Self right() {
if (element != NULL) { if (element != nullptr) {
return _Self(element->right); return _Self(element->right);
} else { } else {
return _Self(NULL); return _Self(nullptr);
} }
} }
bool operator==(const _Self& __x) const { return element == __x.element; } bool operator==(const _Self& __x) const { return element == __x.element; }
bool operator!=(const _Self& __x) const { return element != __x.element; } bool operator!=(const _Self& __x) const { return element != __x.element; }
pointer operator->() const { pointer operator->() const {
if (element != NULL) { if (element != nullptr) {
return element->value; return element->value;
} else { } else {
return NULL; return nullptr;
} }
} }
pointer operator*() const { return this->operator->(); } pointer operator*() const { return this->operator->(); }
@ -62,13 +62,13 @@ class BinaryTree {
typedef ExplicitNodeIterator<Tp> iterator; typedef ExplicitNodeIterator<Tp> iterator;
typedef BinaryNode<Tp> Node; typedef BinaryNode<Tp> Node;
typedef std::pair<iterator, iterator> children; typedef std::pair<iterator, iterator> children;
BinaryTree() : rootNode(NULL) {} BinaryTree() : rootNode(nullptr) {}
BinaryTree(Node* rootNode) : rootNode(rootNode) {} BinaryTree(Node* rootNode) : rootNode(rootNode) {}
iterator begin() const { return iterator(rootNode); } iterator begin() const { return iterator(rootNode); }
static iterator end() { return iterator(NULL); } static iterator end() { return iterator(nullptr); }
iterator insert(bool insertLeft, iterator parentNode, Node* newNode) { iterator insert(bool insertLeft, iterator parentNode, Node* newNode) {
newNode->parent = parentNode.element; newNode->parent = parentNode.element;
if (parentNode.element != NULL) { if (parentNode.element != nullptr) {
if (insertLeft) { if (insertLeft) {
parentNode.element->left = newNode; parentNode.element->left = newNode;
} else { } else {
@ -84,13 +84,13 @@ class BinaryTree {
children erase(iterator node) { children erase(iterator node) {
if (node.element == rootNode) { if (node.element == rootNode) {
// We're root node // We're root node
rootNode = NULL; rootNode = nullptr;
} else { } else {
// Delete parent's reference // Delete parent's reference
if (node.up().left() == node) { if (node.up().left() == node) {
node.up().element->left = NULL; node.up().element->left = nullptr;
} else { } else {
node.up().element->right = NULL; node.up().element->right = nullptr;
} }
} }
return children(node.element->left, node.element->right); return children(node.element->left, node.element->right);

View File

@ -12,7 +12,6 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList : public ArrayList<T, count_t> { class FixedArrayList : public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(), static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
"count_t is not large enough to hold MAX_SIZE"); "count_t is not large enough to hold MAX_SIZE");
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
private: private:
T data[MAX_SIZE]; T data[MAX_SIZE];

View File

@ -155,8 +155,8 @@ class FixedMap : public SerializeIF {
uint32_t maxSize() const { return theMap.maxSize(); } uint32_t maxSize() const { return theMap.maxSize(); }
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override { Endianness streamEndianness) const {
ReturnValue_t result = ReturnValue_t result =
SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness); SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
uint32_t i = 0; uint32_t i = 0;
@ -170,7 +170,7 @@ class FixedMap : public SerializeIF {
return result; return result;
} }
size_t getSerializedSize() const override { virtual size_t getSerializedSize() const {
uint32_t printSize = sizeof(_size); uint32_t printSize = sizeof(_size);
uint32_t i = 0; uint32_t i = 0;
@ -182,8 +182,8 @@ class FixedMap : public SerializeIF {
return printSize; return printSize;
} }
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override { Endianness streamEndianness) {
ReturnValue_t result = ReturnValue_t result =
SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness); SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
if (this->_size > theMap.maxSize()) { if (this->_size > theMap.maxSize()) {

View File

@ -61,7 +61,7 @@ class PlacementFactory {
// Need to call destructor first, in case something was allocated by the object (shouldn't do // Need to call destructor first, in case something was allocated by the object (shouldn't do
// that, however). // that, however).
thisElement->~T(); thisElement->~T();
uint8_t* pointer = (uint8_t*)(thisElement); uint8_t* pointer = static_cast<uint8_t*>(thisElement);
return dataBackend->deleteData(pointer, sizeof(T)); return dataBackend->deleteData(pointer, sizeof(T));
} }

View File

@ -1,6 +1,5 @@
#include "fsfw/container/SharedRingBuffer.h" #include "fsfw/container/SharedRingBuffer.h"
#include "SharedRingBuffer.h"
#include "fsfw/ipc/MutexFactory.h" #include "fsfw/ipc/MutexFactory.h"
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
@ -16,12 +15,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
SharedRingBuffer::~SharedRingBuffer() { SharedRingBuffer::~SharedRingBuffer() { MutexFactory::instance()->deleteMutex(mutex); }
MutexFactory::instance()->deleteMutex(mutex);
if (receiveSizesFifo != nullptr) {
delete (receiveSizesFifo);
}
}
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { this->fifoDepth = fifoDepth; } void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { this->fifoDepth = fifoDepth; }
@ -36,31 +30,18 @@ MutexIF* SharedRingBuffer::getMutexHandle() const { return mutex; }
ReturnValue_t SharedRingBuffer::initialize() { ReturnValue_t SharedRingBuffer::initialize() {
if (fifoDepth > 0) { if (fifoDepth > 0) {
receiveSizesFifo = new DynamicFIFO<size_t>(fifoDepth); receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
} }
return SystemObject::initialize(); return SystemObject::initialize();
} }
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFifo() { DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
if (receiveSizesFifo == nullptr) { if (receiveSizesFIFO == nullptr) {
// Configuration error. // Configuration error.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer" sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
<< " was not configured to have sizes FIFO, returning nullptr!" << std::endl; << " was not configured to have sizes FIFO, returning nullptr!" << std::endl;
#endif #endif
} }
return receiveSizesFifo; return receiveSizesFIFO;
} }
ReturnValue_t SharedRingBuffer::fifoEmpty(bool& empty, MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
if (receiveSizesFifo == nullptr) {
return returnvalue::FAILED;
}
MutexGuard mg(mutex, timeoutType, timeoutMs);
if (mg.getLockResult() != returnvalue::OK) {
return mg.getLockResult();
}
empty = receiveSizesFifo->empty();
return returnvalue::OK;
}

View File

@ -20,7 +20,7 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
* This constructor allocates a new internal buffer with the supplied size. * This constructor allocates a new internal buffer with the supplied size.
* @param size * @param size
* @param overwriteOld * @param overwriteOld
* If the ring buffer is overflowing at a write operation, the oldest data * If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten. * will be overwritten.
*/ */
SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld, SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld,
@ -30,7 +30,7 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
* @param buffer * @param buffer
* @param size * @param size
* @param overwriteOld * @param overwriteOld
* If the ring buffer is overflowing at a write operation, the oldest data * If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten. * will be overwritten.
*/ */
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, bool overwriteOld, SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, bool overwriteOld,
@ -78,15 +78,13 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
* Do not forget to protect access with a lock if required! * Do not forget to protect access with a lock if required!
* @return * @return
*/ */
DynamicFIFO<size_t>* getReceiveSizesFifo(); DynamicFIFO<size_t>* getReceiveSizesFIFO();
ReturnValue_t fifoEmpty(bool& empty, MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
private: private:
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
size_t fifoDepth = 0; size_t fifoDepth = 0;
DynamicFIFO<size_t>* receiveSizesFifo = nullptr; DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
}; };
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */ #endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */

View File

@ -4,31 +4,48 @@
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/subsystem/SubsystemBase.h" #include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
ControllerBase::ControllerBase(object_id_t setObjectId, size_t commandQueueDepth) ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth)
: SystemObject(setObjectId), : SystemObject(setObjectId),
parentId(parentId),
mode(MODE_OFF), mode(MODE_OFF),
submode(SUBMODE_NONE), submode(SUBMODE_NONE),
modeHelper(this), modeHelper(this),
healthHelper(this, setObjectId) { healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this)); commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); } ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t ControllerBase::initialize() { ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = modeHelper.initialize(); ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
result = healthHelper.initialize();
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == nullptr) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
return SystemObject::initialize();
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
} }
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); } MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
@ -58,7 +75,7 @@ void ControllerBase::handleQueue() {
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) { void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
changeHK(this->mode, this->submode, false); changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode_, submode_); triggerEvent(CHANGING_MODE, mode, submode);
mode = mode_; mode = mode_;
submode = submode_; submode = submode_;
modeHelper.modeChanged(mode, submode); modeHelper.modeChanged(mode, submode);
@ -72,17 +89,18 @@ void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
*submode_ = this->submode; *submode_ = this->submode;
} }
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); } void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) { ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue(); handleQueue();
performControlOperation(opCode); performControlOperation();
return returnvalue::OK; return returnvalue::OK;
} }
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
ReturnValue_t ControllerBase::setHealth(HealthState health) { ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) { switch (health) {
case HEALTHY: case HEALTHY:
@ -100,13 +118,3 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {} void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; } ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
const HasHealthIF* ControllerBase::getOptHealthIF() const { return this; }
const HasModesIF& ControllerBase::getModeIF() const { return *this; }
ModeTreeChildIF& ControllerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t ControllerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}

View File

@ -6,9 +6,6 @@
#include "fsfw/modes/HasModesIF.h" #include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeHelper.h" #include "fsfw/modes/ModeHelper.h"
#include "fsfw/objectmanager/SystemObject.h" #include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
#include "fsfw/subsystem/ModeTreeChildIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h" #include "fsfw/tasks/PeriodicTaskIF.h"
@ -21,18 +18,13 @@
class ControllerBase : public HasModesIF, class ControllerBase : public HasModesIF,
public HasHealthIF, public HasHealthIF,
public ExecutableObjectIF, public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public SystemObject { public SystemObject {
public: public:
static const Mode_t MODE_NORMAL = 2; static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, size_t commandQueueDepth = 3); ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ControllerBase() override; ~ControllerBase() override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/** SystemObject override */ /** SystemObject override */
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -46,8 +38,6 @@ class ControllerBase : public HasModesIF,
ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t performOperation(uint8_t opCode) override;
void setTaskIF(PeriodicTaskIF *task) override; void setTaskIF(PeriodicTaskIF *task) override;
ReturnValue_t initializeAfterTaskCreation() override; ReturnValue_t initializeAfterTaskCreation() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
protected: protected:
/** /**
@ -61,11 +51,13 @@ class ControllerBase : public HasModesIF,
/** /**
* Periodic helper, implemented by child class. * Periodic helper, implemented by child class.
*/ */
virtual void performControlOperation(uint8_t opCode) = 0; virtual void performControlOperation() = 0;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override = 0; uint32_t *msToReachTheMode) override = 0;
const object_id_t parentId;
Mode_t mode; Mode_t mode;
Submode_t submode; Submode_t submode;

View File

@ -1,7 +1,8 @@
#include "fsfw/controller/ExtendedControllerBase.h" #include "fsfw/controller/ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth) ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
: ControllerBase(objectId, commandQueueDepth), size_t commandQueueDepth)
: ControllerBase(objectId, parentId, commandQueueDepth),
poolManager(this, commandQueue), poolManager(this, commandQueue),
actionHelper(this, commandQueue) {} actionHelper(this, commandQueue) {}
@ -81,7 +82,7 @@ ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) { ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
handleQueue(); handleQueue();
performControlOperation(opCode); performControlOperation();
/* We do this after performing control operation because variables will be set changed /* We do this after performing control operation because variables will be set changed
in this function. */ in this function. */
poolManager.performHkOperation(); poolManager.performHkOperation();

View File

@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
public HasActionsIF, public HasActionsIF,
public HasLocalDataPoolIF { public HasLocalDataPoolIF {
public: public:
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3); ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ExtendedControllerBase() override; ~ExtendedControllerBase() override;
/* SystemObjectIF overrides */ /* SystemObjectIF overrides */
@ -44,9 +44,9 @@ class ExtendedControllerBase : public ControllerBase,
/** /**
* Periodic helper from ControllerBase, implemented by child class. * Periodic helper from ControllerBase, implemented by child class.
*/ */
void performControlOperation(uint8_t opCode) override = 0; void performControlOperation() override = 0;
// Handle the four messages mentioned above /* Handle the four messages mentioned above */
void handleQueue() override; void handleQueue() override;
/* HasActionsIF overrides */ /* HasActionsIF overrides */

View File

@ -6,8 +6,6 @@
#include "fsfw/globalfunctions/constants.h" #include "fsfw/globalfunctions/constants.h"
#include "fsfw/globalfunctions/math/MatrixOperations.h" #include "fsfw/globalfunctions/math/MatrixOperations.h"
#include "fsfw/globalfunctions/math/VectorOperations.h" #include "fsfw/globalfunctions/math/VectorOperations.h"
#include "fsfw/globalfunctions/sign.h"
#include "fsfw/serviceinterface.h"
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition, double* eciPosition, void CoordinateTransformations::positionEcfToEci(const double* ecfPosition, double* eciPosition,
timeval* timeUTC) { timeval* timeUTC) {
@ -99,16 +97,7 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates, double* e
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) { double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
timeval timeTT; timeval timeTT;
ReturnValue_t result = Clock::convertUTCToTT(timeUTC, &timeTT); Clock::convertUTCToTT(timeUTC, &timeTT);
if (result != returnvalue::OK) {
// i think it is better to continue here than to abort
timeTT = timeUTC;
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CoordinateTransformations::Conversion from UTC to TT failed. Continuing "
"calculations with UTC."
<< std::endl;
#endif
}
double jD2000TT; double jD2000TT;
Clock::convertTimevalToJD2000(timeTT, &jD2000TT); Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
@ -218,61 +207,3 @@ void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC, double T
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3); MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
}; };
void CoordinateTransformations::cartesianFromLatLongAlt(const double lat, const double longi,
const double alt, double* cartesianOutput) {
/* @brief: cartesianFromLatLongAlt() - calculates cartesian coordinates in ECEF from latitude,
* longitude and altitude
* @param: lat geodetic latitude [rad]
* longi longitude [rad]
* alt altitude [m]
* cartesianOutput Cartesian Coordinates in ECEF (3x1)
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.34ff
* Landis Markley and John L. Crassidis*/
double radiusPolar = 6356752.314;
double radiusEqua = 6378137;
double eccentricity = sqrt(1 - pow(radiusPolar, 2) / pow(radiusEqua, 2));
double auxRadius = radiusEqua / sqrt(1 - pow(eccentricity, 2) * pow(sin(lat), 2));
cartesianOutput[0] = (auxRadius + alt) * cos(lat) * cos(longi);
cartesianOutput[1] = (auxRadius + alt) * cos(lat) * sin(longi);
cartesianOutput[2] = ((1 - pow(eccentricity, 2)) * auxRadius + alt) * sin(lat);
};
void CoordinateTransformations::latLongAltFromCartesian(const double* vector, double& latitude,
double& longitude, double& altitude) {
/* @brief: latLongAltFromCartesian() - calculates latitude, longitude and altitude from
* cartesian coordinates in ECEF
* @param: x x-value of position vector [m]
* y y-value of position vector [m]
* z z-value of position vector [m]
* latitude geodetic latitude [rad]
* longitude longitude [rad]
* altitude altitude [m]
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.35 f
* Landis Markley and John L. Crassidis*/
// From World Geodetic System the Earth Radii
double a = 6378137.0; // semimajor axis [m]
double b = 6356752.3142; // semiminor axis [m]
// Calculation
double e2 = 1 - pow(b, 2) / pow(a, 2);
double epsilon2 = pow(a, 2) / pow(b, 2) - 1;
double rho = sqrt(pow(vector[0], 2) + pow(vector[1], 2));
double p = std::abs(vector[2]) / epsilon2;
double s = pow(rho, 2) / (e2 * epsilon2);
double q = pow(p, 2) - pow(b, 2) + s;
double u = p / sqrt(q);
double v = pow(b, 2) * pow(u, 2) / q;
double P = 27 * v * s / q;
double Q = pow(sqrt(P + 1) + sqrt(P), 2. / 3.);
double t = (1 + Q + 1 / Q) / 6;
double c = sqrt(pow(u, 2) - 1 + 2 * t);
double w = (c - u) / 2;
double d = sign(vector[2]) * sqrt(q) * (w + sqrt(sqrt(pow(t, 2) + v) - u * w - t / 2 - 1. / 4.));
double N = a * sqrt(1 + epsilon2 * pow(d, 2) / pow(b, 2));
latitude = asin((epsilon2 + 1) * d / N);
altitude = rho * cos(latitude) + vector[2] * sin(latitude) - pow(a, 2) / N;
longitude = atan2(vector[1], vector[0]);
}

View File

@ -23,12 +23,6 @@ class CoordinateTransformations {
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]); static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
static void cartesianFromLatLongAlt(const double lat, const double longi, const double alt,
double* cartesianOutput);
static void latLongAltFromCartesian(const double* vector, double& latitude, double& longitude,
double& altitude);
private: private:
CoordinateTransformations(); CoordinateTransformations();
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates, static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,

View File

@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
timeval timeSinceEpoch = time - epoch; timeval timeSinceEpoch = time - epoch;
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.; double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
double daysSinceEpoch = minutesSinceEpoch / 60 / 24; double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
if ((daysSinceEpoch > 7) || (daysSinceEpoch < -7)) { if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
return TLE_TOO_OLD; return TLE_TOO_OLD;
} }

View File

@ -88,18 +88,13 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(TcTransferFrame* frame)
uint32_t totalLength = frame->getDataLength(); uint32_t totalLength = frame->getDataLength();
if (totalLength > MAX_PACKET_SIZE) return CONTENT_TOO_LARGE; if (totalLength > MAX_PACKET_SIZE) return CONTENT_TOO_LARGE;
uint8_t* position = frame->getDataField(); uint8_t* position = frame->getDataField();
while ((totalLength > ccsds::HEADER_LEN)) { while ((totalLength > SpacePacketBase::MINIMUM_SIZE)) {
SpacePacketReader packet(position, totalLength); SpacePacketBase packet(position);
status = packet.checkSize(); uint32_t packetSize = packet.getFullSize();
if (status != returnvalue::OK) {
// TODO: Better error handling
status = DATA_CORRUPTED;
}
uint32_t packetSize = packet.getFullPacketLen();
if (packetSize <= totalLength) { if (packetSize <= totalLength) {
status = sendCompletePacket(packet.getFullData(), packet.getFullPacketLen()); status = sendCompletePacket(packet.getWholeData(), packet.getFullSize());
totalLength -= packet.getFullPacketLen(); totalLength -= packet.getFullSize();
position += packet.getFullPacketLen(); position += packet.getFullSize();
status = returnvalue::OK; status = returnvalue::OK;
} else { } else {
status = DATA_CORRUPTED; status = DATA_CORRUPTED;
@ -112,7 +107,7 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(TcTransferFrame* frame)
return status; return status;
} }
ReturnValue_t MapPacketExtraction::sendCompletePacket(const uint8_t* data, uint32_t size) { ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data, uint32_t size) {
store_address_t store_id; store_address_t store_id;
ReturnValue_t status = this->packetStore->addData(&store_id, data, size); ReturnValue_t status = this->packetStore->addData(&store_id, data, size);
if (status == returnvalue::OK) { if (status == returnvalue::OK) {

View File

@ -47,7 +47,7 @@ class MapPacketExtraction : public MapPacketExtractionIF {
* @param size Complete total size of the packet. * @param size Complete total size of the packet.
* @return Return Code of the Packet Store or the Message Queue. * @return Return Code of the Packet Store or the Message Queue.
*/ */
ReturnValue_t sendCompletePacket(const uint8_t* data, uint32_t size); ReturnValue_t sendCompletePacket(uint8_t* data, uint32_t size);
/** /**
* Helper method to reset the internal buffer. * Helper method to reset the internal buffer.
*/ */

View File

@ -64,8 +64,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling * - @c SET_WAS_ALREADY_READ if read() is called twice without calling
* commit() in between * commit() in between
*/ */
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override; uint32_t lockTimeout = 20) override;
/** /**
* @brief The commit call initializes writing back the registered variables. * @brief The commit call initializes writing back the registered variables.
* @details * @details
@ -84,15 +84,15 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
* - @c COMMITING_WITHOUT_READING if set was not read yet and * - @c COMMITING_WITHOUT_READING if set was not read yet and
* contains non write-only variables * contains non write-only variables
*/ */
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override; uint32_t lockTimeout = 20) override;
/** /**
* Register the passed pool variable instance into the data set. * Register the passed pool variable instance into the data set.
* @param variable * @param variable
* @return * @return
*/ */
ReturnValue_t registerVariable(PoolVariableIF* variable) override; virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
/** /**
* Provides the means to lock the underlying data structure to ensure * Provides the means to lock the underlying data structure to ensure

View File

@ -70,7 +70,8 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() { ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
return initializeHousekeepingPoolEntriesOnce(); return initializeHousekeepingPoolEntriesOnce();
} }
@ -285,7 +286,6 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updat
result = updatePacket.serialize(&storePtr, &serializedSize, updatePacketSize, result = updatePacket.serialize(&storePtr, &serializedSize, updatePacketSize,
SerializeIF::Endianness::MACHINE); SerializeIF::Endianness::MACHINE);
return result; return result;
;
} }
void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId, void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId,
@ -349,6 +349,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
if (dataSet != nullptr) { if (dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting);
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics());
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval, LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval,
owner->getPeriodicOperationFrequency()); owner->getPeriodicOperationFrequency());
} }
@ -380,6 +381,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(subdp::ParamsBase&
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
if (dataSet != nullptr) { if (dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics());
} }
hkReceivers.push_back(hkReceiver); hkReceivers.push_back(hkReceiver);
@ -463,37 +465,70 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (command) { switch (command) {
// Houskeeping interface handling. // Houskeeping interface handling.
case (HousekeepingMessage::ENABLE_PERIODIC_DIAGNOSTICS_GENERATION): {
result = togglePeriodicGeneration(sid, true, true);
break;
}
case (HousekeepingMessage::DISABLE_PERIODIC_DIAGNOSTICS_GENERATION): {
result = togglePeriodicGeneration(sid, false, true);
break;
}
case (HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): { case (HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, true); result = togglePeriodicGeneration(sid, true, false);
break; break;
} }
case (HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): { case (HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, false); result = togglePeriodicGeneration(sid, false, false);
break; break;
} }
case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): { case (HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): {
result = generateSetStructurePacket(sid); result = generateSetStructurePacket(sid, true);
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
return result; return result;
} }
break; break;
} }
case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
result = generateSetStructurePacket(sid, false);
if (result == returnvalue::OK) {
return result;
}
break;
}
case (HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL):
case (HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): { case (HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
float newCollIntvl = 0; float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl); HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
result = changeCollectionInterval(sid, newCollIntvl); if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
result = changeCollectionInterval(sid, newCollIntvl, true);
} else {
result = changeCollectionInterval(sid, newCollIntvl, false);
}
break; break;
} }
case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): { case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
case (HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) { if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage", printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
DATASET_NOT_FOUND); DATASET_NOT_FOUND);
return DATASET_NOT_FOUND; return DATASET_NOT_FOUND;
} }
if (command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT and
LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
result = WRONG_HK_PACKET_TYPE;
break;
} else if (command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT and
not LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
result = WRONG_HK_PACKET_TYPE;
break;
}
return generateHousekeepingPacket(HousekeepingMessage::getSid(message), dataSet, true); return generateHousekeepingPacket(HousekeepingMessage::getSid(message), dataSet, true);
} }
@ -534,10 +569,6 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
CommandMessage reply; CommandMessage reply;
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
if (result == WRONG_HK_PACKET_TYPE) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
WRONG_HK_PACKET_TYPE);
}
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result); HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
} else { } else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid); HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
@ -583,7 +614,11 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
/* Now we set a HK message and send it the HK packet destination. */ /* Now we set a HK message and send it the HK packet destination. */
CommandMessage hkMessage; CommandMessage hkMessage;
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId); if (LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId);
} else {
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId);
}
if (hkQueue == nullptr) { if (hkQueue == nullptr) {
/* Error, no queue available to send packet with. */ /* Error, no queue available to send packet with. */
@ -621,6 +656,10 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE); return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
} }
void LocalDataPoolManager::setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor) {
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
}
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid; sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
@ -658,7 +697,8 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
} }
} }
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool enable) { ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool enable,
bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) { if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration", printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration",
@ -666,17 +706,22 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
return DATASET_NOT_FOUND; return DATASET_NOT_FOUND;
} }
if ((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or
(not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) { (not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
return returnvalue::OK; return REPORTING_STATUS_UNCHANGED;
} }
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
float newCollectionInterval) { bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) { if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval", printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
@ -684,6 +729,11 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
return DATASET_NOT_FOUND; return DATASET_NOT_FOUND;
} }
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
PeriodicHousekeepingHelper* periodicHelper = PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet); LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
@ -696,7 +746,7 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) { ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool isDiagnostics) {
/* Get and check dataset first. */ /* Get and check dataset first. */
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) { if (dataSet == nullptr) {
@ -705,6 +755,11 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
return DATASET_NOT_FOUND; return DATASET_NOT_FOUND;
} }
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
bool valid = dataSet->isValid(); bool valid = dataSet->isValid();
bool reportingEnabled = LocalPoolDataSetAttorney::getReportingEnabled(*dataSet); bool reportingEnabled = LocalPoolDataSetAttorney::getReportingEnabled(*dataSet);
float collectionInterval = float collectionInterval =
@ -736,7 +791,11 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
// Send structure reporting reply. // Send structure reporting reply.
CommandMessage reply; CommandMessage reply;
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId); if (isDiagnostics) {
HousekeepingMessage::setDiagnosticsStuctureReportReply(&reply, sid, storeId);
} else {
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
}
result = hkQueue->reply(&reply); result = hkQueue->reply(&reply);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
@ -765,8 +824,6 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
errorPrint = "Dataset not found"; errorPrint = "Dataset not found";
} else if (error == POOLOBJECT_NOT_FOUND) { } else if (error == POOLOBJECT_NOT_FOUND) {
errorPrint = "Pool Object not found"; errorPrint = "Pool Object not found";
} else if (error == WRONG_HK_PACKET_TYPE) {
errorPrint = "Wrong Packet Type";
} else if (error == returnvalue::FAILED) { } else if (error == returnvalue::FAILED) {
if (outputType == sif::OutputTypes::OUT_WARNING) { if (outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning"; errorPrint = "Generic Warning";

View File

@ -102,7 +102,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* @param nonDiagInvlFactor * @param nonDiagInvlFactor
* @return * @return
*/ */
ReturnValue_t initializeAfterTaskCreation(); ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
/** /**
* @brief This should be called in the periodic handler of the owner. * @brief This should be called in the periodic handler of the owner.
@ -152,6 +152,17 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
MessageQueueId_t targetQueueId, MessageQueueId_t targetQueueId,
bool generateSnapshot) override; bool generateSnapshot) override;
/**
* Non-Diagnostics packets usually have a lower minimum sampling frequency
* than diagnostic packets.
* A factor can be specified to determine the minimum sampling frequency
* for non-diagnostic packets. The minimum sampling frequency of the
* diagnostics packets,which is usually jusst the period of the
* performOperation calls, is multiplied with that factor.
* @param factor
*/
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
/** /**
* @brief The manager is also able to handle housekeeping messages. * @brief The manager is also able to handle housekeeping messages.
* @details * @details
@ -174,7 +185,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet, ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
bool forDownlink, bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE); MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
HasLocalDataPoolIF* getOwner(); HasLocalDataPoolIF* getOwner();
@ -337,8 +347,10 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
size_t* serializedSize); size_t* serializedSize);
void performPeriodicHkGeneration(HkReceiver& hkReceiver); void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable); ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid); ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId); void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
void handleChangeResetLogic(DataType type, DataId dataId, MarkChangedIF* toReset); void handleChangeResetLogic(DataType type, DataId dataId, MarkChangedIF* toReset);
@ -352,6 +364,10 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void printWarningOrError(sif::OutputTypes outputType, const char* functionName, void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
ReturnValue_t errorCode = returnvalue::FAILED, ReturnValue_t errorCode = returnvalue::FAILED,
const char* errorPrint = nullptr); const char* errorPrint = nullptr);
private:
using ProvidesDataPoolSubscriptionIF::subscribeForPeriodicPacket;
using ProvidesDataPoolSubscriptionIF::subscribeForUpdatePacket;
}; };
template <class T> template <class T>

View File

@ -239,6 +239,10 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, si
} }
} }
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) { this->diagnostic = isDiagnostics; }
bool LocalPoolDataSetBase::isDiagnostics() const { return diagnostic; }
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) { void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
this->reportingEnabled = reportingEnabled; this->reportingEnabled = reportingEnabled;
} }
@ -246,8 +250,9 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; } bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval, void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval) { dur_millis_t minimumPeriodicInterval,
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval); uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
} }
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; } void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }

View File

@ -162,7 +162,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
object_id_t getCreatorObjectId(); object_id_t getCreatorObjectId();
bool getReportingEnabled() const; bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/** /**
* Returns the current periodic HK generation interval this set * Returns the current periodic HK generation interval this set
@ -182,12 +181,18 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
//! This mutex is used if the data is created by one object only. //! This mutex is used if the data is created by one object only.
MutexIF* mutexIfSingleDataCreator = nullptr; MutexIF* mutexIfSingleDataCreator = nullptr;
bool diagnostic = false;
void setDiagnostic(bool diagnostics);
bool isDiagnostics() const;
/** /**
* Used for periodic generation. * Used for periodic generation.
*/ */
bool reportingEnabled = false; bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval); void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);
/** /**
* If the valid state of a dataset is always relevant to the whole * If the valid state of a dataset is always relevant to the whole

View File

@ -87,9 +87,9 @@ class LocalPoolVariable : public LocalPoolObjectBase {
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override; SerializeIF::Endianness streamEndianness) const override;
size_t getSerializedSize() const override; virtual size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override; SerializeIF::Endianness streamEndianness) override;
/** /**
* @brief This is a call to read the array's values * @brief This is a call to read the array's values

View File

@ -98,11 +98,11 @@ class LocalPoolVector : public LocalPoolObjectBase {
T& operator[](size_t i); T& operator[](size_t i);
const T& operator[](size_t i) const; const T& operator[](size_t i) const;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndiannes) const override; SerializeIF::Endianness streamEndiannes) const override;
size_t getSerializedSize() const override; virtual size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override; SerializeIF::Endianness streamEndianness) override;
/** /**
* @brief This is a call to read the array's values * @brief This is a call to read the array's values

View File

@ -98,6 +98,11 @@ class ProvidesDataPoolSubscriptionIF {
virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0; virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0;
virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0; virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0;
// virtual ReturnValue_t
// subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics) {
// return subscribeForUpdatePacket(sid, reportingEnabled, isDiagnostics, objects::NO_OBJECT);
// }
[[deprecated( [[deprecated(
"Please use the new API which takes all arguments as one wrapper " "Please use the new API which takes all arguments as one wrapper "
"struct")]] virtual ReturnValue_t "struct")]] virtual ReturnValue_t

View File

@ -5,9 +5,17 @@
class LocalPoolDataSetAttorney { class LocalPoolDataSetAttorney {
private: private:
static void setDiagnostic(LocalPoolDataSetBase& set, bool diagnostics) {
set.setDiagnostic(diagnostics);
}
static bool isDiagnostics(LocalPoolDataSetBase& set) { return set.isDiagnostics(); }
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval, static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
uint32_t minimumPeriodicIntervalMs) { uint32_t minimumPeriodicIntervalMs,
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs); uint8_t nonDiagIntervalFactor = 5) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
nonDiagIntervalFactor);
} }
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) { static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {

View File

@ -1,7 +1,7 @@
#include "fsfw/devicehandlers/AssemblyBase.h" #include "fsfw/devicehandlers/AssemblyBase.h"
AssemblyBase::AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth) AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, MODE_OFF, commandQueueDepth), : SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
internalState(STATE_NONE), internalState(STATE_NONE),
recoveryState(RECOVERY_IDLE), recoveryState(RECOVERY_IDLE),
recoveringDevice(childrenMap.end()), recoveringDevice(childrenMap.end()),
@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) { void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode); doStartTransition(mode, submode);
triggerModeHelperEvents(mode, submode); if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
} }
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) { void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
} }
HealthState healthState = healthHelper.healthTable->getHealth(iter->first); HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) { if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY, iter->first, 0); triggerEvent(TRYING_RECOVERY);
recoveryState = RECOVERY_STARTED; recoveryState = RECOVERY_STARTED;
recoveringDevice = iter; recoveringDevice = iter;
// The user needs to take care of commanding the children off in commandChildren
doStartTransition(targetMode, targetSubmode); doStartTransition(targetMode, targetSubmode);
} else { } else {
triggerEvent(CHILD_CHANGED_HEALTH); triggerEvent(CHILD_CHANGED_HEALTH);
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
bool AssemblyBase::checkAndHandleRecovery() { bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) { switch (recoveryState) {
case RECOVERY_STARTED: case RECOVERY_STARTED:
// The recovery was already start in #handleChildrenChangedHealth and we just need
// to wait for an off time period.
// TODO: make time period configurable
recoveryState = RECOVERY_WAIT; recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer(); recoveryOffTimer.resetTimer();
return true; return true;
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
modeHelper.setForced(true); modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL); sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
} }
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}

View File

@ -12,8 +12,7 @@
* Documentation: Dissertation Baetz p.156, 157. * Documentation: Dissertation Baetz p.156, 157.
* *
* This class reduces the complexity of controller components which would * This class reduces the complexity of controller components which would
* otherwise be needed for the handling of redundant devices. However, it can also be used to * otherwise be needed for the handling of redundant devices.
* manage the mode keeping and recovery of non-redundant devices
* *
* The template class monitors mode and health state of its children * The template class monitors mode and health state of its children
* and checks availability of devices on every detected change. * and checks availability of devices on every detected change.
@ -27,9 +26,11 @@
* *
* Important: * Important:
* *
* The implementation must call #registerChild for all commanded children during initialization. * The implementation must call registerChild(object_id_t child)
* for all commanded children during initialization.
* The implementation must call the initialization function of the base class. * The implementation must call the initialization function of the base class.
* (This will call the function in SubsystemBase) * (This will call the function in SubsystemBase)
*
*/ */
class AssemblyBase : public SubsystemBase { class AssemblyBase : public SubsystemBase {
public: public:
@ -41,15 +42,14 @@ class AssemblyBase : public SubsystemBase {
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05); static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1); static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth = 8); AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8);
virtual ~AssemblyBase(); virtual ~AssemblyBase();
protected: protected:
/** /**
* Command children to reach [mode,submode] combination. Can be done by setting * Command children to reach [mode,submode] combination
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery, * Can be done by setting #commandsOutstanding correctly,
* the user needs to ensure that the target devices are healthy. If a device is not healthy, * or using executeTable()
* a recovery might be on-going and the device needs to be commanded to off first.
* @param mode * @param mode
* @param submode * @param submode
* @return * @return
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
virtual ReturnValue_t handleHealthReply(CommandMessage *message); virtual ReturnValue_t handleHealthReply(CommandMessage *message);
/** virtual void performChildOperation();
* @brief Default periodic handler
* @details
* This is the default periodic handler which will be called by the SubsystemBase
* performOperation. It performs the child transitions or reacts to changed health/mode states
* of children objects
*/
virtual void performChildOperation() override;
/**
* This function handles changed mode or health states of children
* @return
*/
bool handleChildrenChanged(); bool handleChildrenChanged();
/** /**
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
bool handleChildrenChangedHealth(); bool handleChildrenChangedHealth();
/**
* Core transition handler. The default implementation will only do something if
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
* from the #doPerformTransition call were executed successfully.
*
* Unless a second step was requested, the function will then use #checkChildrenState to
* determine whether the target mode was reached.
*
* There is some special handling for certain (internal) modes:
* - A second step is necessary. #commandChildren will be performed again
* - The device health was overwritten. #commandChildren will be called
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
*/
virtual void handleChildrenTransition(); virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
/**
* Calls #doStartTransition and triggers an informative event as well that the mode will
* change
* @param mode
* @param submode
*/
virtual void startTransition(Mode_t mode, Submode_t submode); virtual void startTransition(Mode_t mode, Submode_t submode);
/**
* This function starts the transition by setting the internal #targetSubmode and #targetMode
* variables and then calling the #commandChildren function.
* @param mode
* @param submode
*/
virtual void doStartTransition(Mode_t mode, Submode_t submode); virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition(); virtual bool isInTransition();
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
* Manages recovery of a device * Manages recovery of a device
* @return true if recovery is still ongoing, false else. * @return true if recovery is still ongoing, false else.
*/ */
virtual bool checkAndHandleRecovery(); bool checkAndHandleRecovery();
/** /**
* Helper method to overwrite health state of one of the children. * Helper method to overwrite health state of one of the children.
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
* @param objectId Must be a registered child. * @param objectId Must be a registered child.
*/ */
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth); void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
}; };
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */ #endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@ -7,5 +7,4 @@ target_sources(
DeviceHandlerFailureIsolation.cpp DeviceHandlerFailureIsolation.cpp
DeviceHandlerMessage.cpp DeviceHandlerMessage.cpp
DeviceTmReportingWrapper.cpp DeviceTmReportingWrapper.cpp
FreshDeviceHandlerBase.cpp
HealthDevice.cpp) HealthDevice.cpp)

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