Compare commits
42 Commits
38a39cf2ac
...
mohr/warni
Author | SHA1 | Date | |
---|---|---|---|
2ca9eb4204 | |||
45b686a028 | |||
329e80e7ee | |||
3772db4753 | |||
3d13ead275 | |||
e7e9ce4baf | |||
e4c11f8107 | |||
270622a5f1 | |||
4b52e5bec4 | |||
efc2773f84 | |||
87bb29a66a | |||
45963b2064 | |||
bc312243df | |||
9589d702dd | |||
c66fab90f9 | |||
3e8446ba8b | |||
e37af4fe70 | |||
941bf61f28 | |||
70fd9ff3e5 | |||
81c5b2ec95 | |||
7426e10f82 | |||
![]() |
123c81777a | ||
dcc28622a5 | |||
6d85fa155e | |||
e6af6200ae | |||
5ca3e83934 | |||
6adabb059a | |||
5d0a5cd201 | |||
adb8483bb0 | |||
fdfdce2fb0 | |||
90efb132d0 | |||
fe9804d922 | |||
a0eae66c35 | |||
e131480d5f | |||
90bafbb6de | |||
47d85fb61c | |||
39dad5f45b | |||
a993c4e0d4 | |||
fe9cc20d00 | |||
552a12a6ad | |||
13639feec6 | |||
654de0f586 |
@@ -4,5 +4,4 @@ IndentWidth: 2
|
||||
---
|
||||
Language: Cpp
|
||||
ColumnLimit: 100
|
||||
ReflowComments: true
|
||||
---
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
# PyCharm and CLion
|
||||
.idea/*
|
||||
/.idea/*
|
||||
!/.idea/runConfigurations
|
||||
!/.idea/cmake.xml
|
||||
# !/.idea/codeStyles
|
||||
!/.idea/codeStyles
|
||||
|
||||
# Eclipse
|
||||
.cproject
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -0,0 +1,3 @@
|
||||
[submodule "automation/msvc-wine"]
|
||||
path = automation/msvc-wine
|
||||
url = https://github.com/mstorsjo/msvc-wine
|
||||
|
8
.idea/cmake.xml
generated
8
.idea/cmake.xml
generated
@@ -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>
|
14
.idea/codeStyles/Project.xml
generated
Normal file
14
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<clangFormatSettings>
|
||||
<option name="ENABLED" value="true" />
|
||||
</clangFormatSettings>
|
||||
<codeStyleSettings language="CMake">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="0" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
170
CHANGELOG.md
170
CHANGELOG.md
@@ -8,90 +8,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
## Fixes
|
||||
|
||||
- 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.
|
||||
- CFDP support for PDU checksums
|
||||
|
||||
## Changed
|
||||
|
||||
- Improved File System Abstraction to be more in line with normal filesystems.
|
||||
- CFDP implementation was improved, has now even less dependencies on other FSFW components
|
||||
and allows one inserted packet per state machine call.
|
||||
- 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
|
||||
# [v6.0.0]
|
||||
|
||||
## 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
|
||||
seconds instead of uptime.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
|
||||
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
|
||||
only the X scaling factor was used.
|
||||
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
|
||||
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
|
||||
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.
|
||||
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
|
||||
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.
|
||||
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
||||
@@ -101,43 +35,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- `TcpTmTcServer.cpp`: The server was actually not able to handle
|
||||
CCSDS packets which were clumped together. This has been fixed now.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
|
||||
- `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
|
||||
|
||||
- `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.
|
||||
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
|
||||
option on the TCP server. CTOR prototype has changed and expects an explicit
|
||||
@@ -149,36 +49,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
|
||||
- Add new `UnsignedByteField` class
|
||||
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
|
||||
|
||||
- `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
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
|
||||
- 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
|
||||
- Remove default secondary header argument for
|
||||
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
||||
@@ -208,41 +85,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
||||
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
||||
- 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`:
|
||||
- Make functions `const` where it makes sense
|
||||
- Add `const char* getName const` abstract function
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
|
||||
- Generic TMTC Bridge Update
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
|
||||
- comment tweak to event parser can read everything
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
|
||||
- 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
|
||||
|
||||
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||
interface itself so it can be re-used more easily. Also add new
|
||||
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||
|
||||
## CFDP
|
||||
|
||||
@@ -262,7 +116,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
implementation without an extra component
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
||||
|
||||
# [v5.0.0] 2022-07-25
|
||||
# [v5.0.0] 25.07.2022
|
||||
|
||||
## Changes
|
||||
|
||||
|
@@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
|
||||
# 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_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")
|
||||
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_ETL_LIB_NAME etl)
|
||||
@@ -72,7 +79,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
|
||||
20
|
||||
CACHE STRING "ETL library major version requirement")
|
||||
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")
|
||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||
|
||||
@@ -80,7 +87,7 @@ set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
||||
3
|
||||
CACHE STRING "Catch2 library major version requirement")
|
||||
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")
|
||||
|
||||
# Keep this off by default for now. See PR:
|
||||
@@ -140,7 +147,7 @@ option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
||||
set(FSFW_TEST_TGT fsfw-tests)
|
||||
set(FSFW_DUMMY_TGT fsfw-dummy)
|
||||
|
||||
add_library(${LIB_FSFW_NAME} src/fsfw/cfdp/handler/PduPacketIF.h)
|
||||
add_library(${LIB_FSFW_NAME})
|
||||
|
||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||
set_property(TARGET ${LIB_FSFW_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||
@@ -158,7 +165,7 @@ if(FSFW_BUILD_TESTS)
|
||||
if(NOT Catch2_FOUND)
|
||||
message(
|
||||
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)
|
||||
|
||||
@@ -174,11 +181,29 @@ if(FSFW_BUILD_TESTS)
|
||||
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.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)
|
||||
add_executable(
|
||||
${FSFW_TEST_TGT}
|
||||
unittests/cfdp/PduSenderMock.cpp unittests/cfdp/PduSenderMock.h
|
||||
unittests/cfdp/handler/OwnedPduPacket.h)
|
||||
add_executable(${FSFW_TEST_TGT})
|
||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||
TRUE)
|
||||
@@ -204,8 +229,8 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||
message(
|
||||
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)
|
||||
|
||||
FetchContent_Declare(
|
||||
@@ -229,6 +254,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
|
||||
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
set(FSFW_CORE_INC_PATH "inc")
|
||||
@@ -363,6 +389,9 @@ if(FSFW_BUILD_TESTS)
|
||||
endif()
|
||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
|
||||
${LIB_FSFW_NAME})
|
||||
if(FSFW_OSAL MATCHES "freertos")
|
||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE FreeRTOS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
||||
@@ -450,8 +479,47 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(COMPILER_FLAGS "/permissive-")
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
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()
|
||||
|
||||
# Required include paths to compile the FSFW
|
||||
|
@@ -5,7 +5,7 @@ RUN apt-get --yes upgrade
|
||||
|
||||
#tzdata is a dependency, won't install otherwise
|
||||
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
|
||||
|
||||
@@ -21,9 +21,37 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||
cmake -B 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
|
||||
RUN adduser --uid 114 jenkins
|
||||
RUN addgroup -q --gid 117 jenkins && adduser -q --uid 114 --gid 117 jenkins
|
||||
|
||||
#add documentation server to 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
118
automation/Jenkinsfile
vendored
@@ -2,86 +2,72 @@ pipeline {
|
||||
environment {
|
||||
BUILDDIR_HOST = 'cmake-build-tests-host'
|
||||
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'
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'fsfw-ci:d6'
|
||||
image 'fsfw-ci:d9'
|
||||
args '--network host --sysctl fs.mqueue.msg_max=100'
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage('Host') {
|
||||
stages{
|
||||
stage('Clean') {
|
||||
steps {
|
||||
sh 'rm -rf $BUILDDIR_HOST'
|
||||
}
|
||||
}
|
||||
stage('Configure') {
|
||||
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('Host-clang') {
|
||||
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'
|
||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Linux') {
|
||||
stages{
|
||||
stage('Clean') {
|
||||
steps {
|
||||
sh 'rm -rf $BUILDDIR_LINUX'
|
||||
}
|
||||
stage('Linux-gcc') {
|
||||
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) {
|
||||
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('FreeRTOS-gcc') {
|
||||
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) {
|
||||
sh 'cmake --build . -j4'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('rtems-gcc') {
|
||||
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) {
|
||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Valgrind') {
|
||||
steps {
|
||||
dir(BUILDDIR_LINUX) {
|
||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Host-msvc') {
|
||||
steps {
|
||||
sh 'rm -rf $BUILDDIR_WIN'
|
||||
|
||||
dir(BUILDDIR_WIN) {
|
||||
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 ..'
|
||||
sh 'cmake --build . -j4'
|
||||
sh 'wine64 fsfw-tests.exe'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
automation/msvc-wine
Submodule
1
automation/msvc-wine
Submodule
Submodule automation/msvc-wine added at 2d2d7db0b5
@@ -51,10 +51,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
html_theme = "alabaster"
|
||||
|
||||
html_theme_options = {
|
||||
"extra_nav_links": {
|
||||
"Impressum": "https://www.uni-stuttgart.de/impressum",
|
||||
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
|
||||
}
|
||||
"extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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()
|
@@ -32,7 +32,6 @@ add_subdirectory(timemanager)
|
||||
add_subdirectory(tmtcpacket)
|
||||
add_subdirectory(tmtcservices)
|
||||
add_subdirectory(filesystem)
|
||||
add_subdirectory(util)
|
||||
|
||||
# Optional
|
||||
|
||||
|
@@ -59,24 +59,17 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
||||
|
||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress) {
|
||||
bool hasAdditionalData = false;
|
||||
const uint8_t* dataPtr = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result;
|
||||
if (dataAddress != store_address_t::invalid()) {
|
||||
hasAdditionalData = true;
|
||||
result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != returnvalue::OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != returnvalue::OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
if (hasAdditionalData) {
|
||||
ipcStore->deleteData(dataAddress);
|
||||
}
|
||||
ipcStore->deleteData(dataAddress);
|
||||
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||
|
@@ -16,8 +16,8 @@ class CommandActionHelper {
|
||||
public:
|
||||
explicit CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
|
||||
const uint8_t* data = nullptr, uint32_t size = 0);
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size);
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
|
@@ -2,9 +2,7 @@
|
||||
#define FSFW_CFDP_H
|
||||
|
||||
#include "cfdp/definitions.h"
|
||||
#include "cfdp/handler/DestHandler.h"
|
||||
#include "cfdp/handler/FaultHandlerBase.h"
|
||||
#include "cfdp/helpers.h"
|
||||
#include "cfdp/tlv/Lv.h"
|
||||
#include "cfdp/tlv/StringLv.h"
|
||||
#include "cfdp/tlv/Tlv.h"
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "fsfw/cfdp/pdu/HeaderReader.h"
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tcdistribution/CfdpPacketChecker.h"
|
||||
#include "fsfw/tcdistribution/TcDistributorBase.h"
|
||||
|
@@ -4,9 +4,8 @@ CfdpMessage::CfdpMessage() = default;
|
||||
|
||||
CfdpMessage::~CfdpMessage() = default;
|
||||
|
||||
void CfdpMessage::setPutRequest(CommandMessage *message, store_address_t putRequest) {
|
||||
message->setCommand(PUT_REQUEST);
|
||||
message->setParameter(putRequest.raw);
|
||||
void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
|
||||
message->setParameter(cfdpPacket.raw);
|
||||
}
|
||||
|
||||
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {
|
||||
|
@@ -11,11 +11,9 @@ class CfdpMessage {
|
||||
|
||||
public:
|
||||
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();
|
||||
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);
|
||||
|
||||
|
@@ -8,14 +8,11 @@
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
/**
|
||||
* Helper type for the CFDP File Size Sensitive (FSS) fields.
|
||||
*/
|
||||
struct Fss : public SerializeIF {
|
||||
struct FileSize : public SerializeIF {
|
||||
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; }
|
||||
|
||||
@@ -24,7 +21,7 @@ struct Fss : public SerializeIF {
|
||||
this->largeFile = isLarge;
|
||||
return serialize(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
using SerializeIF::serialize;
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override {
|
||||
if (not largeFile) {
|
@@ -4,7 +4,7 @@
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
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 FSFW_DISABLE_PRINTOUT == 0
|
||||
#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; }
|
||||
|
||||
ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) {
|
||||
switch (width_) {
|
||||
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, uint64_t value_) {
|
||||
switch (widthInBytes) {
|
||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||
if (value_ > UINT8_MAX) {
|
||||
return returnvalue::FAILED;
|
||||
@@ -43,14 +43,11 @@ ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uin
|
||||
this->value.fourBytes = value_;
|
||||
break;
|
||||
}
|
||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||
this->value.eightBytes = value_;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->width = width_;
|
||||
this->width = widthInBytes;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@@ -65,9 +62,6 @@ uint64_t cfdp::VarLenField::getValue() const {
|
||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||
return value.fourBytes;
|
||||
}
|
||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||
return value.eightBytes;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -90,10 +84,6 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_
|
||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||
return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||
return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
}
|
||||
default: {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
@@ -108,16 +98,11 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui
|
||||
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,
|
||||
Endianness streamEndianness) {
|
||||
switch (width) {
|
||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||
value.oneByte = **buffer;
|
||||
*buffer += 1;
|
||||
*size += 1;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@@ -127,9 +112,6 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz
|
||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||
return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness);
|
||||
}
|
||||
case (cfdp::WidthInBytes::EIGHT_BYTES): {
|
||||
return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness);
|
||||
}
|
||||
default: {
|
||||
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 {
|
||||
return not(*this == other);
|
||||
}
|
||||
|
||||
void cfdp::VarLenField::setWidth(cfdp::WidthInBytes width_) { this->width = width_; }
|
||||
|
@@ -31,9 +31,7 @@ class VarLenField : public SerializeIF {
|
||||
bool operator!=(const VarLenField &other) const;
|
||||
bool operator<(const VarLenField &other) const;
|
||||
|
||||
ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value);
|
||||
void setWidth(cfdp::WidthInBytes width);
|
||||
ReturnValue_t setValue(uint64_t value);
|
||||
ReturnValue_t setValue(cfdp::WidthInBytes, uint64_t value);
|
||||
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
@@ -53,9 +51,9 @@ class VarLenField : public SerializeIF {
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the
|
||||
// compiler
|
||||
using SerializeIF::deSerialize;
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
@@ -67,7 +65,7 @@ template <typename T>
|
||||
cfdp::VarLenField::VarLenField(UnsignedByteField<T> byteField)
|
||||
: width(static_cast<cfdp::WidthInBytes>(sizeof(T))) {
|
||||
static_assert((sizeof(T) % 2) == 0);
|
||||
setValueAndWidth(width, byteField.getValue());
|
||||
setValue(width, byteField.getValue());
|
||||
}
|
||||
|
||||
struct EntityId : public VarLenField {
|
||||
@@ -76,32 +74,6 @@ struct EntityId : public VarLenField {
|
||||
template <typename T>
|
||||
explicit EntityId(UnsignedByteField<T> byteField) : VarLenField(byteField) {}
|
||||
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 {
|
||||
|
@@ -9,6 +9,11 @@
|
||||
#include "fsfw/returnvalues/FwClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
// Thanks, windows
|
||||
#ifdef NO_ERROR
|
||||
#undef NO_ERROR
|
||||
#endif
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
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 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_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
||||
@@ -38,7 +43,6 @@ static constexpr ReturnValue_t FILESTORE_REQUIRES_SECOND_FILE =
|
||||
static constexpr ReturnValue_t FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE =
|
||||
returnvalue::makeCode(CFDP_CLASS_ID, 9);
|
||||
static constexpr ReturnValue_t INVALID_PDU_FORMAT = returnvalue::makeCode(CFDP_CLASS_ID, 10);
|
||||
static constexpr ReturnValue_t PDU_CHECKSUM_FAILURE = returnvalue::makeCode(CFDP_CLASS_ID, 11);
|
||||
|
||||
//! Checksum types according to the SANA Checksum Types registry
|
||||
//! https://sanaregistry.org/r/checksum_identifiers/
|
||||
@@ -69,7 +73,6 @@ enum WidthInBytes : uint8_t {
|
||||
ONE_BYTE = 1,
|
||||
TWO_BYTES = 2,
|
||||
FOUR_BYTES = 4,
|
||||
EIGHT_BYTES = 8
|
||||
};
|
||||
|
||||
enum FileDirective : uint8_t {
|
||||
@@ -144,20 +147,6 @@ enum RecordContinuationState {
|
||||
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
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_CFDP_PDU_DEFINITIONS_H_ */
|
||||
|
@@ -1,4 +1 @@
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE SourceHandler.cpp DestHandler.cpp PutRequest.cpp
|
||||
ReservedMessageParser.cpp FaultHandlerBase.cpp UserBase.cpp)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE FaultHandlerBase.cpp UserBase.cpp)
|
||||
|
@@ -1,512 +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/HeaderReader.h"
|
||||
#include "fsfw/objectmanager.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
cfdp::DestHandler::DestHandler(PduSenderIF& pduSender, size_t pduBufSize, DestHandlerParams params,
|
||||
FsfwParams fsfwParams)
|
||||
|
||||
: pduBuf(pduBufSize),
|
||||
pduSender(pduSender),
|
||||
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::stateMachineNoPacket() {
|
||||
return stateMachine(std::nullopt);
|
||||
}
|
||||
const cfdp::DestHandler::FsmResult& cfdp::DestHandler::stateMachine(
|
||||
const std::optional<std::reference_wrapper<PduPacketIF>> optPduPacket) {
|
||||
ReturnValue_t result;
|
||||
uint8_t errorIdx = 0;
|
||||
fsmRes.resetOfIteration();
|
||||
if (fsmRes.step == TransactionStep::IDLE) {
|
||||
if (!optPduPacket.has_value()) {
|
||||
return fsmRes;
|
||||
}
|
||||
PduPacketIF& pduPacket = *optPduPacket;
|
||||
if (pduPacket.getPduType() == FILE_DATA or
|
||||
(pduPacket.getPduType() == FILE_DIRECTIVE and *pduPacket.getFileDirective() != METADATA)) {
|
||||
fsmRes.result = DEST_NON_METADATA_PDU_AS_FIRST_PDU;
|
||||
return fsmRes;
|
||||
}
|
||||
result = handleMetadataPdu(pduPacket);
|
||||
checkAndHandleError(result, errorIdx);
|
||||
return updateFsmRes(errorIdx);
|
||||
}
|
||||
|
||||
if (fsmRes.state == CfdpState::BUSY_CLASS_1_NACKED) {
|
||||
if (fsmRes.step == TransactionStep::RECEIVING_FILE_DATA_PDUS) {
|
||||
if (!optPduPacket.has_value()) {
|
||||
return fsmRes;
|
||||
}
|
||||
PduPacketIF& pduPacket = *optPduPacket;
|
||||
if (pduPacket.getPduType() == FILE_DATA) {
|
||||
result = handleFileDataPdu(pduPacket);
|
||||
checkAndHandleError(result, errorIdx);
|
||||
|
||||
} else if (pduPacket.getPduType() == FILE_DIRECTIVE and
|
||||
*pduPacket.getFileDirective() == EOF_DIRECTIVE) {
|
||||
// TODO: Support for check timer missing
|
||||
result = handleEofPdu(pduPacket);
|
||||
checkAndHandleError(result, errorIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
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::handleMetadataPdu(const PduPacketIF& pduPacket) {
|
||||
// Process metadata PDU
|
||||
cfdp::StringLv sourceFileName;
|
||||
cfdp::StringLv destFileName;
|
||||
|
||||
MetadataGenericInfo metadataInfo(transactionParams.fileSize);
|
||||
size_t pduSize = 0;
|
||||
auto rawPdu = pduPacket.getRawPduData(pduSize);
|
||||
MetadataPduReader reader(rawPdu, pduSize, 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, rawPdu, pduSize);
|
||||
}
|
||||
return startTransaction(reader);
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const PduPacketIF& info) {
|
||||
size_t pduSize = 0;
|
||||
const auto rawPdu = info.getRawPduData(pduSize);
|
||||
// Process file data PDU
|
||||
FileDataInfo fdInfo;
|
||||
FileDataReader reader(rawPdu, pduSize, fdInfo);
|
||||
ReturnValue_t result = reader.parseData();
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
size_t fileSegmentLen = 0;
|
||||
const uint8_t* fileData = fdInfo.getFileData(&fileSegmentLen);
|
||||
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);
|
||||
}
|
||||
sif::printDebug("Writing %d bytes at offset %d\n", fileSegmentLen, fdInfo.getOffset().value());
|
||||
result = destParams.user.vfs.writeToFile(transactionParams.destName.data(),
|
||||
fdInfo.getOffset().value(), fileData, fileSegmentLen);
|
||||
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;
|
||||
}
|
||||
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::PduPacketIF& info) {
|
||||
size_t pduSize = 0;
|
||||
const auto rawPdu = info.getRawPduData(pduSize);
|
||||
// Process EOF PDU
|
||||
EofInfo eofInfo(nullptr);
|
||||
EofPduReader reader(rawPdu, pduSize, 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
|
||||
sif::printWarning("cfdp::DestHandler: parsing metadata PDU failed with code %04x\n", result);
|
||||
#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;
|
||||
// handling to allow only specifying target directory. Example:
|
||||
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
|
||||
bool isDirectory = false;
|
||||
|
||||
result = destParams.user.vfs.isDirectory(transactionParams.destName.data(), isDirectory);
|
||||
if (result == returnvalue::OK && isDirectory) {
|
||||
result = tryBuildingAbsoluteDestName(destNameSize);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (destParams.user.vfs.fileExists(transactionParams.destName.data())) {
|
||||
result = destParams.user.vfs.truncateFile(transactionParams.destName.data());
|
||||
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(transactionParams.destName.data());
|
||||
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.crcFlag = transactionParams.remoteCfg->crcOnTransmission;
|
||||
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 (uint32_t tlvIdx = 0; tlvIdx < reader.getNumberOfParsedOptions(); tlvIdx++) {
|
||||
if (tlvVec[tlvIdx].getType() == TlvType::MSG_TO_USER) {
|
||||
msgToUserVec[params.numberOfMsgsToUser] =
|
||||
MessageToUserTlv(tlvVec[tlvIdx].getValue(), tlvVec[tlvIdx].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]{};
|
||||
size_t baseNameLen = 0;
|
||||
const ReturnValue_t result = destParams.user.vfs.getBaseFilename(
|
||||
transactionParams.sourceName.data(), 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();
|
||||
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;
|
||||
while (currentOffset < transactionParams.fileSize.value()) {
|
||||
uint64_t lenToRead;
|
||||
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
|
||||
lenToRead = transactionParams.fileSize.value() - currentOffset;
|
||||
} else {
|
||||
lenToRead = buf.size();
|
||||
}
|
||||
if (lenToRead > 0) {
|
||||
size_t readLen = 0;
|
||||
const auto result =
|
||||
destParams.user.vfs.readFromFile(transactionParams.destName.data(), currentOffset,
|
||||
lenToRead, buf.data(), readLen, 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() + lenToRead);
|
||||
}
|
||||
currentOffset += lenToRead;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
size_t serLen = 0;
|
||||
ReturnValue_t result =
|
||||
finishedPdu.serialize(pduBuf.data(), serLen, finishedPdu.getSerializedSize());
|
||||
checkAndHandleError(result, fsmRes.errors);
|
||||
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;
|
||||
}
|
||||
pduSender.sendPdu(PduType::FILE_DIRECTIVE, FileDirective::FINISH, pduBuf.data(), serLen);
|
||||
if (result != OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "cfdp::DestHandler::sendFinishedPdu: Sending PDU failed" << std::endl;
|
||||
#endif
|
||||
fsfwParams.eventReporter->forwardEvent(events::PDU_SEND_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::setEventReporter(EventReportingProxyIF& reporter) {
|
||||
fsfwParams.eventReporter = &reporter;
|
||||
}
|
||||
|
||||
const cfdp::DestHandlerParams& cfdp::DestHandler::getDestHandlerParams() const {
|
||||
return destParams;
|
||||
}
|
@@ -1,183 +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/PduPacketIF.h"
|
||||
#include "fsfw/cfdp/handler/PduSenderIF.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/storagemanager/StorageManagerIF.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,
|
||||
// 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),
|
||||
lostSegmentsContainer(lostSegmentsContainer) {}
|
||||
|
||||
LocalEntityCfg cfg;
|
||||
UserBase& user;
|
||||
RemoteConfigTableIF& remoteCfgTable;
|
||||
|
||||
LostSegmentsListBase& lostSegmentsContainer;
|
||||
uint8_t maxTlvsInOnePdu = 20;
|
||||
size_t maxFilenameLen = 255;
|
||||
};
|
||||
|
||||
struct PacketInfo {
|
||||
const uint8_t* rawPdu = nullptr;
|
||||
size_t pduSize = 0;
|
||||
PduType pduType = PduType::FILE_DATA;
|
||||
std::optional<FileDirective> directiveType = FileDirective::INVALID_DIRECTIVE;
|
||||
};
|
||||
|
||||
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 {
|
||||
uint32_t packetsSent = 0;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
TransactionStep step = TransactionStep::IDLE;
|
||||
CfdpState state = CfdpState::IDLE;
|
||||
uint8_t errors = 0;
|
||||
std::array<ReturnValue_t, 3> errorCodes = {};
|
||||
void resetOfIteration() {
|
||||
result = returnvalue::OK;
|
||||
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(PduSenderIF& pduSender, size_t pduBufSize, DestHandlerParams handlerParams,
|
||||
FsfwParams fsfwParams);
|
||||
|
||||
/**
|
||||
* This is the core function to drive the destination handler. It is also used to insert
|
||||
* packets into the destination handler.
|
||||
*
|
||||
* The state machine should either be called if packets with the appropriate destination ID
|
||||
* are received and periodically to perform all CFDP related tasks, for example
|
||||
* checking for timeouts or missed file segments.
|
||||
*
|
||||
* The function returns the number of sent PDU packets on success.
|
||||
*/
|
||||
const FsmResult& stateMachine(std::optional<std::reference_wrapper<PduPacketIF>> optPduPacket);
|
||||
|
||||
const FsmResult& stateMachineNoPacket();
|
||||
|
||||
void setEventReporter(EventReportingProxyIF& reporter);
|
||||
|
||||
[[nodiscard]] CfdpState getCfdpState() const;
|
||||
[[nodiscard]] TransactionStep getTransactionStep() const;
|
||||
[[nodiscard]] const TransactionId& getTransactionId() const;
|
||||
[[nodiscard]] const DestHandlerParams& getDestHandlerParams() 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<uint8_t> pduBuf;
|
||||
PduSenderIF& pduSender;
|
||||
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 PduPacketIF& pduPacket);
|
||||
ReturnValue_t handleFileDataPdu(const PduPacketIF& info);
|
||||
ReturnValue_t handleEofPdu(const PduPacketIF& 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
|
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class PduPacketIF {
|
||||
public:
|
||||
virtual ~PduPacketIF() = default;
|
||||
|
||||
[[nodiscard]] virtual cfdp::PduType getPduType() const = 0;
|
||||
[[nodiscard]] virtual std::optional<cfdp::FileDirective> getFileDirective() const = 0;
|
||||
[[nodiscard]] virtual const uint8_t* getRawPduData(size_t& pduLen) const = 0;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
|
||||
namespace cfdp {
|
||||
class PduSenderIF {
|
||||
public:
|
||||
virtual ~PduSenderIF() = default;
|
||||
|
||||
virtual ReturnValue_t sendPdu(cfdp::PduType pduType,
|
||||
std::optional<cfdp::FileDirective> fileDirective,
|
||||
const uint8_t* pdu, size_t pduSize) = 0;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
@@ -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;
|
||||
}
|
@@ -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
|
@@ -16,7 +16,7 @@ class RemoteConfigTableIF {
|
||||
*/
|
||||
class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
||||
public:
|
||||
explicit OneRemoteConfigProvider(RemoteEntityCfg& cfg) : cfg(cfg) {}
|
||||
explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
|
||||
|
||||
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
|
||||
if (remoteId != cfg.remoteId) {
|
||||
@@ -27,7 +27,7 @@ class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
||||
}
|
||||
|
||||
private:
|
||||
RemoteEntityCfg& cfg;
|
||||
RemoteEntityCfg cfg;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
@@ -1,71 +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) const {
|
||||
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++) {
|
||||
uint8_t messageType = 0;
|
||||
if (not msgsToUserArray[idx].isReservedCfdpMessage(messageType, ¤tPtr, deserSize)) {
|
||||
continue;
|
||||
}
|
||||
if (messageType == static_cast<uint8_t>(ProxyOpMessageType::PUT_REQUEST)) {
|
||||
EntityId entityIdLv;
|
||||
result = entityIdLv.deSerializeFromLv(¤tPtr, &deserSize);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
putRequest.setDestId(entityIdLv);
|
||||
result =
|
||||
sourceFileName.deSerialize(¤tPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
result = destFileName.deSerialize(¤tPtr, &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;
|
||||
}
|
@@ -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) const;
|
||||
|
||||
private:
|
||||
MessageQueueIF& msgQueue;
|
||||
StorageManagerIF& ipcStore;
|
||||
MessageQueueId_t userDestination;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
@@ -1,354 +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(PduSenderIF& pduSender, size_t pduBufferSize,
|
||||
SourceHandlerParams params, FsfwParams fsfwParams)
|
||||
: pduSender(pduSender),
|
||||
pduBuf(pduBufferSize),
|
||||
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;
|
||||
while (currentOffset < transactionParams.fileSize.value()) {
|
||||
uint64_t lenToRead;
|
||||
if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
|
||||
lenToRead = transactionParams.fileSize.value() - currentOffset;
|
||||
} else {
|
||||
lenToRead = buf.size();
|
||||
}
|
||||
if (lenToRead > 0) {
|
||||
size_t readLen = 0;
|
||||
auto result =
|
||||
sourceParams.user.vfs.readFromFile(transactionParams.sourceName.data(), currentOffset,
|
||||
lenToRead, buf.data(), readLen, buf.size());
|
||||
if (result != OK) {
|
||||
addError(result);
|
||||
return FAILED;
|
||||
}
|
||||
crcCalc.add(buf.begin(), buf.begin() + lenToRead);
|
||||
}
|
||||
currentOffset += lenToRead;
|
||||
}
|
||||
|
||||
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';
|
||||
if (!sourceParams.user.vfs.fileExists(transactionParams.sourceName.data())) {
|
||||
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(transactionParams.sourceName.data(), 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(PduType::FILE_DIRECTIVE, FileDirective::METADATA, 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 lenToRead;
|
||||
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) {
|
||||
lenToRead = transactionParams.fileSize.value();
|
||||
} else {
|
||||
if (transactionParams.progress + transactionParams.remoteCfg.maxFileSegmentLen > fileSize) {
|
||||
lenToRead = fileSize - transactionParams.progress;
|
||||
} else {
|
||||
lenToRead = transactionParams.remoteCfg.maxFileSegmentLen;
|
||||
}
|
||||
}
|
||||
FileOpParams fileParams(transactionParams.sourceName.data(), lenToRead);
|
||||
fileParams.offset = transactionParams.progress;
|
||||
size_t readLen = 0;
|
||||
ReturnValue_t result = sourceParams.user.vfs.readFromFile(
|
||||
transactionParams.sourceName.data(), transactionParams.progress, lenToRead, fileBuf.data(),
|
||||
readLen, fileBuf.size());
|
||||
if (result != returnvalue::OK) {
|
||||
addError(result);
|
||||
return result;
|
||||
}
|
||||
auto fileDataInfo = FileDataInfo(offset, fileBuf.data(), lenToRead);
|
||||
auto fileDataPdu = FileDataCreator(transactionParams.pduConf, fileDataInfo);
|
||||
result = sendGenericPdu(PduType::FILE_DATA, std::nullopt, fileDataPdu);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
transactionParams.progress += lenToRead;
|
||||
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(PduType::FILE_DIRECTIVE, FileDirective::EOF_DIRECTIVE, eofPdu);
|
||||
if (result != OK) {
|
||||
return result;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::SourceHandler::initialize() { return OK; }
|
||||
|
||||
ReturnValue_t cfdp::SourceHandler::sendGenericPdu(PduType pduType,
|
||||
std::optional<FileDirective> fileDirective,
|
||||
const SerializeIF& pdu) {
|
||||
store_address_t storeId;
|
||||
if (pdu.getSerializedSize() > pduBuf.size()) {
|
||||
addError(PDU_BUFFER_TOO_SMALL);
|
||||
return PDU_BUFFER_TOO_SMALL;
|
||||
}
|
||||
size_t serializedLen = 0;
|
||||
ReturnValue_t result = pdu.serializeBe(pduBuf.data(), serializedLen, pdu.getSerializedSize());
|
||||
if (result != OK) {
|
||||
addError(result);
|
||||
return result;
|
||||
}
|
||||
pduSender.sendPdu(pduType, fileDirective, pduBuf.data(), serializedLen);
|
||||
fsmResult.packetsSent += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() {
|
||||
if (sourceParams.cfg.indicCfg.transactionFinishedIndicRequired) {
|
||||
// TODO: This could still be improved by caching the Finished PDU parameters.
|
||||
FileDeliveryStatus deliveryStatus = FileDeliveryStatus::FILE_STATUS_UNREPORTED;
|
||||
if (transactionParams.closureRequested) {
|
||||
deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
|
||||
}
|
||||
cfdp::TransactionFinishedParams params(transactionParams.id, ConditionCode::NO_ERROR,
|
||||
FileDeliveryCode::DATA_COMPLETE, deliveryStatus);
|
||||
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;
|
||||
}
|
||||
}
|
@@ -1,116 +0,0 @@
|
||||
#ifndef FSFW_CFDP_CFDPSOURCEHANDLER_H
|
||||
#define FSFW_CFDP_CFDPSOURCEHANDLER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "PduSenderIF.h"
|
||||
#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;
|
||||
uint32_t packetsSent = 0;
|
||||
// CallStatus callStatus = CallStatus::CALL_AFTER_DELAY;
|
||||
CfdpState state = CfdpState::IDLE;
|
||||
uint8_t errors = 0;
|
||||
std::array<ReturnValue_t, 3> errorCodes = {};
|
||||
};
|
||||
|
||||
SourceHandler(PduSenderIF& pduSender, size_t pduBufferSize, 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;
|
||||
|
||||
PduSenderIF& pduSender;
|
||||
std::vector<uint8_t> pduBuf;
|
||||
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(PduType pduType,
|
||||
std::optional<FileDirective> fileDirective,
|
||||
const SerializeIF& pdu);
|
||||
void addError(ReturnValue_t error);
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_CFDP_CFDPSOURCEHANDLER_H
|
@@ -6,7 +6,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "StatusReportIF.h"
|
||||
#include "fsfw/cfdp/Fss.h"
|
||||
#include "fsfw/cfdp/VarLenFields.h"
|
||||
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
|
||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
||||
@@ -28,14 +27,14 @@ struct TransactionFinishedParams {
|
||||
};
|
||||
|
||||
struct MetadataRecvdParams {
|
||||
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId, Fss fileSize)
|
||||
: id(id), sourceId(sourceId), fileSize(std::move(fileSize)) {}
|
||||
MetadataRecvdParams(const TransactionId& id, const EntityId& sourceId)
|
||||
: id(id), sourceId(sourceId) {}
|
||||
const TransactionId& id;
|
||||
const EntityId& sourceId;
|
||||
Fss fileSize{};
|
||||
uint64_t fileSize = 0;
|
||||
const char* sourceFileName = "";
|
||||
const char* destFileName = "";
|
||||
size_t numberOfMsgsToUser = 0;
|
||||
size_t msgsToUserLen = 0;
|
||||
const MessageToUserTlv* msgsToUserArray = nullptr;
|
||||
};
|
||||
|
||||
@@ -66,10 +65,10 @@ struct FileSegmentRecvdParams {
|
||||
*/
|
||||
class UserBase {
|
||||
friend class DestHandler;
|
||||
friend class SourceHandler;
|
||||
|
||||
public:
|
||||
explicit UserBase(HasFileSystemIF& vfs);
|
||||
virtual ~UserBase() = default;
|
||||
|
||||
virtual void transactionIndication(const TransactionId& id) = 0;
|
||||
virtual void eofSentIndication(const TransactionId& id) = 0;
|
||||
|
@@ -1,41 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <etl/list.h>
|
||||
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
#include "fsfw/storagemanager/storeAddress.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||
#ifndef FSFW_CFDP_HANDLER_DEFS_H
|
||||
#define FSFW_CFDP_HANDLER_DEFS_H
|
||||
|
||||
namespace cfdp {
|
||||
enum class CfdpState { 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;
|
||||
enum class CfdpStates { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
|
||||
|
||||
struct FsfwParams {
|
||||
FsfwParams(EventReportingProxyIF* eventReporter) : eventReporter(eventReporter) {}
|
||||
|
||||
EventReportingProxyIF* eventReporter = nullptr;
|
||||
};
|
||||
|
||||
namespace events {
|
||||
static constexpr Event PDU_SEND_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);
|
||||
static constexpr ReturnValue_t DEST_NON_METADATA_PDU_AS_FIRST_PDU = returnvalue::makeCode(CID, 8);
|
||||
static constexpr ReturnValue_t PDU_BUFFER_TOO_SMALL = returnvalue::makeCode(CID, 9);
|
||||
} // namespace cfdp
|
||||
}
|
||||
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
||||
|
@@ -27,15 +27,14 @@ struct LocalEntityCfg {
|
||||
};
|
||||
|
||||
struct RemoteEntityCfg {
|
||||
RemoteEntityCfg() = default;
|
||||
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
|
||||
EntityId remoteId;
|
||||
size_t maxFileSegmentLen = 1024;
|
||||
size_t maxFileSegmentLen = 2048;
|
||||
bool closureRequested = false;
|
||||
bool crcOnTransmission = false;
|
||||
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
|
||||
ChecksumType defaultChecksum = ChecksumType::NULL_CHECKSUM;
|
||||
uint8_t version = CFDP_VERSION_2;
|
||||
const uint8_t version = CFDP_VERSION_2;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#include "helpers.h"
|
||||
|
||||
const char* COND_CODE_STRINGS[14] = {"Unknown",
|
||||
static const char* COND_CODE_STRINGS[14] = {"Unknown",
|
||||
"No Error",
|
||||
"Positive ACK Limit Reached",
|
||||
"Keep Alive Limit Reached",
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#include "AckPduCreator.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
AckPduCreator::AckPduCreator(AckInfo &ackInfo, PduConfig &pduConf)
|
||||
: FileDirectiveCreator(pduConf, cfdp::FileDirective::ACK, 2), ackInfo(ackInfo) {}
|
||||
|
||||
@@ -9,7 +7,6 @@ size_t AckPduCreator::getSerializedSize() const { return FileDirectiveCreator::g
|
||||
|
||||
ReturnValue_t AckPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -32,10 +29,5 @@ ReturnValue_t AckPduCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
||||
**buffer = ackedConditionCode << 4 | transactionStatus;
|
||||
*buffer += 1;
|
||||
*size += 1;
|
||||
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ target_sources(
|
||||
FinishedInfo.cpp
|
||||
FinishedPduCreator.cpp
|
||||
FinishedPduReader.cpp
|
||||
MetadataGenericInfo.cpp
|
||||
MetadataInfo.cpp
|
||||
MetadataPduCreator.cpp
|
||||
MetadataPduReader.cpp
|
||||
KeepAlivePduCreator.cpp
|
||||
|
@@ -1,13 +1,8 @@
|
||||
#include "EofInfo.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::Fss fileSize,
|
||||
EofInfo::EofInfo(cfdp::ConditionCode conditionCode, uint32_t checksum, cfdp::FileSize fileSize,
|
||||
EntityIdTlv* faultLoc)
|
||||
: conditionCode(conditionCode),
|
||||
checksum(checksum),
|
||||
fileSize(std::move(fileSize)),
|
||||
faultLoc(faultLoc) {}
|
||||
: conditionCode(conditionCode), checksum(checksum), fileSize(fileSize), faultLoc(faultLoc) {}
|
||||
|
||||
EofInfo::EofInfo(EntityIdTlv* faultLoc)
|
||||
: conditionCode(cfdp::ConditionCode::NO_CONDITION_FIELD),
|
||||
@@ -21,15 +16,15 @@ cfdp::ConditionCode EofInfo::getConditionCode() const { return conditionCode; }
|
||||
|
||||
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_) {
|
||||
this->conditionCode = conditionCode_;
|
||||
void EofInfo::setConditionCode(cfdp::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) {
|
||||
// Condition code + spare + 4 byte checksum
|
||||
@@ -47,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
|
||||
return size;
|
||||
}
|
||||
|
||||
ReturnValue_t EofInfo::setFileSize(size_t fileSize_, bool isLarge) {
|
||||
return this->fileSize.setFileSize(fileSize_, isLarge);
|
||||
ReturnValue_t EofInfo::setFileSize(uint64_t fileSize, bool isLarge) {
|
||||
return this->fileSize.setFileSize(fileSize, isLarge);
|
||||
}
|
||||
|
@@ -1,14 +1,14 @@
|
||||
#ifndef 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 "fsfw/cfdp/tlv/EntityIdTlv.h"
|
||||
|
||||
struct EofInfo {
|
||||
public:
|
||||
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);
|
||||
|
||||
size_t getSerializedSize(bool fssLarge = false);
|
||||
@@ -17,16 +17,16 @@ struct EofInfo {
|
||||
[[nodiscard]] cfdp::ConditionCode getConditionCode() const;
|
||||
|
||||
[[nodiscard]] EntityIdTlv* getFaultLoc() const;
|
||||
cfdp::Fss& getFileSize();
|
||||
cfdp::FileSize& getFileSize();
|
||||
void setChecksum(uint32_t checksum);
|
||||
void setConditionCode(cfdp::ConditionCode conditionCode);
|
||||
void setFaultLoc(EntityIdTlv* faultLoc);
|
||||
ReturnValue_t setFileSize(size_t size, bool isLarge);
|
||||
ReturnValue_t setFileSize(uint64_t size, bool isLarge);
|
||||
|
||||
private:
|
||||
cfdp::ConditionCode conditionCode;
|
||||
uint32_t checksum;
|
||||
cfdp::Fss fileSize;
|
||||
cfdp::FileSize fileSize;
|
||||
EntityIdTlv* faultLoc = nullptr;
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#include "EofPduCreator.h"
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
EofPduCreator::EofPduCreator(PduConfig &conf, EofInfo &info)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::EOF_DIRECTIVE, 9), info(info) {
|
||||
@@ -12,7 +11,6 @@ size_t EofPduCreator::getSerializedSize() const { return FileDirectiveCreator::g
|
||||
|
||||
ReturnValue_t EofPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -38,9 +36,5 @@ ReturnValue_t EofPduCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
||||
if (info.getFaultLoc() != nullptr and info.getConditionCode() != cfdp::ConditionCode::NO_ERROR) {
|
||||
result = info.getFaultLoc()->serialize(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
FileDataCreator::FileDataCreator(PduConfig& conf, FileDataInfo& info)
|
||||
: HeaderCreator(conf, cfdp::PduType::FILE_DATA, 0, info.getSegmentMetadataFlag()), info(info) {
|
||||
update();
|
||||
@@ -20,7 +18,6 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
|
||||
if (buffer == nullptr or size == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
const uint8_t* start = *buffer;
|
||||
if (*size + getSerializedSize() > maxSize) {
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
@@ -40,7 +37,7 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
|
||||
*buffer += segmentMetadataLen;
|
||||
*size += segmentMetadataLen;
|
||||
}
|
||||
cfdp::Fss& offset = info.getOffset();
|
||||
cfdp::FileSize& offset = info.getOffset();
|
||||
result = offset.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -53,11 +50,6 @@ ReturnValue_t FileDataCreator::serialize(uint8_t** buffer, size_t* size, size_t
|
||||
std::memcpy(*buffer, readOnlyPtr, fileSize);
|
||||
*buffer += fileSize;
|
||||
*size += fileSize;
|
||||
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#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)
|
||||
: offset(std::move(offset)), fileData(fileData), fileSize(fileSize) {}
|
||||
FileDataInfo::FileDataInfo(cfdp::FileSize &offset) : offset(offset) {}
|
||||
|
||||
void FileDataInfo::setSegmentMetadataFlag(bool enable) {
|
||||
if (enable) {
|
||||
@@ -71,7 +71,7 @@ const uint8_t *FileDataInfo::getSegmentMetadata(size_t *segmentMetadataLen_) {
|
||||
return segmentMetadata;
|
||||
}
|
||||
|
||||
cfdp::Fss &FileDataInfo::getOffset() { return offset; }
|
||||
cfdp::FileSize &FileDataInfo::getOffset() { return offset; }
|
||||
|
||||
void FileDataInfo::setRecordContinuationState(cfdp::RecordContinuationState recContState) {
|
||||
this->recContState = recContState;
|
||||
|
@@ -1,17 +1,17 @@
|
||||
#ifndef 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>
|
||||
|
||||
class FileDataInfo {
|
||||
public:
|
||||
FileDataInfo() = default;
|
||||
FileDataInfo(cfdp::Fss offset, const uint8_t* fileData, size_t fileSize);
|
||||
explicit FileDataInfo(cfdp::FileSize& offset);
|
||||
FileDataInfo(cfdp::FileSize& offset, const uint8_t* fileData, size_t fileSize);
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize(bool largeFile = false) const;
|
||||
|
||||
cfdp::Fss& getOffset();
|
||||
cfdp::FileSize& getOffset();
|
||||
const uint8_t* getFileData(size_t* fileSize = nullptr) const;
|
||||
void setFileData(const uint8_t* fileData, size_t fileSize);
|
||||
|
||||
@@ -33,7 +33,7 @@ class FileDataInfo {
|
||||
private:
|
||||
cfdp::SegmentMetadataFlag segmentMetadataFlag = cfdp::SegmentMetadataFlag::NOT_PRESENT;
|
||||
cfdp::SegmentationControl segCtrl = cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION;
|
||||
cfdp::Fss offset;
|
||||
cfdp::FileSize& offset;
|
||||
const uint8_t* fileData = nullptr;
|
||||
size_t fileSize = 0;
|
||||
cfdp::RecordContinuationState recContState = cfdp::RecordContinuationState::NO_START_NO_END;
|
||||
|
@@ -8,9 +8,6 @@ ReturnValue_t FileDataReader::parseData() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (not performCrcCheckIfApplicable()) {
|
||||
return cfdp::PDU_CHECKSUM_FAILURE;
|
||||
}
|
||||
size_t currentIdx = PduHeaderReader::getHeaderSize();
|
||||
const uint8_t* buf = pointers.rawPtr + currentIdx;
|
||||
size_t remSize = PduHeaderReader::getWholePduSize() - currentIdx;
|
||||
@@ -37,9 +34,6 @@ ReturnValue_t FileDataReader::parseData() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (getCrcFlag()) {
|
||||
remSize -= 2;
|
||||
}
|
||||
if (remSize > 0) {
|
||||
info.setFileData(buf, remSize);
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "FileDataInfo.h"
|
||||
#include "HeaderReader.h"
|
||||
#include "PduHeaderReader.h"
|
||||
|
||||
class FileDataReader : public PduHeaderReader {
|
||||
public:
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#include "FileDirectiveReader.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
FileDirectiveReader::FileDirectiveReader(const uint8_t *pduBuf, size_t maxSize)
|
||||
: PduHeaderReader(pduBuf, maxSize) {}
|
||||
|
||||
@@ -12,10 +10,6 @@ ReturnValue_t FileDirectiveReader::parseData() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (not performCrcCheckIfApplicable()) {
|
||||
return cfdp::PDU_CHECKSUM_FAILURE;
|
||||
}
|
||||
|
||||
if (this->getPduDataFieldLen() < 1) {
|
||||
return cfdp::INVALID_PDU_DATAFIELD_LEN;
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#define FSFW_SRC_FSFW_CFDP_PDU_FILEDIRECTIVEDESERIALIZER_H_
|
||||
|
||||
#include "../definitions.h"
|
||||
#include "fsfw/cfdp/pdu/HeaderReader.h"
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
|
||||
/**
|
||||
* @brief This class is used to deserialize a PDU file directive header from raw memory.
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#include "FinishedPduCreator.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
FinishPduCreator::FinishPduCreator(PduConfig &conf, FinishedInfo &finishInfo)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::FINISH, 0), finishInfo(finishInfo) {
|
||||
updateDirectiveFieldLen();
|
||||
@@ -15,7 +13,6 @@ void FinishPduCreator::updateDirectiveFieldLen() {
|
||||
|
||||
ReturnValue_t FinishPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -43,9 +40,5 @@ ReturnValue_t FinishPduCreator::serialize(uint8_t **buffer, size_t *size, size_t
|
||||
if (finishInfo.getFaultLocation(&entityId) == returnvalue::OK) {
|
||||
result = entityId->serialize(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -1,5 +1,10 @@
|
||||
#include "FinishedPduReader.h"
|
||||
|
||||
// Thanks, windows
|
||||
#ifdef NO_ERROR
|
||||
#undef NO_ERROR
|
||||
#endif
|
||||
|
||||
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
|
||||
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}
|
||||
|
||||
|
@@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
||||
*buffer += 1;
|
||||
**buffer = pduDataFieldLen & 0x00ff;
|
||||
*buffer += 1;
|
||||
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
|
||||
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
|
||||
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
|
||||
pduConf.seqNum.getWidth();
|
||||
*buffer += 1;
|
||||
*size += 4;
|
||||
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
|
||||
|
@@ -1,10 +1,8 @@
|
||||
#include "HeaderReader.h"
|
||||
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "PduHeaderReader.h"
|
||||
|
||||
PduHeaderReader::PduHeaderReader(const uint8_t *pduBuf, size_t maxSize) {
|
||||
setReadOnlyData(pduBuf, maxSize);
|
||||
@@ -19,29 +17,28 @@ ReturnValue_t PduHeaderReader::parseData() {
|
||||
}
|
||||
pointers.fixedHeader =
|
||||
reinterpret_cast<PduHeaderFixedStruct *>(const_cast<uint8_t *>(pointers.rawPtr));
|
||||
sourceIdRaw = &pointers.fixedHeader->variableFieldsStart;
|
||||
sourceIdRaw = static_cast<uint8_t *>(&pointers.fixedHeader->variableFieldsStart);
|
||||
cfdp::WidthInBytes widthEntityIds = getLenEntityIds();
|
||||
cfdp::WidthInBytes widthSeqNum = getLenSeqNum();
|
||||
seqNumRaw = static_cast<uint8_t *>(sourceIdRaw) + static_cast<uint8_t>(widthEntityIds);
|
||||
destIdRaw = static_cast<uint8_t *>(seqNumRaw) + static_cast<uint8_t>(widthSeqNum);
|
||||
if (getWholePduSize() > PduHeaderReader::getHeaderSize()) {
|
||||
pointers.dataFieldStart = static_cast<const uint8_t *>(destIdRaw) + widthEntityIds;
|
||||
pointers.dataFieldStart = reinterpret_cast<const uint8_t *>(destIdRaw) + widthEntityIds;
|
||||
} else {
|
||||
pointers.dataFieldStart = nullptr;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PduHeaderReader::setData(uint8_t *dataPtr, size_t maxSize, void *args) {
|
||||
ReturnValue_t PduHeaderReader::setData(uint8_t *dataPtr, size_t maxSize_, void *args) {
|
||||
if (dataPtr == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (maxSize < 7) {
|
||||
if (maxSize_ < 7) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
pointers.rawPtr = dataPtr;
|
||||
this->maxSize = maxSize;
|
||||
maxSize = maxSize_;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@@ -81,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() 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 {
|
||||
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
|
||||
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
|
||||
}
|
||||
|
||||
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
|
||||
@@ -106,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons
|
||||
}
|
||||
|
||||
void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width,
|
||||
void *sourcePtr) {
|
||||
void *sourcePtr) const {
|
||||
switch (width) {
|
||||
case (cfdp::WidthInBytes::ONE_BYTE): {
|
||||
auto *fieldTyped = static_cast<uint8_t *>(sourcePtr);
|
||||
field->setValueAndWidth(width, *fieldTyped);
|
||||
field->setValue(width, *fieldTyped);
|
||||
break;
|
||||
}
|
||||
case (cfdp::WidthInBytes::TWO_BYTES): {
|
||||
@@ -118,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
|
||||
size_t deserSize = 0;
|
||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
field->setValueAndWidth(width, fieldTyped);
|
||||
field->setValue(width, fieldTyped);
|
||||
break;
|
||||
}
|
||||
case (cfdp::WidthInBytes::FOUR_BYTES): {
|
||||
@@ -126,15 +123,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB
|
||||
size_t deserSize = 0;
|
||||
SerializeAdapter::deSerialize(&fieldTyped, static_cast<uint8_t *>(sourcePtr), &deserSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
field->setValueAndWidth(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);
|
||||
field->setValue(width, fieldTyped);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -169,12 +158,3 @@ void PduHeaderReader::fillConfig(PduConfig &cfg) const {
|
||||
}
|
||||
|
||||
const uint8_t *PduHeaderReader::getPduDataField() const { return pointers.dataFieldStart; }
|
||||
|
||||
bool PduHeaderReader::performCrcCheckIfApplicable() const {
|
||||
if (getCrcFlag()) {
|
||||
if (CRC::crc16ccitt(pointers.rawPtr, getWholePduSize()) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
#include "KeepAlivePduCreator.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::Fss &progress)
|
||||
KeepAlivePduCreator::KeepAlivePduCreator(PduConfig &conf, cfdp::FileSize &progress)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::KEEP_ALIVE, 4), progress(progress) {
|
||||
updateDirectiveFieldLen();
|
||||
}
|
||||
@@ -19,18 +17,9 @@ void KeepAlivePduCreator::updateDirectiveFieldLen() {
|
||||
|
||||
ReturnValue_t KeepAlivePduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return result;
|
||||
return progress.serialize(this->getLargeFileFlag(), buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
#ifndef 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"
|
||||
|
||||
class KeepAlivePduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
KeepAlivePduCreator(PduConfig& conf, cfdp::Fss& progress);
|
||||
KeepAlivePduCreator(PduConfig& conf, cfdp::FileSize& progress);
|
||||
|
||||
void updateDirectiveFieldLen();
|
||||
|
||||
@@ -16,7 +16,7 @@ class KeepAlivePduCreator : public FileDirectiveCreator {
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
private:
|
||||
cfdp::Fss& progress;
|
||||
cfdp::FileSize& progress;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUSERIALIZER_H_ */
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#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) {}
|
||||
|
||||
ReturnValue_t KeepAlivePduReader::parseData() {
|
||||
@@ -14,4 +15,4 @@ ReturnValue_t KeepAlivePduReader::parseData() {
|
||||
return progress.deSerialize(&buffer, &remLen, getEndianness());
|
||||
}
|
||||
|
||||
cfdp::Fss& KeepAlivePduReader::getProgress() { return progress; }
|
||||
cfdp::FileSize& KeepAlivePduReader::getProgress() { return progress; }
|
||||
|
@@ -1,19 +1,19 @@
|
||||
#ifndef 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"
|
||||
|
||||
class KeepAlivePduReader : public FileDirectiveReader {
|
||||
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;
|
||||
|
||||
cfdp::Fss& getProgress();
|
||||
cfdp::FileSize& getProgress();
|
||||
|
||||
private:
|
||||
cfdp::Fss& progress;
|
||||
cfdp::FileSize& progress;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_KEEPALIVEPDUREADER_H_ */
|
||||
|
@@ -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; }
|
@@ -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_ */
|
103
src/fsfw/cfdp/pdu/MetadataInfo.cpp
Normal file
103
src/fsfw/cfdp/pdu/MetadataInfo.cpp
Normal 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; }
|
55
src/fsfw/cfdp/pdu/MetadataInfo.h
Normal file
55
src/fsfw/cfdp/pdu/MetadataInfo.h
Normal 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_ */
|
@@ -1,28 +1,12 @@
|
||||
#include "MetadataPduCreator.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataGenericInfo &info,
|
||||
cfdp::StringLv &srcFileName, cfdp::StringLv &destFileName,
|
||||
cfdp::Tlv **optionsArray, size_t optionsLen)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5),
|
||||
info(info),
|
||||
srcFileName(srcFileName),
|
||||
destFileName(destFileName),
|
||||
optionsArray(optionsArray),
|
||||
optionsLen(optionsLen) {
|
||||
MetadataPduCreator::MetadataPduCreator(PduConfig &conf, MetadataInfo &info)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::METADATA, 5), info(info) {
|
||||
updateDirectiveFieldLen();
|
||||
}
|
||||
|
||||
void MetadataPduCreator::updateDirectiveFieldLen() {
|
||||
size_t dirFieldLen = MetadataGenericInfo::getSerializedSize(HeaderCreator::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);
|
||||
setDirectiveDataFieldLen(info.getSerializedSize(getLargeFileFlag()));
|
||||
}
|
||||
|
||||
size_t MetadataPduCreator::getSerializedSize() const {
|
||||
@@ -31,7 +15,6 @@ size_t MetadataPduCreator::getSerializedSize() const {
|
||||
|
||||
ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -46,29 +29,25 @@ ReturnValue_t MetadataPduCreator::serialize(uint8_t **buffer, size_t *size, size
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = srcFileName.serialize(buffer, size, maxSize, streamEndianness);
|
||||
result = info.getSourceFileName().serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = destFileName.serialize(buffer, size, maxSize, streamEndianness);
|
||||
result = info.getDestFileName().serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (optionsLen > 0 and optionsArray != nullptr) {
|
||||
for (size_t idx = 0; idx < optionsLen; idx++) {
|
||||
result = optionsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (info.hasOptions()) {
|
||||
cfdp::Tlv **optsArray = nullptr;
|
||||
size_t optsLen = 0;
|
||||
info.getOptions(&optsArray, &optsLen, nullptr);
|
||||
for (size_t idx = 0; idx < optsLen; idx++) {
|
||||
result = optsArray[idx]->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const cfdp::StringLv &MetadataPduCreator::getSourceFileName() const { return srcFileName; }
|
||||
const cfdp::StringLv &MetadataPduCreator::getDestFileName() const { return destFileName; }
|
||||
|
@@ -2,30 +2,22 @@
|
||||
#define FSFW_CFDP_PDU_METADATAPDUCREATOR_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataInfo.h"
|
||||
|
||||
class MetadataPduCreator : public FileDirectiveCreator {
|
||||
public:
|
||||
MetadataPduCreator(PduConfig& conf, MetadataGenericInfo& info, cfdp::StringLv& srcFileName,
|
||||
cfdp::StringLv& destFileName, cfdp::Tlv** optionsArray, size_t optionsLen);
|
||||
MetadataPduCreator(PduConfig& conf, MetadataInfo& info);
|
||||
|
||||
void updateDirectiveFieldLen();
|
||||
|
||||
[[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,
|
||||
Endianness streamEndianness) const override;
|
||||
using FileDirectiveCreator::serialize;
|
||||
|
||||
private:
|
||||
MetadataGenericInfo& info;
|
||||
cfdp::StringLv& srcFileName;
|
||||
cfdp::StringLv& destFileName;
|
||||
cfdp::Tlv** optionsArray;
|
||||
size_t optionsLen;
|
||||
MetadataInfo& info;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_METADATAPDUCREATOR_H_ */
|
||||
|
@@ -1,15 +1,9 @@
|
||||
#include "MetadataPduReader.h"
|
||||
|
||||
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize,
|
||||
MetadataGenericInfo& info, cfdp::Tlv* optionsArray,
|
||||
size_t optArrayMaxSize)
|
||||
: FileDirectiveReader(pduBuf, maxSize),
|
||||
info(info),
|
||||
optionArray(optionsArray),
|
||||
optionArrayMaxSize(optArrayMaxSize) {}
|
||||
MetadataPduReader::MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info)
|
||||
: FileDirectiveReader(pduBuf, maxSize), info(info) {}
|
||||
|
||||
ReturnValue_t MetadataPduReader::parseData() {
|
||||
parsedOptions = 0;
|
||||
ReturnValue_t result = FileDirectiveReader::parseData();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -25,47 +19,39 @@ ReturnValue_t MetadataPduReader::parseData() {
|
||||
remSize -= 1;
|
||||
buf += 1;
|
||||
auto endianness = getEndianness();
|
||||
result = info.getMutFileSize().deSerialize(&buf, &remSize, endianness);
|
||||
result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = srcFileName.deSerialize(&buf, &remSize, endianness);
|
||||
result = info.getSourceFileName().deSerialize(&buf, &remSize, endianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = destFileName.deSerialize(&buf, &remSize, endianness);
|
||||
result = info.getDestFileName().deSerialize(&buf, &remSize, endianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (getCrcFlag() && remSize == 2) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
info.setOptionsLen(0);
|
||||
if (remSize > 0) {
|
||||
if (optionArrayMaxSize == 0 or optionArray == nullptr) {
|
||||
if (not info.canHoldOptions()) {
|
||||
return cfdp::METADATA_CANT_PARSE_OPTIONS;
|
||||
}
|
||||
cfdp::Tlv** optionsArray = nullptr;
|
||||
size_t optsMaxLen = 0;
|
||||
size_t optsIdx = 0;
|
||||
info.getOptions(&optionsArray, nullptr, &optsMaxLen);
|
||||
while (remSize > 0) {
|
||||
if (optsIdx > optionArrayMaxSize) {
|
||||
if (optsIdx > optsMaxLen) {
|
||||
return cfdp::METADATA_CANT_PARSE_OPTIONS;
|
||||
}
|
||||
result = optionArray[optsIdx].deSerialize(&buf, &remSize, endianness);
|
||||
result = optionsArray[optsIdx]->deSerialize(&buf, &remSize, endianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
optsIdx++;
|
||||
}
|
||||
parsedOptions = optsIdx;
|
||||
info.setOptionsLen(optsIdx);
|
||||
}
|
||||
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; }
|
||||
|
@@ -2,28 +2,16 @@
|
||||
#define FSFW_CFDP_PDU_METADATAPDUREADER_H_
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataGenericInfo.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataInfo.h"
|
||||
|
||||
class MetadataPduReader : public FileDirectiveReader {
|
||||
public:
|
||||
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataGenericInfo& info,
|
||||
cfdp::Tlv* optionsArray, size_t optArrayMaxSize);
|
||||
MetadataPduReader(const uint8_t* pduBuf, size_t maxSize, MetadataInfo& info);
|
||||
|
||||
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:
|
||||
cfdp::StringLv srcFileName;
|
||||
cfdp::StringLv destFileName;
|
||||
MetadataGenericInfo& info;
|
||||
cfdp::Tlv* optionArray;
|
||||
size_t optionArrayMaxSize;
|
||||
size_t parsedOptions = 0;
|
||||
MetadataInfo& info;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CFDP_PDU_METADATAPDUREADER_H_ */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#include "NakInfo.h"
|
||||
|
||||
NakInfo::NakInfo(cfdp::Fss startOfScope, cfdp::Fss endOfScope)
|
||||
NakInfo::NakInfo(cfdp::FileSize startOfScope, cfdp::FileSize endOfScope)
|
||||
: startOfScope(startOfScope), endOfScope(endOfScope) {}
|
||||
|
||||
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; }
|
||||
|
||||
|
@@ -3,21 +3,21 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "fsfw/cfdp/Fss.h"
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
|
||||
class NakInfo {
|
||||
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,
|
||||
size_t* maxSegmentRequestLen);
|
||||
|
||||
size_t getSerializedSize(bool fssLarge = false);
|
||||
|
||||
cfdp::Fss& getStartOfScope();
|
||||
cfdp::Fss& getEndOfScope();
|
||||
cfdp::FileSize& getStartOfScope();
|
||||
cfdp::FileSize& getEndOfScope();
|
||||
|
||||
bool hasSegmentRequests() const;
|
||||
bool canHoldSegmentRequests() const;
|
||||
@@ -31,8 +31,8 @@ class NakInfo {
|
||||
void setSegmentRequestLen(size_t readLen);
|
||||
|
||||
private:
|
||||
cfdp::Fss startOfScope;
|
||||
cfdp::Fss endOfScope;
|
||||
cfdp::FileSize startOfScope;
|
||||
cfdp::FileSize endOfScope;
|
||||
SegmentRequest* segmentRequests = nullptr;
|
||||
size_t segmentRequestsLen = 0;
|
||||
size_t maxSegmentRequestsLen = 0;
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#include "NakPduCreator.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
NakPduCreator::NakPduCreator(PduConfig &pduConf, NakInfo &nakInfo)
|
||||
: FileDirectiveCreator(pduConf, cfdp::FileDirective::NAK, 0), nakInfo(nakInfo) {
|
||||
updateDirectiveFieldLen();
|
||||
@@ -15,7 +13,6 @@ size_t NakPduCreator::getSerializedSize() const { return FileDirectiveCreator::g
|
||||
|
||||
ReturnValue_t NakPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -43,9 +40,5 @@ ReturnValue_t NakPduCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "NakInfo.h"
|
||||
#include "fsfw/cfdp/Fss.h"
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
#include "fsfw/cfdp/definitions.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
|
||||
|
@@ -71,11 +71,6 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
|
||||
void getDestId(cfdp::EntityId& destId) const override;
|
||||
void getTransactionSeqNum(cfdp::TransactionSeqNum& seqNum) const override;
|
||||
|
||||
/**
|
||||
* Performs the CRC check on the whole PDU if the CRC flag is set.
|
||||
*/
|
||||
[[nodiscard]] bool performCrcCheckIfApplicable() const;
|
||||
|
||||
ReturnValue_t deserResult = returnvalue::OK;
|
||||
|
||||
[[nodiscard]] size_t getMaxSize() const;
|
||||
@@ -110,8 +105,7 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF {
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override;
|
||||
static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width,
|
||||
void* sourcePtr);
|
||||
void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const;
|
||||
void* sourceIdRaw = nullptr;
|
||||
void* seqNumRaw = nullptr;
|
||||
void* destIdRaw = nullptr;
|
@@ -1,7 +1,5 @@
|
||||
#include "PromptPduCreator.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
PromptPduCreator::PromptPduCreator(PduConfig &conf, cfdp::PromptResponseRequired responseRequired)
|
||||
: FileDirectiveCreator(conf, cfdp::FileDirective::PROMPT, 1),
|
||||
responseRequired(responseRequired) {}
|
||||
@@ -12,7 +10,6 @@ size_t PromptPduCreator::getSerializedSize() const {
|
||||
|
||||
ReturnValue_t PromptPduCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
const uint8_t *start = *buffer;
|
||||
ReturnValue_t result = FileDirectiveCreator::serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@@ -23,10 +20,5 @@ ReturnValue_t PromptPduCreator::serialize(uint8_t **buffer, size_t *size, size_t
|
||||
**buffer = responseRequired << 7;
|
||||
*buffer += 1;
|
||||
*size += 1;
|
||||
|
||||
if (getCrcFlag()) {
|
||||
uint16_t crc = CRC::crc16ccitt(start, getWholePduSize() - 2);
|
||||
result = SerializeAdapter::serialize(&crc, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -8,5 +8,4 @@ target_sources(
|
||||
StringLv.cpp
|
||||
FlowLabelTlv.cpp
|
||||
MessageToUserTlv.cpp
|
||||
FaultHandlerOverrideTlv.cpp
|
||||
ReservedMessageCreator.cpp)
|
||||
FaultHandlerOverrideTlv.cpp)
|
||||
|
@@ -23,8 +23,7 @@ class EntityIdTlv : public TlvIF {
|
||||
*/
|
||||
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
|
||||
|
||||
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
|
||||
// the compiler
|
||||
using SerializeIF::deSerialize;
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
@@ -26,6 +26,7 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
|
||||
*/
|
||||
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
|
||||
|
||||
using SerializeIF::deSerialize;
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
@@ -29,8 +29,7 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
|
||||
*/
|
||||
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
|
||||
|
||||
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
|
||||
// the compiler
|
||||
using SerializeIF::deSerialize;
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
@@ -66,9 +66,9 @@ static constexpr uint8_t FSR_DENY_DIR_NOT_ALLOWED = 0b0010;
|
||||
|
||||
class FilestoreTlvBase : public TlvIF {
|
||||
public:
|
||||
explicit FilestoreTlvBase(cfdp::StringLv& firstFileName) : firstFileName(firstFileName) {};
|
||||
explicit FilestoreTlvBase(cfdp::StringLv& firstFileName) : firstFileName(firstFileName){};
|
||||
FilestoreTlvBase(FilestoreActionCode actionCode, cfdp::StringLv& firstFileName)
|
||||
: actionCode(actionCode), firstFileName(firstFileName) {};
|
||||
: actionCode(actionCode), firstFileName(firstFileName){};
|
||||
|
||||
ReturnValue_t commonSerialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness, bool isResponse = false,
|
||||
|
@@ -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(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,
|
||||
Endianness streamEndianness) const {
|
||||
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 {
|
||||
if (zeroLen or value.getConstBuffer() == nullptr) {
|
||||
if (zeroLen) {
|
||||
return 1;
|
||||
} else if (value.getConstBuffer() == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
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 {
|
||||
if (size != nullptr) {
|
||||
// Length without length field
|
||||
*size = getSerializedSize() - 1;
|
||||
*size = value.getSerializedSize() - 1;
|
||||
}
|
||||
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; }
|
||||
|
@@ -18,12 +18,8 @@ class Lv : public SerializeIF {
|
||||
Lv(const uint8_t* value, size_t size);
|
||||
Lv();
|
||||
|
||||
// Semantically, this class is a zero-copy helper, so the copy ctor and copy assigment do not
|
||||
// really make sense here.
|
||||
Lv(const Lv&) = delete;
|
||||
Lv& operator=(const Lv&) = delete;
|
||||
Lv(Lv&&) noexcept;
|
||||
Lv& operator=(Lv&&) noexcept;
|
||||
Lv(const Lv&);
|
||||
Lv& operator=(const Lv&);
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
@@ -40,8 +36,6 @@ class Lv : public SerializeIF {
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
size_t getValueLen() const;
|
||||
|
||||
/**
|
||||
* Get value field and its size.
|
||||
* @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;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
private:
|
||||
bool zeroLen = true;
|
||||
SerialBufferAdapter<uint8_t> value;
|
||||
|
@@ -7,22 +7,3 @@ MessageToUserTlv::MessageToUserTlv() : Tlv() {}
|
||||
|
||||
MessageToUserTlv::MessageToUserTlv(const std::vector<uint8_t>& data)
|
||||
: 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;
|
||||
}
|
||||
|
@@ -9,12 +9,8 @@ class MessageToUserTlv : public cfdp::Tlv {
|
||||
public:
|
||||
MessageToUserTlv();
|
||||
MessageToUserTlv(uint8_t* value, size_t size);
|
||||
MessageToUserTlv(const uint8_t* value, size_t size);
|
||||
explicit MessageToUserTlv(const std::vector<uint8_t>& data);
|
||||
|
||||
bool isReservedCfdpMessage(uint8_t& messageType, const uint8_t** msgDataStart,
|
||||
size_t& msgLen) const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
}
|
@@ -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
|
@@ -7,12 +7,3 @@ cfdp::StringLv::StringLv(const char* filename, size_t len)
|
||||
: Lv(reinterpret_cast<const uint8_t*>(filename), len) {}
|
||||
|
||||
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};
|
||||
}
|
||||
|
@@ -13,8 +13,6 @@ class StringLv : public Lv {
|
||||
explicit StringLv(const std::string& fileName);
|
||||
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
|
||||
StringLv(const std::string&&) = delete;
|
||||
};
|
||||
|
@@ -54,7 +54,6 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
return STREAM_TOO_SHORT;
|
||||
}
|
||||
|
||||
rawData = *buffer;
|
||||
uint8_t rawType = **buffer;
|
||||
if (not checkType(rawType)) {
|
||||
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; }
|
||||
|
||||
void cfdp::Tlv::setType(TlvType type) { this->type = type; }
|
||||
|
||||
const uint8_t *cfdp::Tlv::getRawData() const { return rawData; }
|
||||
|
@@ -47,7 +47,6 @@ class Tlv : public TlvIF {
|
||||
void setValue(uint8_t *value, size_t len);
|
||||
|
||||
[[nodiscard]] const uint8_t *getValue() const;
|
||||
[[nodiscard]] const uint8_t *getRawData() const;
|
||||
void setType(TlvType type);
|
||||
[[nodiscard]] TlvType getType() const override;
|
||||
[[nodiscard]] uint8_t getLengthField() const override;
|
||||
@@ -56,7 +55,6 @@ class Tlv : public TlvIF {
|
||||
bool checkType(uint8_t rawType);
|
||||
|
||||
bool zeroLen = true;
|
||||
const uint8_t *rawData = nullptr;
|
||||
TlvType type = TlvType::INVALID_TLV;
|
||||
SerialBufferAdapter<uint8_t> value;
|
||||
};
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
class TlvIF : public SerializeIF {
|
||||
public:
|
||||
virtual ~TlvIF() {};
|
||||
virtual ~TlvIF(){};
|
||||
|
||||
virtual uint8_t getLengthField() const = 0;
|
||||
virtual cfdp::TlvType getType() const = 0;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
template <typename Tp>
|
||||
class BinaryNode {
|
||||
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;
|
||||
BinaryNode* left;
|
||||
BinaryNode* right;
|
||||
@@ -23,31 +23,31 @@ class ExplicitNodeIterator {
|
||||
typedef Tp value_type;
|
||||
typedef Tp* pointer;
|
||||
typedef Tp& reference;
|
||||
ExplicitNodeIterator() : element(NULL) {}
|
||||
ExplicitNodeIterator() : element(nullptr) {}
|
||||
ExplicitNodeIterator(_Node* node) : element(node) {}
|
||||
BinaryNode<Tp>* element;
|
||||
_Self up() { return _Self(element->parent); }
|
||||
_Self left() {
|
||||
if (element != NULL) {
|
||||
if (element != nullptr) {
|
||||
return _Self(element->left);
|
||||
} else {
|
||||
return _Self(NULL);
|
||||
return _Self(nullptr);
|
||||
}
|
||||
}
|
||||
_Self right() {
|
||||
if (element != NULL) {
|
||||
if (element != nullptr) {
|
||||
return _Self(element->right);
|
||||
} 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; }
|
||||
pointer operator->() const {
|
||||
if (element != NULL) {
|
||||
if (element != nullptr) {
|
||||
return element->value;
|
||||
} else {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
pointer operator*() const { return this->operator->(); }
|
||||
@@ -62,13 +62,13 @@ class BinaryTree {
|
||||
typedef ExplicitNodeIterator<Tp> iterator;
|
||||
typedef BinaryNode<Tp> Node;
|
||||
typedef std::pair<iterator, iterator> children;
|
||||
BinaryTree() : rootNode(NULL) {}
|
||||
BinaryTree() : rootNode(nullptr) {}
|
||||
BinaryTree(Node* rootNode) : rootNode(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) {
|
||||
newNode->parent = parentNode.element;
|
||||
if (parentNode.element != NULL) {
|
||||
if (parentNode.element != nullptr) {
|
||||
if (insertLeft) {
|
||||
parentNode.element->left = newNode;
|
||||
} else {
|
||||
@@ -84,13 +84,13 @@ class BinaryTree {
|
||||
children erase(iterator node) {
|
||||
if (node.element == rootNode) {
|
||||
// We're root node
|
||||
rootNode = NULL;
|
||||
rootNode = nullptr;
|
||||
} else {
|
||||
// Delete parent's reference
|
||||
if (node.up().left() == node) {
|
||||
node.up().element->left = NULL;
|
||||
node.up().element->left = nullptr;
|
||||
} else {
|
||||
node.up().element->right = NULL;
|
||||
node.up().element->right = nullptr;
|
||||
}
|
||||
}
|
||||
return children(node.element->left, node.element->right);
|
||||
|
@@ -12,7 +12,6 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||
class FixedArrayList : public ArrayList<T, count_t> {
|
||||
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||
"count_t is not large enough to hold MAX_SIZE");
|
||||
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
|
||||
|
||||
private:
|
||||
T data[MAX_SIZE];
|
||||
|
@@ -155,8 +155,8 @@ class FixedMap : public SerializeIF {
|
||||
|
||||
uint32_t maxSize() const { return theMap.maxSize(); }
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override {
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result =
|
||||
SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
|
||||
uint32_t i = 0;
|
||||
@@ -170,7 +170,7 @@ class FixedMap : public SerializeIF {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t getSerializedSize() const override {
|
||||
virtual size_t getSerializedSize() const {
|
||||
uint32_t printSize = sizeof(_size);
|
||||
uint32_t i = 0;
|
||||
|
||||
@@ -182,8 +182,8 @@ class FixedMap : public SerializeIF {
|
||||
return printSize;
|
||||
}
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override {
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result =
|
||||
SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
|
||||
if (this->_size > theMap.maxSize()) {
|
||||
|
@@ -61,7 +61,7 @@ class PlacementFactory {
|
||||
// Need to call destructor first, in case something was allocated by the object (shouldn't do
|
||||
// that, however).
|
||||
thisElement->~T();
|
||||
uint8_t* pointer = (uint8_t*)(thisElement);
|
||||
uint8_t* pointer = static_cast<uint8_t*>(thisElement);
|
||||
return dataBackend->deleteData(pointer, sizeof(T));
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include "fsfw/container/SharedRingBuffer.h"
|
||||
|
||||
#include "SharedRingBuffer.h"
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
|
||||
@@ -16,12 +15,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
SharedRingBuffer::~SharedRingBuffer() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
if (receiveSizesFifo != nullptr) {
|
||||
delete (receiveSizesFifo);
|
||||
}
|
||||
}
|
||||
SharedRingBuffer::~SharedRingBuffer() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||
|
||||
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { this->fifoDepth = fifoDepth; }
|
||||
|
||||
@@ -36,31 +30,18 @@ MutexIF* SharedRingBuffer::getMutexHandle() const { return mutex; }
|
||||
|
||||
ReturnValue_t SharedRingBuffer::initialize() {
|
||||
if (fifoDepth > 0) {
|
||||
receiveSizesFifo = new DynamicFIFO<size_t>(fifoDepth);
|
||||
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||
}
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFifo() {
|
||||
if (receiveSizesFifo == nullptr) {
|
||||
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
||||
if (receiveSizesFIFO == nullptr) {
|
||||
// Configuration error.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||
<< " was not configured to have sizes FIFO, returning nullptr!" << std::endl;
|
||||
#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;
|
||||
}
|
@@ -20,7 +20,7 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
* @param size
|
||||
* @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.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld,
|
||||
@@ -30,7 +30,7 @@ class SharedRingBuffer : public SystemObject, public SimpleRingBuffer {
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @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.
|
||||
*/
|
||||
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!
|
||||
* @return
|
||||
*/
|
||||
DynamicFIFO<size_t>* getReceiveSizesFifo();
|
||||
|
||||
ReturnValue_t fifoEmpty(bool& empty, MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
||||
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||
|
||||
private:
|
||||
MutexIF* mutex = nullptr;
|
||||
|
||||
size_t fifoDepth = 0;
|
||||
DynamicFIFO<size_t>* receiveSizesFifo = nullptr;
|
||||
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */
|
||||
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */
|
||||
|
@@ -4,31 +4,48 @@
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.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),
|
||||
parentId(parentId),
|
||||
mode(MODE_OFF),
|
||||
submode(SUBMODE_NONE),
|
||||
modeHelper(this),
|
||||
healthHelper(this, setObjectId) {
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||
|
||||
ReturnValue_t ControllerBase::initialize() {
|
||||
ReturnValue_t result = modeHelper.initialize();
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
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) {
|
||||
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(); }
|
||||
@@ -58,7 +75,7 @@ void ControllerBase::handleQueue() {
|
||||
|
||||
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode_, submode_);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
mode = mode_;
|
||||
submode = submode_;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
@@ -72,17 +89,18 @@ void ControllerBase::getMode(Mode_t* mode_, Submode_t* 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::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
|
||||
|
||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
performControlOperation(opCode);
|
||||
performControlOperation();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
|
||||
|
||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
switch (health) {
|
||||
case HEALTHY:
|
||||
@@ -100,13 +118,3 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
|
||||
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@@ -6,9 +6,6 @@
|
||||
#include "fsfw/modes/HasModesIF.h"
|
||||
#include "fsfw/modes/ModeHelper.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/PeriodicTaskIF.h"
|
||||
|
||||
@@ -21,18 +18,13 @@
|
||||
class ControllerBase : public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public ExecutableObjectIF,
|
||||
public ModeTreeChildIF,
|
||||
public ModeTreeConnectionIF,
|
||||
public SystemObject {
|
||||
public:
|
||||
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;
|
||||
|
||||
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
||||
ModeTreeChildIF &getModeTreeChildIF() override;
|
||||
|
||||
/** SystemObject override */
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
@@ -46,8 +38,6 @@ class ControllerBase : public HasModesIF,
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
void setTaskIF(PeriodicTaskIF *task) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
const HasHealthIF *getOptHealthIF() const override;
|
||||
const HasModesIF &getModeIF() const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -61,11 +51,13 @@ class ControllerBase : public HasModesIF,
|
||||
/**
|
||||
* 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,
|
||||
uint32_t *msToReachTheMode) override = 0;
|
||||
|
||||
const object_id_t parentId;
|
||||
|
||||
Mode_t mode;
|
||||
|
||||
Submode_t submode;
|
||||
|
@@ -1,7 +1,8 @@
|
||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||
|
||||
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
|
||||
: ControllerBase(objectId, commandQueueDepth),
|
||||
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
||||
size_t commandQueueDepth)
|
||||
: ControllerBase(objectId, parentId, commandQueueDepth),
|
||||
poolManager(this, commandQueue),
|
||||
actionHelper(this, commandQueue) {}
|
||||
|
||||
@@ -81,7 +82,7 @@ ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
performControlOperation(opCode);
|
||||
performControlOperation();
|
||||
/* We do this after performing control operation because variables will be set changed
|
||||
in this function. */
|
||||
poolManager.performHkOperation();
|
||||
|
@@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
|
||||
public HasActionsIF,
|
||||
public HasLocalDataPoolIF {
|
||||
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;
|
||||
|
||||
/* SystemObjectIF overrides */
|
||||
@@ -44,9 +44,9 @@ class ExtendedControllerBase : public ControllerBase,
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/* HasActionsIF overrides */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user