From f7cb761e18f338f09b4a59f07f6458aefb0a0f05 Mon Sep 17 00:00:00 2001 From: silabsbot Date: Thu, 6 Jun 2024 14:37:30 +0000 Subject: [PATCH] CPCd Release: 4.5.0 --- .gitignore | 19 - CMakeLists.txt | 579 ++++----------- cmake-variants.yaml | 35 - cmake/Warnings.cmake | 21 +- cmake/modules/FindMbedTLS.cmake | 2 +- debian/changelog | 5 + debian/control | 46 ++ debian/cpcd.install | 2 + debian/libcpc-dev.install | 3 + debian/libcpc3.install | 1 + debian/rules | 12 + debian/source/format | 1 + doc/troubleshooting.md | 15 +- driver/driver_emul.c | 128 +++- driver/driver_emul.h | 1 - driver/driver_ezsp.c | 5 +- driver/driver_ezsp.h | 1 - driver/driver_kill.c | 6 +- driver/driver_spi.c | 30 +- driver/driver_spi.h | 1 - driver/driver_uart.c | 213 +++--- driver/driver_uart.h | 3 +- driver/driver_xmodem.c | 120 ++- include/cpcd/board_controller.h | 2 +- include/cpcd/config.h | 12 +- include/cpcd/core.h | 5 +- include/cpcd/event.h | 4 +- include/cpcd/exchange.h | 8 +- include/cpcd/exit.h | 2 + include/cpcd/gpio.h | 6 +- include/cpcd/logging.h | 14 +- include/cpcd/server_core.h | 3 +- include/cpcd/sl_slist.h | 12 +- include/cpcd/sleep.h | 4 +- include/cpcd/xmodem.h | 2 +- lib/bindings/rust/README.txt | 1 + lib/sl_cpc.c | 83 +-- main.c | 7 +- misc/board_controller.c | 3 +- misc/config.c | 18 +- misc/{version.h.in => config.h.in} | 27 +- misc/exit.c | 10 +- misc/gpio.c | 23 +- misc/gpio_sysfs.c | 7 +- misc/logging.c | 125 ++-- misc/sl_slist.c | 4 +- misc/sleep.c | 23 +- misc/utils.c | 20 +- modes/binding.c | 2 + modes/firmware_update.c | 11 +- modes/normal.c | 2 + modes/uart_validation.c | 41 +- script/cpc_iostream_bridge.py | 12 +- security/private/keys/keys.c | 116 ++- security/private/keys/keys.h | 3 +- security/private/protocol/protocol.c | 6 +- security/private/protocol/protocol.h | 4 +- .../private/thread/command_synchronizer.c | 22 +- .../private/thread/command_synchronizer.h | 4 +- security/private/thread/security_thread.c | 12 +- security/private/thread/security_thread.h | 2 +- security/security.c | 3 +- server_core/core/buffer.c | 10 +- server_core/core/buffer.h | 8 +- server_core/core/core.c | 345 +++++---- server_core/core/core.h | 23 +- server_core/core/crc.c | 67 +- server_core/core/crc.h | 10 +- server_core/core/hdlc.c | 2 + server_core/core/hdlc.h | 2 +- server_core/core/protocol.c | 5 + server_core/core/protocol.h | 11 + server_core/core/protocol_internal.h | 5 + server_core/core/protocol_v4.c | 20 +- server_core/core/protocol_v5.c | 129 +++- server_core/epoll/epoll.c | 20 +- server_core/epoll/epoll.h | 4 +- server_core/server/server.c | 699 +++++++++--------- server_core/server/server_internal.h | 2 +- server_core/server/server_ready_sync.c | 4 +- server_core/server_core.c | 137 ++-- server_core/system_endpoint/system.c | 118 ++- server_core/system_endpoint/system.h | 2 +- 83 files changed, 1778 insertions(+), 1759 deletions(-) delete mode 100644 cmake-variants.yaml create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/cpcd.install create mode 100644 debian/libcpc-dev.install create mode 100644 debian/libcpc3.install create mode 100755 debian/rules create mode 100644 debian/source/format rename misc/{version.h.in => config.h.in} (73%) mode change 100644 => 100755 script/cpc_iostream_bridge.py diff --git a/.gitignore b/.gitignore index ae73b9e..25074c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,2 @@ -# .gitignore - -# Debian files -debian/.debhelper/ -debian/debhelper-build-stamp -debian/files -debian/*.substvars -debian/python-cpc-daemon-doc/ -debian/python3-cpc-daemon/ - -# Emacs files -*~ - -# Python files -.pybuild/ - -# Other files -tmp/ - build/* build_*/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 285fbeb..a5e6f1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,56 +1,53 @@ +# Ubuntu 18.04 ships CMake 3.10 cmake_minimum_required(VERSION 3.10) -project(cpcd - VERSION "4.4.2.0" +project(cpc-daemon + VERSION "4.5.0.0" LANGUAGES C) -set(CPC_LIBRARY_API_VERSION "3") -set(CPC_PROTOCOL_VERSION "5") -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules") +option(BUILD_SHARED_LIBS "Build shared libraries" ON) +option(BUILD_TESTING "Build tests" OFF) -### Require out-of-source builds -file(TO_CMAKE_PATH "${CMAKE_CURRENT_BINARY_DIR}/CMakeLists.txt" LOC_PATH) -if(EXISTS "${LOC_PATH}") - message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory.") -endif() - -# Options -set(TARGET_GROUP release CACHE STRING "Group to build") -option(WARN_AS_ERROR "Treat warnings as errors") -option(ENABLE_ENCRYPTION "Enable the encryption of the CPC link using MbedTLS" TRUE) -option(USE_LEGACY_GPIO_SYSFS "Use the legacy GPIO sysfs instead of GPIO device" FALSE) -option(COMPILE_LTTNG "Enable LTTng tracing") -option(ENABLE_VALGRIND "Enable Valgrind in tests") -option(TARGET_TESTING "Enable some features used only in testing") - -# Includes -include(cmake/GetGitRevisionDescription.cmake) -include(cmake/TargetStds.cmake) -include(cmake/Warnings.cmake) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules") +include(CTest) include(GNUInstallDirs) +include("./cmake/GetGitRevisionDescription.cmake") +include("./cmake/Warnings.cmake") + +option(USE_LEGACY_GPIO_SYSFS "Use the legacy GPIO sysfs instead of GPIO device" OFF) +option(ENABLE_ENCRYPTION "Enable the encryption of the CPC link using MbedTLS" ON) +option(COMPILE_LTTNG "Enable LTTng tracing" OFF) +option(ENABLE_VALGRIND "Enable Valgrind in tests" OFF) +option(TARGET_TESTING "Enable target testing" OFF) +set(CPC_LIBRARY_API_VERSION "3") +set(CPC_PROTOCOL_VERSION "5") +set(CPC_SOCKET_DIR "/dev/shm" CACHE STRING "CPC socket directory") +set(DEFAULT_INSTANCE_NAME "cpcd_0" CACHE STRING "Default instance name") +set(CPCD_CONFIG_FILE_PATH "${CMAKE_INSTALL_FULL_SYSCONFDIR}/cpcd.conf" CACHE STRING "CPCd config file") +set(CPCD_REBOOT_TIME_MS "2000" CACHE STRING "CPCd reboot time") -# Dependencies -# In near future, we may make pkg-config mandatory. +### + +find_package(Backtrace) find_package(PkgConfig) find_package(Threads REQUIRED) -find_package(Backtrace) if(ENABLE_ENCRYPTION) # 1. Try pkg-config # 2. Try config file provided by MbedTLS starting from 3.0 # 3. Try module search for MbedTLS - # PATHS "$ENV{PREFIX}/lib/cmake" if(PkgConfig_FOUND) pkg_search_module(MbedCrypto IMPORTED_TARGET mbedcrypto>=2.7) endif() if(MbedCrypto_FOUND) add_library(MbedTLS::mbedcrypto ALIAS PkgConfig::MbedCrypto) else() - set(TERMUX_CMAKE_CONFIG_PATH "$ENV{PREFIX}/lib/cmake") - find_package(MbedTLS 3 QUIET CONFIG PATHS "${TERMUX_CMAKE_CONFIG_PATH}") + find_package(MbedTLS 3 QUIET CONFIG + # For Termux + PATHS "$ENV{PREFIX}/lib/cmake") if(NOT MbedTLS_FOUND) - unset(MbedTLS_FOUND) - find_package(MbedTLS 2.7 MODULE QUIET REQUIRED COMPONENTS crypto) + find_package(MbedTLS 2.7 MODULE REQUIRED + COMPONENTS crypto) endif() message(STATUS "Found MbedTLS: v${MbedTLS_VERSION}") endif() @@ -60,445 +57,121 @@ if(COMPILE_LTTNG) find_package(LTTngUST REQUIRED) endif() -find_path(Linux_INCLUDE_DIR "linux/version.h") -if(NOT Linux_INCLUDE_DIR) - message(WARNING "Linux headers not found") -endif() - -set(GIT_SHA1 "Unknown") -set(GIT_REFSPEC "Unknown") -get_git_head_revision(GIT_REFSPEC GIT_SHA1 ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) -add_definitions("-DGIT_SHA1=\"${GIT_SHA1}\"") -add_definitions("-DGIT_REFSPEC=\"${GIT_REFSPEC}\"") - -if(WARN_AS_ERROR) - message(STATUS "Treating warnings as errors") - target_compile_options(_Warnings INTERFACE -Werror) -endif() - -add_library(backtrace INTERFACE) if(Backtrace_FOUND) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/backtrace/backtrace.h" "#include <${Backtrace_HEADER}>\n") - target_compile_definitions(backtrace INTERFACE HAVE_BACKTRACE) - target_include_directories(backtrace INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/backtrace") + file(WRITE "${PROJECT_BINARY_DIR}/backtrace/backtrace.h" "#include <${Backtrace_HEADER}>\n") + add_library(backtrace INTERFACE) + target_include_directories(backtrace INTERFACE "${PROJECT_BINARY_DIR}/backtrace") target_include_directories(backtrace INTERFACE ${Backtrace_INCLUDE_DIRS}) target_link_libraries(backtrace INTERFACE ${Backtrace_LIBRARIES}) endif() -add_library(cpc SHARED) -target_stds(cpc C 99 POSIX 2008) -target_link_libraries(cpc PRIVATE Interface::Warnings) -target_link_libraries(cpc PRIVATE Threads::Threads) -target_sources(cpc PRIVATE misc/sleep.c) -target_sources(cpc PRIVATE misc/sl_slist.c) -target_sources(cpc PRIVATE lib/sl_cpc.c) +### -if(COMPILE_LTTNG) - message(STATUS "Building CPC library with LTTNG tracing enabled.") - target_compile_definitions(cpc PRIVATE COMPILE_LTTNG) - target_link_libraries(cpc PRIVATE LTTng::UST) +add_compile_options(-fno-omit-frame-pointer -fstack-protector-strong) +if(TARGET LTTng::UST) + link_libraries(LTTng::UST) endif() -target_include_directories(cpc PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/lib") -target_include_directories(cpc PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") -target_include_directories(cpc PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_include_directories(cpc PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") -set_target_properties(cpc PROPERTIES VERSION ${PROJECT_VERSION}) -set_target_properties(cpc PROPERTIES SOVERSION ${CPC_LIBRARY_API_VERSION}) -set_target_properties(cpc PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/lib/sl_cpc.h") -configure_file(libcpc.pc.in libcpc.pc @ONLY) -install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/libcpc.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig -) - -# CPCd Config file path -if(NOT DEFINED CPCD_CONFIG_FILE_PATH) - set(CPCD_CONFIG_FILE_PATH "${CMAKE_INSTALL_FULL_SYSCONFDIR}/cpcd.conf") -endif() -add_definitions(-DCPCD_CONFIG_FILE_PATH="${CPCD_CONFIG_FILE_PATH}") -message(STATUS "CPCD_CONFIG_FILE_PATH=${CPCD_CONFIG_FILE_PATH}") - -# CPCd minimum reboot time -if(NOT DEFINED CPCD_REBOOT_TIME_MS) - set(CPCD_REBOOT_TIME_MS 2000) +if(TARGET backtrace) + set(HAVE_BACKTRACE ON) endif() -add_definitions(-DCPCD_REBOOT_TIME_MS=${CPCD_REBOOT_TIME_MS}) -message(STATUS "CPCD_REBOOT_TIME_MS=${CPCD_REBOOT_TIME_MS}") -# CPC Socket directory -if(NOT DEFINED CPC_SOCKET_DIR) - set(CPC_SOCKET_DIR /dev/shm) -endif() -add_definitions(-DCPC_SOCKET_DIR="${CPC_SOCKET_DIR}") -message(STATUS "CPC_SOCKET_DIR=${CPC_SOCKET_DIR}") - -# Default instance name -if(NOT DEFINED DEFAULT_INSTANCE_NAME) - set(DEFAULT_INSTANCE_NAME cpcd_0) -endif() -add_definitions(-DDEFAULT_INSTANCE_NAME="${DEFAULT_INSTANCE_NAME}") -message(STATUS "DEFAULT_INSTANCE_NAME=${DEFAULT_INSTANCE_NAME}") - -# Enable encryption support if the user requested it -if(ENABLE_ENCRYPTION) - add_definitions("-DENABLE_ENCRYPTION") - message(STATUS "Building CPCd with encryption enabled") -else() - message(WARNING "Building CPCd with encryption disabled, removing MbedTLS dependency") -endif() +get_git_head_revision(GIT_REFSPEC GIT_SHA1 ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) +configure_file("./misc/config.h.in" "config.h" @ONLY) +configure_file("./libcpc.pc.in" "libcpc.pc" @ONLY) + +### + +add_library(cpc) +set_target_properties(cpc PROPERTIES + VERSION ${PROJECT_VERSION} SOVERSION ${CPC_LIBRARY_API_VERSION}) +set_target_properties(cpc PROPERTIES + C_STANDARD 99 C_STANDARD_REQUIRED YES C_EXTENSIONS NO) +target_compile_definitions(cpc PRIVATE _POSIX_C_SOURCE=200809L) +target_include_directories(cpc PRIVATE "${PROJECT_BINARY_DIR}") +target_include_directories(cpc PRIVATE "./include") +target_include_directories(cpc PUBLIC "./lib") +set_target_properties(cpc PROPERTIES PUBLIC_HEADER "./lib/sl_cpc.h") +target_sources(cpc PRIVATE + "./lib/sl_cpc.c" + "./misc/sl_slist.c" + "./misc/sleep.c") +target_link_libraries(cpc PRIVATE Threads::Threads) -# Enable gpiod support if the user requested it +set(CPCD_SOURCES + "${PROJECT_SOURCE_DIR}/driver/driver_ezsp.c" + "${PROJECT_SOURCE_DIR}/driver/driver_kill.c" + "${PROJECT_SOURCE_DIR}/driver/driver_spi.c" + "${PROJECT_SOURCE_DIR}/driver/driver_uart.c" + "${PROJECT_SOURCE_DIR}/driver/driver_xmodem.c" + "${PROJECT_SOURCE_DIR}/misc/board_controller.c" + "${PROJECT_SOURCE_DIR}/misc/config.c" + "${PROJECT_SOURCE_DIR}/misc/exit.c" + "${PROJECT_SOURCE_DIR}/misc/logging.c" + "${PROJECT_SOURCE_DIR}/misc/sl_slist.c" + "${PROJECT_SOURCE_DIR}/misc/sleep.c" + "${PROJECT_SOURCE_DIR}/misc/utils.c" + "${PROJECT_SOURCE_DIR}/modes/firmware_update.c" + "${PROJECT_SOURCE_DIR}/modes/normal.c" + "${PROJECT_SOURCE_DIR}/modes/uart_validation.c" + "${PROJECT_SOURCE_DIR}/server_core/core/buffer.c" + "${PROJECT_SOURCE_DIR}/server_core/core/core.c" + "${PROJECT_SOURCE_DIR}/server_core/core/crc.c" + "${PROJECT_SOURCE_DIR}/server_core/core/hdlc.c" + "${PROJECT_SOURCE_DIR}/server_core/core/protocol.c" + "${PROJECT_SOURCE_DIR}/server_core/core/protocol_v4.c" + "${PROJECT_SOURCE_DIR}/server_core/core/protocol_v5.c" + "${PROJECT_SOURCE_DIR}/server_core/epoll/epoll.c" + "${PROJECT_SOURCE_DIR}/server_core/server/server.c" + "${PROJECT_SOURCE_DIR}/server_core/server/server_ready_sync.c" + "${PROJECT_SOURCE_DIR}/server_core/server_core.c" + "${PROJECT_SOURCE_DIR}/server_core/system_endpoint/system.c") if(USE_LEGACY_GPIO_SYSFS) - message(STATUS "Building CPCd with GPIO sysfs") + list(APPEND CPCD_SOURCES "${PROJECT_SOURCE_DIR}/misc/gpio_sysfs.c") else() - message(STATUS "Building CPCd with GPIO device") + list(APPEND CPCD_SOURCES "${PROJECT_SOURCE_DIR}/misc/gpio.c") endif() - -if(TARGET_TESTING) - add_definitions(-DTARGET_TESTING) -endif() - -# Build CPC Daemon if building for release or debug -if((TARGET_GROUP STREQUAL release) OR - (TARGET_GROUP STREQUAL debug) OR - (TARGET_GROUP STREQUAL blackbox_test) OR - (TARGET_GROUP STREQUAL blackbox_test_spurious_reset) OR - (TARGET_GROUP STREQUAL blackbox_test_large_buf) OR - (TARGET_GROUP STREQUAL blackbox_test_nonce_overflow) OR - (TARGET_GROUP STREQUAL blackbox_test_multi_spi)) - message(STATUS "Building CPC Daemon") - - if((TARGET_GROUP STREQUAL debug) OR - (TARGET_GROUP STREQUAL blackbox_test) OR - (TARGET_GROUP STREQUAL blackbox_test_spurious_reset) OR - (TARGET_GROUP STREQUAL blackbox_test_large_buf) OR - (TARGET_GROUP STREQUAL blackbox_test_nonce_overflow)) - add_compile_options(-funwind-tables) - # CMake<3.13 does not support target_link_options - target_link_libraries(backtrace INTERFACE "-rdynamic") - set(CMAKE_BUILD_TYPE RelWithDebInfo) - endif() - - if(TARGET_GROUP STREQUAL blackbox_test_nonce_overflow) - # 2^29 - 4 - add_definitions("-DSLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE=536870908") - set(ENABLE_ENCRYPTION TRUE CACHE BOOL "" FORCE) - set(RUN_TESTS_ENCRYPTED "TRUE" CACHE STRING "Run tests with encryption") - endif() - - # CMake<3.11 requires two arguments - add_executable(cpcd main.c) - target_stds(cpcd C 99 POSIX 2008) - target_link_libraries(cpcd PRIVATE Interface::Warnings) - target_sources(cpcd PRIVATE - server_core/server_core.c - server_core/epoll/epoll.c - server_core/core/buffer.c - server_core/core/core.c - server_core/core/crc.c - server_core/core/hdlc.c - server_core/core/protocol.c - server_core/core/protocol_v4.c - server_core/core/protocol_v5.c - server_core/server/server.c - server_core/server/server_ready_sync.c - server_core/system_endpoint/system.c - driver/driver_spi.c - driver/driver_uart.c - driver/driver_xmodem.c - driver/driver_ezsp.c - driver/driver_kill.c - misc/exit.c - misc/logging.c - misc/config.c - misc/utils.c - misc/sl_slist.c - misc/board_controller.c - misc/sleep.c - modes/firmware_update.c - modes/normal.c - modes/uart_validation.c - lib/sl_cpc.c) - - if(COMPILE_LTTNG) - message(STATUS "Building CPC Daemon with LTTNG tracing enabled. Set ENABLE_LTTNG_TRACING=true in config file to activate it.") - target_compile_definitions(cpcd PRIVATE COMPILE_LTTNG) - target_link_libraries(cpcd PRIVATE LTTng::UST) - endif() - - target_include_directories(cpcd PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") - target_include_directories(cpcd PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") - target_include_directories(cpcd PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") - target_include_directories(cpcd PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib") - target_link_libraries(cpcd PRIVATE Threads::Threads) +if(ENABLE_ENCRYPTION) + list(APPEND CPCD_SOURCES + "${PROJECT_SOURCE_DIR}/modes/binding.c" + "${PROJECT_SOURCE_DIR}/security/private/keys/keys.c" + "${PROJECT_SOURCE_DIR}/security/private/protocol/protocol.c" + "${PROJECT_SOURCE_DIR}/security/private/thread/command_synchronizer.c" + "${PROJECT_SOURCE_DIR}/security/private/thread/security_thread.c" + "${PROJECT_SOURCE_DIR}/security/security.c") +endif() + +add_executable(cpcd "./main.c") +set_target_properties(cpcd PROPERTIES + C_STANDARD 99 C_STANDARD_REQUIRED YES C_EXTENSIONS NO) +target_compile_definitions(cpcd PRIVATE _GNU_SOURCE) +target_include_directories(cpcd PRIVATE "${PROJECT_BINARY_DIR}") +target_include_directories(cpcd PRIVATE "./include" ".") +target_sources(cpcd PRIVATE ${CPCD_SOURCES}) +target_link_libraries(cpcd PRIVATE Threads::Threads cpc) +if(TARGET MbedTLS::mbedcrypto) + target_link_libraries(cpcd PRIVATE MbedTLS::mbedcrypto) +endif() +if(TARGET backtrace) target_link_libraries(cpcd PRIVATE backtrace) - - if(ENABLE_ENCRYPTION) - target_link_libraries(cpcd PRIVATE MbedTLS::mbedcrypto) - target_sources(cpcd PRIVATE - modes/binding.c - security/private/keys/keys.c - security/private/protocol/protocol.c - security/private/thread/command_synchronizer.c - security/private/thread/security_thread.c - security/security.c) - endif() - - if(USE_LEGACY_GPIO_SYSFS) - target_compile_definitions(cpcd PRIVATE USE_LEGACY_GPIO_SYSFS) - target_sources(cpcd PRIVATE misc/gpio_sysfs.c) - else() - target_sources(cpcd PRIVATE misc/gpio.c) - endif() - - # Hash all files except those in the output folder - get_target_property(CPCD_SOURCES cpcd SOURCES) - foreach(file ${CPCD_SOURCES}) - file(SHA256 "${CMAKE_CURRENT_SOURCE_DIR}/${file}" FILE_HASH) - string(APPEND SOURCES_HASH "${FILE_HASH}") - string(SHA256 SOURCES_HASH "${SOURCES_HASH}") - endforeach() - message(STATUS "Sources hash: ${SOURCES_HASH}") - - install(TARGETS cpc cpcd - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - PRIVATE_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - - install(FILES cpcd.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR} COMPONENT config) endif() -# Build CPC Daemon for release, nothing to do -if(TARGET_GROUP STREQUAL release) - message(STATUS "Building release version") +### -# Build CPC Daemon for debug, add debug flags -elseif(TARGET_GROUP STREQUAL debug) - message(STATUS "Building debug version") - set(CMAKE_BUILD_TYPE Debug) - -# Build CPC Daemon for self tests -elseif((TARGET_GROUP STREQUAL unit_test) OR (TARGET_GROUP STREQUAL unit_test_with_valgrind)) - message(STATUS "Building unit tests") - set(CMAKE_BUILD_TYPE Debug) - add_definitions(-DUNIT_TESTING) - enable_testing() - include(CTest) - - if(NOT DEFINED UNITY_PATH) - set(UNITY_SOURCES "${CMAKE_CURRENT_LIST_DIR}/../../../../util/third_party/unity") - else() - set(UNITY_SOURCES ${UNITY_PATH}) - endif() - - add_definitions(-DHOST_BUILD) - add_library(unity STATIC ${UNITY_SOURCES}/src/unity.c) - set_target_properties(unity PROPERTIES PUBLIC_HEADER ${UNITY_SOURCES}/src/unity.h) - target_include_directories(unity PUBLIC ${UNITY_SOURCES}/src/) - - add_executable(cpc_unity - server_core/server_core.c - server_core/epoll/epoll.c - server_core/core/buffer.c - server_core/core/core.c - server_core/core/crc.c - server_core/core/hdlc.c - server_core/core/protocol.c - server_core/core/protocol_v4.c - server_core/core/protocol_v5.c - server_core/server/server.c - server_core/server/server_ready_sync.c - server_core/system_endpoint/system.c - security/security.c - security/private/keys/keys.c - security/private/protocol/protocol.c - security/private/thread/command_synchronizer.c - security/private/thread/security_thread.c - driver/driver_emul.c - driver/driver_kill.c - driver/driver_uart.c - lib/sl_cpc.c - modes/uart_validation.c - misc/exit.c - misc/logging.c - misc/config.c - misc/utils.c - misc/sl_slist.c - misc/board_controller.c - misc/sleep.c - test/unity/endpoints.c - test/unity/ack.c - test/unity/crc.c - test/unity/read.c - test/unity/write.c - test/unity/hdlc.c - test/unity/reject.c - test/unity/security.c - test/unity/re_transmit.c - test/unity/cpc_unity_common.c - test/unity/main.c) - - target_include_directories(cpc_unity PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") - target_include_directories(cpc_unity PRIVATE ${UNITY_SOURCES}/src/) - target_include_directories(cpc_unity PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") - target_include_directories(cpc_unity PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") - target_include_directories(cpc_unity PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib") - target_link_libraries(cpc_unity PRIVATE Threads::Threads MbedTLS::mbedcrypto) - target_link_libraries(cpc_unity PRIVATE backtrace) - target_link_libraries(cpc_unity PRIVATE cpc unity) - - # Run the tests - add_subdirectory(test/unity) - -elseif((TARGET_GROUP STREQUAL blackbox_test) OR (TARGET_GROUP STREQUAL blackbox_test_multi_spi)) - message(STATUS "Building blackbox_test") - - set(CMAKE_BUILD_TYPE Debug) - include_directories(test/blackbox/) - - add_executable(lib_client - test/blackbox/cpc_lib_client.c) - - target_include_directories(lib_client PRIVATE lib/) - target_include_directories(lib_client PRIVATE misc/) - target_include_directories(lib_client PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") - target_link_libraries(lib_client PRIVATE Threads::Threads) - target_link_libraries(lib_client PRIVATE cpc) - - enable_testing() - include(CTest) - - if(NOT DEFINED UNITY_PATH) - set(UNITY_SOURCES "${CMAKE_CURRENT_LIST_DIR}/../../../../util/third_party/unity") - else() - set(UNITY_SOURCES ${UNITY_PATH}) - endif() - - add_definitions(-DHOST_BUILD) - add_library(unity STATIC ${UNITY_SOURCES}/src/unity.c) - set_target_properties(unity PROPERTIES PUBLIC_HEADER ${UNITY_SOURCES}/src/unity.h) - target_include_directories(unity PUBLIC ${UNITY_SOURCES}/src/) - - target_link_libraries(lib_client PRIVATE cpc unity) - - # Run the tests - if(TARGET_GROUP STREQUAL blackbox_test) - add_subdirectory(test/blackbox) - elseif(TARGET_GROUP STREQUAL blackbox_test_multi_spi) - add_subdirectory(test/blackbox/multi_spi) - endif() - -elseif(TARGET_GROUP STREQUAL blackbox_test_spurious_reset) - message(STATUS "Building blackbox_test_spurious_reset") - - set(CMAKE_BUILD_TYPE Debug) - include_directories(test/blackbox/) - - add_executable(lib_client - test/blackbox/cpc_lib_client.c) - - target_include_directories(lib_client PRIVATE lib/) - target_include_directories(lib_client PRIVATE misc/) - target_include_directories(lib_client PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") - target_link_libraries(lib_client PRIVATE Threads::Threads) - target_link_libraries(lib_client PRIVATE cpc) - - enable_testing() - include(CTest) - - if(NOT DEFINED UNITY_PATH) - set(UNITY_SOURCES "${CMAKE_CURRENT_LIST_DIR}/../../../../util/third_party/unity") - else() - set(UNITY_SOURCES ${UNITY_PATH}) - endif() - - add_definitions(-DHOST_BUILD) - add_definitions(-DTEST_SECONDARY_CRASH) - - add_library(unity STATIC ${UNITY_SOURCES}/src/unity.c) - set_target_properties(unity PROPERTIES PUBLIC_HEADER ${UNITY_SOURCES}/src/unity.h) - target_include_directories(unity PUBLIC ${UNITY_SOURCES}/src/) - - target_link_libraries(lib_client PRIVATE cpc unity) - - # Run the tests - add_subdirectory(test/blackbox) - -elseif(TARGET_GROUP STREQUAL blackbox_test_large_buf) - message(STATUS "Building blackbox_test_large_buf") - - set(CMAKE_BUILD_TYPE Debug) - include_directories(test/blackbox/) - - add_definitions(-DDATA_CHUNK_SIZE=4087) - - add_executable(lib_client - test/blackbox/cpc_lib_client.c) - - target_include_directories(lib_client PRIVATE lib/) - target_include_directories(lib_client PRIVATE misc/) - target_include_directories(lib_client PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") - target_link_libraries(lib_client PRIVATE Threads::Threads) - target_link_libraries(lib_client PRIVATE cpc) - - enable_testing() - include(CTest) - - if(NOT DEFINED UNITY_PATH) - set(UNITY_SOURCES "${CMAKE_CURRENT_LIST_DIR}/../../../../util/third_party/unity") - else() - set(UNITY_SOURCES ${UNITY_PATH}) - endif() - - add_definitions(-DHOST_BUILD) - add_library(unity STATIC ${UNITY_SOURCES}/src/unity.c) - set_target_properties(unity PROPERTIES PUBLIC_HEADER ${UNITY_SOURCES}/src/unity.h) - target_include_directories(unity PUBLIC ${UNITY_SOURCES}/src/) - - target_link_libraries(lib_client PRIVATE cpc unity) - - # Run the tests - add_subdirectory(test/blackbox) -elseif(TARGET_GROUP STREQUAL blackbox_test_nonce_overflow) - message(STATUS "Building blackbox_test") - - set(CMAKE_BUILD_TYPE Debug) - include_directories(test/blackbox/) - - add_executable(lib_client - test/blackbox/cpc_lib_client_overflow.c) - - target_include_directories(lib_client PRIVATE lib/) - target_include_directories(lib_client PRIVATE misc/) - target_include_directories(lib_client PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/autogen") - target_link_libraries(lib_client PRIVATE Threads::Threads) - target_link_libraries(lib_client PRIVATE cpc) - - enable_testing() - include(CTest) - - if(NOT DEFINED UNITY_PATH) - set(UNITY_SOURCES "${CMAKE_CURRENT_LIST_DIR}/../../../../util/third_party/unity") - else() - set(UNITY_SOURCES ${UNITY_PATH}) - endif() - - add_definitions(-DHOST_BUILD) - add_library(unity STATIC ${UNITY_SOURCES}/src/unity.c) - set_target_properties(unity PROPERTIES PUBLIC_HEADER ${UNITY_SOURCES}/src/unity.h) - target_include_directories(unity PUBLIC ${UNITY_SOURCES}/src/) - - target_link_libraries(lib_client PRIVATE cpc unity) - - # Run the tests - add_subdirectory(test/blackbox) - -else() - message(FATAL_ERROR "Given TARGET_GROUP unknown specify when running cmake.. i.g: -DTARGET_GROUP=release") +if(BUILD_TESTING AND (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)) + message(STATUS "Enabling tests (${BUILD_TESTING})") + add_subdirectory("./test") endif() -# Configure the version header file -configure_file(misc/version.h.in autogen/version.h) +### + +install(TARGETS cpc + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") +install( + FILES "${PROJECT_BINARY_DIR}/libcpc.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +install(TARGETS cpcd + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") +install(FILES "./cpcd.conf" DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}") diff --git a/cmake-variants.yaml b/cmake-variants.yaml deleted file mode 100644 index 9767d31..0000000 --- a/cmake-variants.yaml +++ /dev/null @@ -1,35 +0,0 @@ -TARGET_GROUP: - default: release - choices: - release: - short: Release - settings: - TARGET_GROUP: release - debug: - short: Debug - settings: - TARGET_GROUP: debug - blackbox_test: - short: Blackbox Test - settings: - TARGET_GROUP: blackbox_test - blackbox_test_spurious_reset: - short: Blackbox Test Spurious Reset - settings: - TARGET_GROUP: blackbox_test_spurious_reset - blackbox_test_large_buf: - short: Blackbox Test Large Buf - settings: - TARGET_GROUP: blackbox_test_large_buf - unit_test: - short: Unit Test - settings: - TARGET_GROUP: unit_test - unit_test_with_valgrind: - short: Unit Test With Valgrind - settings: - TARGET_GROUP: unit_test_with_valgrind - target_test: - short: Target Test - settings: - TARGET_GROUP: target_test diff --git a/cmake/Warnings.cmake b/cmake/Warnings.cmake index d6e24c4..813c2d0 100644 --- a/cmake/Warnings.cmake +++ b/cmake/Warnings.cmake @@ -1,12 +1,7 @@ # Inspired by Meson's warning_level option -add_library(_Warnings INTERFACE) -add_library(Interface::Warnings ALIAS _Warnings) - if(NOT DEFINED WARNING_LEVEL) - if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "Debug") - set(WARNING_LEVEL 2) - endif() + set(WARNING_LEVEL 2) endif() if(WARNING_LEVEL GREATER_EQUAL "1") @@ -20,7 +15,10 @@ if(WARNING_LEVEL GREATER_EQUAL "1") # Custom warnings list(APPEND _POSSIBLE_WARNINGS -Wconversion + -Wformat=2 + -Wlogical-op -Wmissing-declarations + -Wpointer-arith -Wsign-conversion -Wswitch-default ) @@ -28,11 +26,18 @@ if(WARNING_LEVEL GREATER_EQUAL "1") include(CheckCCompilerFlag) foreach(_WARNING IN LISTS _POSSIBLE_WARNINGS) - string(MAKE_C_IDENTIFIER "${_WARNING}" _warning) + string(MAKE_C_IDENTIFIER ${_WARNING} _warning) check_c_compiler_flag(${_WARNING} ${_warning}) if(${_warning}) - target_compile_options(_Warnings INTERFACE "${_WARNING}") + add_compile_options(${_WARNING}) endif() endforeach() unset(_POSSIBLE_WARNINGS) endif() + +if(CMAKE_VERSION VERSION_LESS "3.24") + if(CMAKE_COMPILE_WARNING_AS_ERROR) + message(STATUS "Treating compile warnings as errors") + add_compile_options(-Werror) + endif() +endif() diff --git a/cmake/modules/FindMbedTLS.cmake b/cmake/modules/FindMbedTLS.cmake index 624c827..381e725 100644 --- a/cmake/modules/FindMbedTLS.cmake +++ b/cmake/modules/FindMbedTLS.cmake @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.7) include(FindPackageHandleStandardArgs) -if(DEFINED MbedTLS_FOUND) +if(MbedTLS_FOUND) return() endif() diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..53cad51 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +cpc-daemon (4.4.0) unstable; urgency=medium + + * Initial release. + + -- Issam Maghni Mon, 01 Apr 2024 15:30:00 -0400 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..8a0e6a4 --- /dev/null +++ b/debian/control @@ -0,0 +1,46 @@ +Source: cpc-daemon +Section: misc +Priority: optional +Maintainer: Issam Maghni +Build-Depends: + debhelper-compat (= 10), + cmake, + pkgconf | pkg-config, + libmbedtls-dev (>= 2.16), +Standards-Version: 4.6.1 + +Package: libcpc3 +Architecture: linux-any +Multi-Arch: same +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: + ${shlibs:Depends}, + ${misc:Depends}, +Description: CPC library + This library offers a safe API to communicate using multiple endpoints + with a secondary processor through the CPC daemon. + +Package: libcpc-dev +Architecture: linux-any +Multi-Arch: same +Section: libdevel +Pre-Depends: ${misc:Pre-Depends} +Depends: + libcpc3 (= ${binary:Version}), + ${misc:Depends}, +Description: CPC development +Provides: libcpc3-dev + +Package: cpcd +Architecture: linux-any +Multi-Arch: foreign +Pre-Depends: ${misc:Pre-Depends} +# cpcd communicates only with the same library version +Depends: + libcpc3 (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends}, +Description: CPC daemon + This daemon permits the CPC library to communicate with a secondary + processor using multiple endpoints through a shared physical link. diff --git a/debian/cpcd.install b/debian/cpcd.install new file mode 100644 index 0000000..3caf082 --- /dev/null +++ b/debian/cpcd.install @@ -0,0 +1,2 @@ +usr/bin/* +etc/* diff --git a/debian/libcpc-dev.install b/debian/libcpc-dev.install new file mode 100644 index 0000000..7df81cd --- /dev/null +++ b/debian/libcpc-dev.install @@ -0,0 +1,3 @@ +usr/include/* +usr/lib/*/lib*.so +usr/lib/*/pkgconfig/* diff --git a/debian/libcpc3.install b/debian/libcpc3.install new file mode 100644 index 0000000..3ddde58 --- /dev/null +++ b/debian/libcpc3.install @@ -0,0 +1 @@ +usr/lib/*/lib*.so.* diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..a1a6fc5 --- /dev/null +++ b/debian/rules @@ -0,0 +1,12 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ + +ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) +override_dh_auto_configure: + dh_auto_configure -- -D CMAKE_COMPILE_WARNING_AS_ERROR=YES -D BUILD_TESTING=YES -D UNITY_DIR=../../unity +endif diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/doc/troubleshooting.md b/doc/troubleshooting.md index 9f1af33..7798300 100644 --- a/doc/troubleshooting.md +++ b/doc/troubleshooting.md @@ -25,7 +25,7 @@ Adding the `cpc_journal` component enables efficient logging of CPC events. This For projects with a command line interface, the `cpc_journal_cli` component introduces the `print_cpc_journal` command. This command prints the contents of the CPC Journal in a CSV format via the CLI. -Additionally, projects with the `iostream` component can use `sl_cpc_journal_print`. +Additionally, projects with the `iostream` component can use `sl_cpc_journal_print`. This function allows for printing the journal's contents. **Note: Entries are consumed when printed** @@ -47,11 +47,11 @@ If the issue is reproduced fairly quickly, the `enable_frame_trace` configuratio can be used to enable an additional level of information to the traces. #### Log Rotation -When an issue takes a longer time to reproduce, trace files might occupy excessive space on the target. -To manage this, the [logrotate](https://linux.die.net/man/8/logrotate) tool can be utilized to consolidate logs. +When an issue takes a longer time to reproduce, trace files might occupy excessive space on the target. +To manage this, the [logrotate](https://linux.die.net/man/8/logrotate) tool can be utilized to consolidate logs. Below is an example of a logrotate configuration, that will retain 10 log files, -each up to 10 MB in size, and rotate them accordingly. +each up to 10 MB in size, and rotate them accordingly. Log compression can be done by adding the `compress` option in the configuration. ``` /home/pi/cpcd_log/*.log { @@ -102,8 +102,9 @@ Traces are then sent over `stderr` with the associated timestamp. ## Debugging CPCd with GDB First, add debug symbols to the CPCd binary by specifying the `debug` target group: ``` -mkdir build -cmake ../ -DTARGET_GROUP=debug +mkdir ./build +cd ./build +cmake -D CMAKE_BUILD_TYPE=Debug .. make ``` @@ -165,7 +166,7 @@ Provide the following details: * **CPCd Version**: Specify the version of the CPCd you are using. * **Operating System & Version**: e.g., Raspbian, Ubuntu * **Hardware Information**: Details about the primary and secondary processors involved. -* **Secondary Version**: The version of the GSDK release being used +* **Secondary Version**: The version of the Simplicity SDK release being used * **CPCd Compilation**: * Compiler: [Name, Version] * **Secondary Compilation**: diff --git a/driver/driver_emul.c b/driver/driver_emul.c index 90c374b..86c699e 100644 --- a/driver/driver_emul.c +++ b/driver/driver_emul.c @@ -15,7 +15,8 @@ * ******************************************************************************/ -#define _GNU_SOURCE +#include "config.h" + #include #include @@ -28,6 +29,10 @@ #include #include +#if defined(__ANDROID__) +#include +#endif + #include "cpcd/core.h" #include "cpcd/logging.h" #include "cpcd/security.h" @@ -61,10 +66,22 @@ typedef struct { static void* driver_thread_func(void* param); -void driver_emul_kill(void) +#if defined(__ANDROID__) +static void driver_emul_kill_handler(int signum) +{ + (void)signum; + pthread_exit(NULL); +} +#endif + +static void driver_emul_kill(void) { if (drv_thread_started) { +#if defined(__ANDROID__) + pthread_kill(drv_thread, SIGUSR1); +#else pthread_cancel(drv_thread); +#endif drv_thread_started = false; } } @@ -83,10 +100,14 @@ void driver_emul_init(int* fd_core, int *fd_notify_core) fd_socket_drv = fd_sockets[0]; - /* setup driver kill */ +#if defined(__ANDROID__) + signal(SIGUSR1, &driver_emul_kill_handler); +#endif + + // setup driver kill driver_kill_init(driver_emul_kill); - /* create driver thread */ + // create driver thread if (pthread_create(&drv_thread, NULL, driver_thread_func, NULL)) { FATAL("Error creating driver thread"); } @@ -177,12 +198,12 @@ void sli_cpc_drv_emul_submit_pkt_for_rx(void *header_buf, void *payload_buf, uin // recreate header with adjusted tag length hdlc_create_header(buffer, address, - hdlc_get_length(header_buf) + tag_len, + (uint16_t)(hdlc_get_length(header_buf) + tag_len), hdlc_get_control(header_buf), true); // FCS is part of payload_buf_len, drop it as it's useless to us now - payload_buf_len -= 2; + payload_buf_len = (uint16_t)(payload_buf_len - 2); endpoint.id = hdlc_get_address(header_buf); endpoint.frame_counter_tx = ep_frame_counters_tx[endpoint.id]; @@ -207,12 +228,12 @@ void sli_cpc_drv_emul_submit_pkt_for_rx(void *header_buf, void *payload_buf, uin // recompute FCS with encrypted payload + tag fcs = sli_cpc_get_crc_sw(&buffer[SLI_CPC_HDLC_HEADER_RAW_SIZE], - payload_buf_len + tag_len); + (uint16_t)(payload_buf_len + tag_len)); buffer[SLI_CPC_HDLC_HEADER_RAW_SIZE + payload_buf_len + tag_len + 0] = (uint8_t)fcs; buffer[SLI_CPC_HDLC_HEADER_RAW_SIZE + payload_buf_len + tag_len + 1] = (uint8_t)(fcs >> 8); // restore payload_buf_len to accomodate "send" - payload_buf_len += 2; + payload_buf_len = (uint16_t)(payload_buf_len + 2); #endif } else { memcpy(buffer, header_buf, SLI_CPC_HDLC_HEADER_RAW_SIZE); @@ -221,7 +242,7 @@ void sli_cpc_drv_emul_submit_pkt_for_rx(void *header_buf, void *payload_buf, uin } } - (void)send(fd_socket_drv, buffer, payload_buf_len + tag_len + SLI_CPC_HDLC_HEADER_RAW_SIZE, 0); + send(fd_socket_drv, buffer, (size_t)payload_buf_len + (size_t)tag_len + (size_t)SLI_CPC_HDLC_HEADER_RAW_SIZE, 0); free(buffer); } @@ -320,15 +341,17 @@ static void* driver_thread_func(void* param) uint16_t tag_len = (uint16_t)security_encrypt_get_extra_buffer_size(); #endif +#if !defined(__ANDROID__) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); +#endif while (1) { FD_ZERO(&rfds); FD_SET(fd_socket_drv, &rfds); max_fd = fd_socket_drv; - /* select() requires the number of the highest file descriptor + 1 in the fd_set passed */ + // select() requires the number of the highest file descriptor + 1 in the fd_set passed max_fd++; - //no timeout + // no timeout retval = select(max_fd, &rfds, NULL, NULL, NULL); if (retval == -1) { perror("select()"); @@ -367,7 +390,7 @@ static void* driver_thread_func(void* param) sl_status_t status; uint8_t ack; - /* the payload buffer must be longer than the security tag */ + // the payload buffer must be longer than the security tag BUG_ON(length < tag_len); length = (uint16_t)(length - tag_len - 2); @@ -377,7 +400,7 @@ static void* driver_thread_func(void* param) ack = hdlc_get_ack(hdlc_get_control(frame->header)); hdlc_set_control_ack(&frame->header[SLI_CPC_HDLC_CONTROL_POS], 0); - /* decrypt like the secondary would do when receiving such frame */ + // decrypt like the secondary would do when receiving such frame status = security_decrypt_secondary(&endpoint, frame->header, SLI_CPC_HDLC_HEADER_SIZE, frame->payload, length, @@ -395,7 +418,7 @@ static void* driver_thread_func(void* param) TRACE_DRIVER("Successfully decrypted frame\n"); } - /* copy plaintext buffer at the payload pointer */ + // copy plaintext buffer at the payload pointer memcpy(frame->payload, plaintext_buffer, length); } #endif @@ -420,14 +443,14 @@ static void* driver_thread_func(void* param) memcpy(&system_cmd, frame->payload, sizeof(system_cmd)); - /* system_cmd.payload cannot be used because it's a flexible array, - * and its content is not copied by the memcpy */ + // system_cmd.payload cannot be used because it's a flexible array, + // and its content is not copied by the memcpy system_cmd_payload = frame->payload + sizeof(system_cmd); sli_cpc_system_property_cmd_t system_property_cmd; memcpy(&system_property_cmd, system_cmd_payload, sizeof(system_property_cmd)); - property_length = system_cmd.length - sizeof(sli_cpc_property_id_t); + property_length = (uint16_t)(system_cmd.length - sizeof(sli_cpc_property_id_t)); property_payload = frame->payload + sizeof(sli_cpc_system_cmd_t) + sizeof(sli_cpc_system_property_cmd_t); @@ -455,10 +478,17 @@ static void* driver_thread_func(void* param) + 2; } else if (system_property_cmd.property_id >= EP_ID_TO_PROPERTY_ENCRYPTION(1) && system_property_cmd.property_id <= EP_ID_TO_PROPERTY_ENCRYPTION(255)) { - buf_len = sizeof(sli_cpc_system_cmd_t) - + sizeof(sli_cpc_property_id_t) - + sizeof(bool) - + 2; + if (system_cmd.command_id == CMD_SYSTEM_PROP_VALUE_GET) { + buf_len = sizeof(sli_cpc_system_cmd_t) + + sizeof(sli_cpc_property_id_t) + + sizeof(bool) + + 2; + } else { + buf_len = sizeof(sli_cpc_system_cmd_t) + + sizeof(sli_cpc_property_id_t) + + 2 * sizeof(uint32_t) + + 2; + } } FATAL_ON(buf_len < 2); @@ -490,32 +520,48 @@ static void* driver_thread_func(void* param) } else if (system_cmd.command_id == CMD_SYSTEM_PROP_VALUE_SET) { TRACE_DRIVER("Replying to property set"); uint8_t ep_id = PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id); - sli_cpc_endpoint_state_t requested_state; - memcpy(&requested_state, property_payload, sizeof(requested_state)); + if ((system_property_cmd.property_id >= EP_ID_TO_PROPERTY_STATE(1) + && system_property_cmd.property_id <= EP_ID_TO_PROPERTY_STATE(255))) { + sli_cpc_endpoint_state_t requested_state; + + memcpy(&requested_state, property_payload, sizeof(requested_state)); - TRACE_DRIVER("Property set for ep #%d requested state %d, current %d", - ep_id, requested_state, ep_states[ep_id]); + TRACE_DRIVER("Property set for ep #%d requested state %d, current %d", + ep_id, requested_state, ep_states[ep_id]); - if (requested_state == SLI_CPC_STATE_CONNECTED) { - if (ep_states[ep_id] == SLI_CPC_STATE_OPEN) { - ep_states[ep_id] = SLI_CPC_STATE_CONNECTED; - TRACE_DRIVER("Property set forcing state CONNECTED for ep #%d", + if (requested_state == SLI_CPC_STATE_CONNECTED) { + if (ep_states[ep_id] == SLI_CPC_STATE_OPEN) { + ep_states[ep_id] = SLI_CPC_STATE_CONNECTED; + TRACE_DRIVER("Property set forcing state CONNECTED for ep #%d", + ep_id); + } + } else if (requested_state == SLI_CPC_STATE_CLOSED) { + ep_states[ep_id] = SLI_CPC_STATE_CLOSED; + } + + // Create the set property reply + sli_cpc_drv_emul_create_set_endpoint_status_reply((sli_cpc_system_cmd_t *)buffer, + PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id), + system_cmd.command_seq, + ep_states[PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id)]); + if (requested_state == SLI_CPC_STATE_CLOSED && ep_states[ep_id] == SLI_CPC_STATE_CLOSED) { + ep_states[ep_id] = SLI_CPC_STATE_OPEN; + TRACE_DRIVER("Property set forcing state OPEN for ep #%d", ep_id); } - } else if (requested_state == SLI_CPC_STATE_CLOSED) { - ep_states[ep_id] = SLI_CPC_STATE_CLOSED; - } + } else if (system_property_cmd.property_id >= EP_ID_TO_PROPERTY_ENCRYPTION(1) + && system_property_cmd.property_id <= EP_ID_TO_PROPERTY_ENCRYPTION(255)) { + sli_cpc_system_cmd_t *tx_cmd = (sli_cpc_system_cmd_t *)buffer; + + tx_cmd->command_id = CMD_SYSTEM_PROP_VALUE_IS; + tx_cmd->command_seq = system_cmd.command_seq; + tx_cmd->length = sizeof(sli_cpc_property_id_t) + 2 * sizeof(uint32_t); + + sli_cpc_system_property_cmd_t *tx_property = (sli_cpc_system_property_cmd_t*)tx_cmd->payload; - // Create the set property reply - sli_cpc_drv_emul_create_set_endpoint_status_reply((sli_cpc_system_cmd_t *)buffer, - PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id), - system_cmd.command_seq, - ep_states[PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id)]); - if (requested_state == SLI_CPC_STATE_CLOSED && ep_states[ep_id] == SLI_CPC_STATE_CLOSED) { - ep_states[ep_id] = SLI_CPC_STATE_OPEN; - TRACE_DRIVER("Property set forcing state OPEN for ep #%d", - ep_id); + tx_property->property_id = system_property_cmd.property_id; + memcpy(tx_property->payload, property_payload, property_length); } } else { BUG("Invalid command id"); diff --git a/driver/driver_emul.h b/driver/driver_emul.h index 53c537b..ea432f4 100644 --- a/driver/driver_emul.h +++ b/driver/driver_emul.h @@ -18,7 +18,6 @@ #ifndef DRV_UART_H #define DRV_UART_H -#define _GNU_SOURCE #include #include diff --git a/driver/driver_ezsp.c b/driver/driver_ezsp.c index 33dadff..9af9419 100644 --- a/driver/driver_ezsp.c +++ b/driver/driver_ezsp.c @@ -14,6 +14,9 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ + +#include "config.h" + #include #include #include @@ -469,7 +472,7 @@ static sl_status_t send_command(struct spi_interface *spi, uint8_t command, uint static sl_status_t send_command_with_retries(struct spi_interface *spi, uint8_t command, uint8_t * const rx_buffer) { - sl_status_t status; + sl_status_t status = SL_STATUS_OK; size_t retries = MAX_RETRANSMIT_ATTEMPTS; while (retries--) { diff --git a/driver/driver_ezsp.h b/driver/driver_ezsp.h index d351814..6d3f1b1 100644 --- a/driver/driver_ezsp.h +++ b/driver/driver_ezsp.h @@ -18,7 +18,6 @@ #ifndef DRIVER_EZSP_H #define DRIVER_EZSP_H -#define _GNU_SOURCE #include #include diff --git a/driver/driver_kill.c b/driver/driver_kill.c index 75cbe41..89748b0 100644 --- a/driver/driver_kill.c +++ b/driver/driver_kill.c @@ -14,8 +14,10 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE /* See feature_test_macros(7) */ -#include /* Definition of O_* constants */ + +#include "config.h" + +#include // Definition of O_* constants #include #include diff --git a/driver/driver_spi.c b/driver/driver_spi.c index 3e74d94..605b128 100644 --- a/driver/driver_spi.c +++ b/driver/driver_spi.c @@ -14,7 +14,8 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE + +#include "config.h" #include #include @@ -42,8 +43,12 @@ #include "driver/driver_ezsp.h" #include "driver/driver_kill.h" -// This value is a reasonable worst case estimate of the interrupt latency when RAIL is used for the radio -#define MAXIMUM_REASONABLE_INTERRUPT_LATENCY_US 500 +// Convert a millisecond to microseconds +#define MS_TO_US (1000) + +// This value is a reasonable worst case estimate of how long the CPC core can hold +// the IRQ line when asserting its flow control when it's out of RX buffers. +#define MAXIMUM_REASONABLE_INTERRUPT_LATENCY_US (20 * MS_TO_US) static int fd_core; static int fd_core_notify; @@ -280,8 +285,6 @@ static long t2_minus_t1_us(struct timespec *t2, struct timespec *t1) */ static bool wait_for_irq_assert_or_timeout(size_t timeout_us) { - //TODO CPC-649 Rewrite this method - // In 99.99% of the cases, the secondary executed its header interrupt and lowered IRQ before // the host even returns from the SPI ioctl transfer call. Try executing the minimal amount of logic // path first @@ -303,7 +306,6 @@ static bool wait_for_irq_assert_or_timeout(size_t timeout_us) struct timespec now_time; clock_gettime(CLOCK_MONOTONIC, &now_time); - // Timeout on 10 * MAXIMUM_REASONABLE_INTERRUPT_LATENCY_US if (t2_minus_t1_us(&now_time, &start_time) > (long) timeout_us) { return false; } @@ -335,6 +337,7 @@ static void driver_spi_transaction(bool initiated_by_irq_line_event) bool want_to_receive = false; bool want_to_transmit = false; bool rx_header_checksum_error = false; + bool rx_payload_size_invalid = false; memset(&local_spi_transfer, 0x00, sizeof(local_spi_transfer)); @@ -467,6 +470,10 @@ static void driver_spi_transaction(bool initiated_by_irq_line_event) TRACE_DRIVER_INVALID_HEADER_CHECKSUM(); TRACE_DRIVER("Header checksum error"); + } else if ((unsigned long) rx_payload_size > sizeof(rx_buffer)) { + rx_payload_size_invalid = true; + rx_length = (size_t) rx_payload_size; + TRACE_DRIVER("RX buffer size from bus is invalid: %d", rx_payload_size); } else { rx_length = (size_t) rx_payload_size; } @@ -480,9 +487,9 @@ static void driver_spi_transaction(bool initiated_by_irq_line_event) } // Wait for the secondary to notify us we can clock the payload - bool ret = wait_for_irq_assert_or_timeout(10 * MAXIMUM_REASONABLE_INTERRUPT_LATENCY_US); + bool wait_successful = wait_for_irq_assert_or_timeout(MAXIMUM_REASONABLE_INTERRUPT_LATENCY_US); - if (ret == false) { //timed out + if (wait_successful == false) { //timed out if (secondary_started) { BUG("The IRQ it stuck abnormally long in the de-asserted state."); } else { @@ -522,6 +529,13 @@ static void driver_spi_transaction(bool initiated_by_irq_line_event) // If we received a bad header, we will clock the maximum theoretical number of bytes the secondary can // send us in order to purge its data local_spi_transfer.len = SPI_BUFFER_SIZE - SLI_CPC_HDLC_HEADER_RAW_SIZE; + } else if (rx_payload_size_invalid) { + // If we received a header with an RX size larget than the size of the + // RX buffer, send the requested number of bytes to purge its TX data. + // Normally, this should never happen however, since the secondary should + // prevent any payload larger than 4K to be sent over the bus. + local_spi_transfer.len = (unsigned int)(payload_length - SLI_CPC_HDLC_HEADER_RAW_SIZE); + local_spi_transfer.rx_buf = (unsigned long) NULL; } else { local_spi_transfer.len = (unsigned int) payload_length; } diff --git a/driver/driver_spi.h b/driver/driver_spi.h index c470782..9ada03c 100644 --- a/driver/driver_spi.h +++ b/driver/driver_spi.h @@ -18,7 +18,6 @@ #ifndef DRIVER_SPI_H #define DRIVER_SPI_H -#define _GNU_SOURCE #include #include diff --git a/driver/driver_uart.c b/driver/driver_uart.c index f279e06..637ed67 100644 --- a/driver/driver_uart.c +++ b/driver/driver_uart.c @@ -14,7 +14,8 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE + +#include "config.h" #include @@ -70,20 +71,20 @@ typedef struct notify_private_data{ int timer_file_descriptor; }notify_private_data_t; -/* +/***************************************************************************//** * @return The number of bytes appended to the buffer - */ + ******************************************************************************/ static size_t read_and_append_uart_received_data(uint8_t *buffer, size_t buffer_head, size_t buffer_size); -/* +/***************************************************************************//** * Call this function in loop over the buffer to delimit and push the frames to the core * * @return Whether or not this call has delimited a pushed a frame, in other words, * shall this function be called again in a loop - */ + ******************************************************************************/ static bool delimit_and_push_frames_to_core(uint8_t *buffer, size_t *buffer_head); -/* +/***************************************************************************//** * Insures the start of the buffer is aligned with the start of a valid checksum * and re-synch in case the buffer starts with garbage. ******************************************************************************/ @@ -97,7 +98,7 @@ void driver_uart_init(int *fd_to_core, int *fd_notify_core, const char *device, fd_uart = driver_uart_open(device, baudrate, hardflow); - /* Flush the uart IO fifo */ + // Flush the uart IO fifo tcflush(fd_uart, TCIOFLUSH); ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd_sockets); @@ -112,22 +113,20 @@ void driver_uart_init(int *fd_to_core, int *fd_notify_core, const char *device, fd_core_notify = fd_sockets_notify[0]; *fd_notify_core = fd_sockets_notify[1]; - /* - * Create stop driver event, this file descriptor will be used by - * receive and transmit thread to exit gracefully - */ + // Create stop driver event, this file descriptor will be used by + // receive and transmit thread to exit gracefully fd_stop_drv = eventfd(0, // Start with 0 value EFD_CLOEXEC); FATAL_SYSCALL_ON(fd_stop_drv == -1); // Set driver kill callback driver_kill_init(driver_uart_kill); - /* create transmitter driver thread */ + // create transmitter driver thread ret = pthread_create(&tx_drv_thread, NULL, transmit_driver_thread_func, NULL); FATAL_ON(ret != 0); tx_drv_thread_started = true; - /* create receiver driver thread */ + // create receiver driver thread ret = pthread_create(&rx_drv_thread, NULL, receive_driver_thread_func, NULL); FATAL_ON(ret != 0); rx_drv_thread_started = true; @@ -290,17 +289,17 @@ static void* receive_driver_thread_func(void* param) TRACE_DRIVER("Receiver thread start"); - /* Create the epoll set */ + // Create the epoll set fd_epoll = epoll_create1(EPOLL_CLOEXEC); FATAL_SYSCALL_ON(fd_epoll < 0); - /* Setup poll event for reading uart device */ + // Setup poll event for reading uart device events[0].events = EPOLLIN; events[0].data.fd = fd_uart; ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_uart, &events[0]); FATAL_SYSCALL_ON(ret < 0); - /* Setup poll event for stop event */ + // Setup poll event for stop event events[1].events = EPOLLIN; events[1].data.fd = fd_stop_drv; ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_stop_drv, &events[1]); @@ -309,32 +308,28 @@ static void* receive_driver_thread_func(void* param) while (!exit_thread) { int event_count; - /* Wait for action */ - { - do { - event_count = epoll_wait(fd_epoll, events, 2, -1); - if (event_count == -1 && errno == EINTR) { - continue; - } - FATAL_SYSCALL_ON(event_count == -1); - break; - } while (1); - - /* Timeouts should not occur */ - FATAL_ON(event_count == 0); - } - - /* Process each ready file descriptor */ - { - size_t event_i; - for (event_i = 0; event_i != (size_t)event_count; event_i++) { - int current_event_fd = events[event_i].data.fd; - - if (current_event_fd == fd_uart) { - driver_uart_process_uart(); - } else if (current_event_fd == fd_stop_drv) { - exit_thread = true; - } + // Wait for action + do { + event_count = epoll_wait(fd_epoll, events, 2, -1); + if (event_count == -1 && errno == EINTR) { + continue; + } + FATAL_SYSCALL_ON(event_count == -1); + break; + } while (1); + + // Timeouts should not occur + FATAL_ON(event_count == 0); + + // Process each ready file descriptor + size_t event_i; + for (event_i = 0; event_i != (size_t)event_count; event_i++) { + int current_event_fd = events[event_i].data.fd; + + if (current_event_fd == fd_uart) { + driver_uart_process_uart(); + } else if (current_event_fd == fd_stop_drv) { + exit_thread = true; } } } @@ -355,17 +350,17 @@ static void* transmit_driver_thread_func(void* param) TRACE_DRIVER("Transmitter thread start"); - /* Create the epoll set */ + // Create the epoll set fd_epoll = epoll_create1(EPOLL_CLOEXEC); FATAL_SYSCALL_ON(fd_epoll < 0); - /* Setup poll event for reading core socket */ + // Setup poll event for reading core socket events[0].events = EPOLLIN; events[0].data.fd = fd_core; ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_core, &events[0]); FATAL_SYSCALL_ON(ret < 0); - /* Setup poll event for stop event */ + // Setup poll event for stop event events[1].events = EPOLLIN; events[1].data.fd = fd_stop_drv; ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_stop_drv, &events[1]); @@ -374,32 +369,28 @@ static void* transmit_driver_thread_func(void* param) while (!exit_thread) { int event_count; - /* Wait for action */ - { - do { - event_count = epoll_wait(fd_epoll, events, 2, -1); - if (event_count == -1 && errno == EINTR) { - continue; - } - FATAL_SYSCALL_ON(event_count == -1); - break; - } while (1); - - /* Timeouts should not occur */ - FATAL_ON(event_count == 0); - } - - /* Process each ready file descriptor */ - { - size_t event_i; - for (event_i = 0; event_i != (size_t)event_count; event_i++) { - int current_event_fd = events[event_i].data.fd; - - if (current_event_fd == fd_core) { - driver_uart_process_core(); - } else if (current_event_fd == fd_stop_drv) { - exit_thread = true; - } + // Wait for action + do { + event_count = epoll_wait(fd_epoll, events, 2, -1); + if (event_count == -1 && errno == EINTR) { + continue; + } + FATAL_SYSCALL_ON(event_count == -1); + break; + } while (1); + + // Timeouts should not occur + FATAL_ON(event_count == 0); + + // Process each ready file descriptor + size_t event_i; + for (event_i = 0; event_i != (size_t)event_count; event_i++) { + int current_event_fd = events[event_i].data.fd; + + if (current_event_fd == fd_core) { + driver_uart_process_core(); + } else if (current_event_fd == fd_stop_drv) { + exit_thread = true; } } } @@ -447,7 +438,7 @@ int driver_uart_open(const char *device, unsigned int baudrate, bool hardflow) cfsetispeed(&tty, (speed_t)sym_baudrate); cfsetospeed(&tty, (speed_t)sym_baudrate); cfmakeraw(&tty); - /* Nonblocking read. */ + // Nonblocking read tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 1; tty.c_iflag &= (unsigned) ~(IXON); @@ -463,10 +454,10 @@ int driver_uart_open(const char *device, unsigned int baudrate, bool hardflow) FATAL_SYSCALL_ON(tcsetattr(fd, TCSANOW, &tty) < 0); - /* Flush the content of the UART in case there was stale data */ + // Flush the content of the UART in case there was stale data { - /* There was once a bug in the kernel requiring a delay before flushing the uart. - * Keep it there for backward compatibility */ + // There was once a bug in the kernel requiring a delay before flushing the uart. + // Keep it there for backward compatibility sleep_ms(10); tcflush(fd, TCIOFLUSH); @@ -515,7 +506,7 @@ static void driver_uart_process_uart(void) static size_t buffer_head = 0; static enum {EXPECTING_HEADER, EXPECTING_PAYLOAD} state = EXPECTING_HEADER; - /* Put the read data at the tip of the buffer head and increment it. */ + // Put the read data at the tip of the buffer head and increment it. buffer_head += read_and_append_uart_received_data(buffer, buffer_head, sizeof(buffer)); while (1) { @@ -526,18 +517,18 @@ static void driver_uart_process_uart(void) // We are synchronized on a valid header, start delimiting the data that follows into a frame. state = EXPECTING_PAYLOAD; } else { - /* We went through all the data contained in 'buffer' and haven't synchronized on a header. - * Go back to waiting for more data. */ + // We went through all the data contained in 'buffer' and haven't synchronized on a header. + // Go back to waiting for more data. return; } break; case EXPECTING_PAYLOAD: if (delimit_and_push_frames_to_core(buffer, &buffer_head)) { - /* A frame has been delimited and pushed to the core, go back to synchronizing on the next header */ + // A frame has been delimited and pushed to the core, go back to synchronizing on the next header state = EXPECTING_HEADER; } else { - /* Not yet enough data, go back to waiting. */ + // Not yet enough data, go back to waiting. return; } break; @@ -550,21 +541,21 @@ static void driver_uart_process_uart(void) } } -/* Append UART new data to the frame delimiter processing buffer */ +// Append UART new data to the frame delimiter processing buffer static size_t read_and_append_uart_received_data(uint8_t *buffer, size_t buffer_head, size_t buffer_size) { uint8_t temp_buffer[UART_BUFFER_SIZE]; BUG_ON(buffer_head >= buffer_size); - /* Make sure we don't read more data than the supplied buffer can handle */ + // Make sure we don't read more data than the supplied buffer can handle const size_t available_space = buffer_size - buffer_head - 1; - /* Read the uart data into the temp buffer */ + // Read the uart data into the temp buffer ssize_t read_retval = read(fd_uart, temp_buffer, available_space); FATAL_ON(read_retval < 0); - /* copy the data in the main buffer */ + // copy the data in the main buffer memcpy(&buffer[buffer_head], temp_buffer, (size_t)read_retval); return (size_t)read_retval; @@ -573,6 +564,7 @@ static size_t read_and_append_uart_received_data(uint8_t *buffer, size_t buffer_ static bool validate_header(uint8_t *header_start) { uint16_t hcs; + uint16_t payload_size; if (header_start[SLI_CPC_HDLC_FLAG_POS] != SLI_CPC_HDLC_FLAG_VAL) { return false; @@ -585,6 +577,14 @@ static bool validate_header(uint8_t *header_start) return false; } + payload_size = hdlc_get_length(header_start); + if (payload_size > UART_BUFFER_SIZE) { + // Received valid header with oversized payload. Invalidate the frame to avoid + // overflowing the reception buffers. + TRACE_DRIVER("RX buffer size from bus is invalid: %d", payload_size); + return false; + } + return true; } @@ -595,8 +595,8 @@ static bool header_synch(uint8_t *buffer, size_t *buffer_head) return false; } - /* If we think of a header like a sliding window of width SLI_CPC_HDLC_HEADER_RAW_SIZE, - * then we can slide it 'num_header_combination' times over the data. */ + // If we think of a header like a sliding window of width SLI_CPC_HDLC_HEADER_RAW_SIZE, + // then we can slide it 'num_header_combination' times over the data. const size_t num_header_combination = *buffer_head - SLI_CPC_HDLC_HEADER_RAW_SIZE + 1; size_t i; @@ -606,26 +606,23 @@ static bool header_synch(uint8_t *buffer, size_t *buffer_head) if (i == 0) { // The start of the buffer is aligned with a good header, don't do anything } else { - /* We had 'i' number of bad bytes until we struck a good header, move back the data - * to the beginning of the buffer */ + // We had 'i' number of bad bytes until we struck a good header, move back the data + // to the beginning of the buffer memmove(&buffer[0], &buffer[i], *buffer_head - i); - /* We crushed 'i' bytes at the start of the buffer */ + // We crushed 'i' bytes at the start of the buffer *buffer_head -= i; } return true; } else { - /* The header is not valid, continue until it is */ + // The header is not valid, continue until it is } } - /* If we land here, no header at all was found. Keep the last 'SLI_CPC_HDLC_HEADER_RAW_SIZE - 1' bytes and - * bring them back at the start of the buffer so that the next appended byte could complete that potential header */ - { - memmove(&buffer[0], &buffer[num_header_combination], SLI_CPC_HDLC_HEADER_RAW_SIZE - 1); - - *buffer_head = SLI_CPC_HDLC_HEADER_RAW_SIZE - 1; - } + // If we land here, no header at all was found. Keep the last 'SLI_CPC_HDLC_HEADER_RAW_SIZE - 1' bytes and + // bring them back at the start of the buffer so that the next appended byte could complete that potential header + memmove(&buffer[0], &buffer[num_header_combination], SLI_CPC_HDLC_HEADER_RAW_SIZE - 1); + *buffer_head = SLI_CPC_HDLC_HEADER_RAW_SIZE - 1; return false; } @@ -638,10 +635,10 @@ static bool header_synch(uint8_t *buffer, size_t *buffer_head) */ static bool delimit_and_push_frames_to_core(uint8_t *buffer, size_t *buffer_head) { - uint16_t payload_len; /* The length of the payload, as retrieved from the header (including the checksum) */ - size_t frame_size; /* The whole size of the frame */ + uint16_t payload_len; // The length of the payload, as retrieved from the header (including the checksum) + size_t frame_size; // The whole size of the frame - /* if not enough bytes even for a header */ + // if not enough bytes even for a header if (*buffer_head < SLI_CPC_HDLC_HEADER_RAW_SIZE) { return false; } @@ -650,33 +647,33 @@ static bool delimit_and_push_frames_to_core(uint8_t *buffer, size_t *buffer_head frame_size = payload_len + SLI_CPC_HDLC_HEADER_RAW_SIZE; - /* Check if we have enough data for a full frame*/ + // Check if we have enough data for a full frame if (frame_size > *buffer_head) { return false; } - /* Push to core */ + // Push to core { TRACE_FRAME("Driver : Frame delimiter : push delimited frame to core : ", buffer, frame_size); ssize_t write_retval = write(fd_core, buffer, frame_size); FATAL_SYSCALL_ON(write_retval < 0); - /* Error if write is not complete */ + // Error if write is not complete FATAL_ON((size_t)write_retval != frame_size); } - /* Move the remaining data back to the start of the buffer. */ + // Move the remaining data back to the start of the buffer. { const size_t remaining_bytes = *buffer_head - frame_size; memmove(buffer, &buffer[frame_size], remaining_bytes); - /* Adjust the buffer_head now that we have modified the buffer's content */ + // Adjust the buffer_head now that we have modified the buffer's content *buffer_head = remaining_bytes; } - /* A complete frame has been delimited. A second round of parsing can be done. */ + // A complete frame has been delimited. A second round of parsing can be done. return true; } @@ -709,7 +706,7 @@ static void driver_uart_process_core(void) FATAL_SYSCALL_ON(write_retval < 0); - /* Error if write is not complete */ + // Error if write is not complete FATAL_ON((size_t)write_retval != (size_t)read_retval); } @@ -726,7 +723,7 @@ static void driver_uart_process_core(void) tx_complete_timestamp.tv_nsec += driver_get_time_to_drain_ns((uint32_t)length); tx_complete_timestamp.tv_nsec %= 1000000000; - /* Push write notification to core */ + // Push write notification to core ssize_t write_retval = write(fd_core_notify, &tx_complete_timestamp, sizeof(tx_complete_timestamp)); FATAL_SYSCALL_ON(write_retval != sizeof(tx_complete_timestamp)); } diff --git a/driver/driver_uart.h b/driver/driver_uart.h index 6ead78d..c19bf41 100644 --- a/driver/driver_uart.h +++ b/driver/driver_uart.h @@ -18,7 +18,6 @@ #ifndef DRIVER_UART_H #define DRIVER_UART_H -#define _GNU_SOURCE #include #include @@ -39,4 +38,4 @@ void driver_uart_assert_rts(bool assert); void driver_uart_print_overruns(void); -#endif //DRIVER_UART_H +#endif // DRIVER_UART_H diff --git a/driver/driver_xmodem.c b/driver/driver_xmodem.c index bbafbb3..ca8ff64 100644 --- a/driver/driver_xmodem.c +++ b/driver/driver_xmodem.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -38,8 +40,8 @@ #define MAX_RETRANSMIT_ATTEMPTS (5) -// data from the bootloader comes in chunks -static bool wait_for_bootloader_string(int fd, char *string) +// Data from the bootloader comes in chunks +static bool wait_for_bootloader_string(int fd, const char *string) { char btl_buffer[128] = { 0 }; char *btl_chunk = btl_buffer; @@ -47,7 +49,7 @@ static bool wait_for_bootloader_string(int fd, char *string) ssize_t ret; unsigned int retries = 10; - // receive data until the string is found + // Receive data until the string is found do { sleep_s(1); @@ -79,14 +81,14 @@ sl_status_t xmodem_uart_firmware_upgrade(const char* image_file, const char *dev int image_file_fd; uint8_t* mmapped_image_file_data; size_t mmapped_image_file_len; - ssize_t ret; + ssize_t sret; + int ret; uint8_t answer; unsigned int retransmit_count = 0; - /* Open the uart and memory map the firmware update file */ + // Open the uart and memory map the firmware update file { struct stat stat; - int ret; uart_fd = driver_uart_open(dev_name, bitrate, hardflow); @@ -107,28 +109,24 @@ sl_status_t xmodem_uart_firmware_upgrade(const char* image_file, const char *dev FATAL_SYSCALL_ON(mmapped_image_file_data == NULL); } - /* Wait for the "C" character meaning the secondary is ready for XMODEM-CRC transfer */ + // Wait for the "C" character meaning the secondary is ready for XMODEM-CRC transfer { // wait_for_bootloader_string implements a timeout, so fd must be non-blocking ret = fcntl(uart_fd, F_SETFL, O_NONBLOCK); FATAL_SYSCALL_ON(ret < 0); - { - TRACE_XMODEM("Connecting to bootloader..."); - if (!wait_for_bootloader_string(uart_fd, BTL_MENU_PROMPT)) { - TRACE_XMODEM("Failed to connect to bootloader."); - return SL_STATUS_FAIL; - } + TRACE_XMODEM("Connecting to bootloader..."); + if (!wait_for_bootloader_string(uart_fd, BTL_MENU_PROMPT)) { + TRACE_XMODEM("Failed to connect to bootloader."); + return SL_STATUS_FAIL; } - /* The bootloader sends a menu with options. We have to send '1' in order to start a gbl file transfer */ - { - const uint8_t upload_gbl = '1'; - TRACE_XMODEM("Received bootloader menu, send \"1\" to start gbl file transfer."); + // The bootloader sends a menu with options. We have to send '1' in order to start a gbl file transfer + const uint8_t upload_gbl = '1'; + TRACE_XMODEM("Received bootloader menu, send \"1\" to start gbl file transfer."); - ret = write(uart_fd, (const void *)&upload_gbl, sizeof(upload_gbl)); - FATAL_SYSCALL_ON(ret != sizeof(upload_gbl)); - } + sret = write(uart_fd, (const void *)&upload_gbl, sizeof(upload_gbl)); + FATAL_SYSCALL_ON(sret != sizeof(upload_gbl)); TRACE_XMODEM("Waiting for receiver ping ..."); @@ -140,21 +138,21 @@ sl_status_t xmodem_uart_firmware_upgrade(const char* image_file, const char *dev ret = fcntl(uart_fd, F_SETFL, flags); FATAL_SYSCALL_ON(ret < 0); do { - ret = read(uart_fd, &answer, sizeof(answer)); - FATAL_SYSCALL_ON(ret != sizeof(answer)); + sret = read(uart_fd, &answer, sizeof(answer)); + FATAL_SYSCALL_ON(sret != sizeof(answer)); } while (answer != XMODEM_CMD_C); TRACE_XMODEM("Received \"C\" ping. Transfer begins : "); } - /* Actual file transfer */ + // Actual file transfer { XmodemFrame_t frame; uint8_t* image_file_data = mmapped_image_file_data; size_t image_file_len = mmapped_image_file_len; frame.header = XMODEM_CMD_SOH; - frame.seq = 1; //Sequence number starts at one initially, wraps around to 0 afterward + frame.seq = 1; // Sequence number starts at one initially, wraps around to 0 afterward while (image_file_len) { size_t z = 0; @@ -164,17 +162,17 @@ sl_status_t xmodem_uart_firmware_upgrade(const char* image_file, const char *dev z = min(image_file_len, sizeof(frame.data)); memcpy(frame.data, image_file_data, z); - memset(frame.data + z, 0xff, sizeof(frame.data) - z); //Pad last frame with 0xFF + memset(frame.data + z, 0xff, sizeof(frame.data) - z); // Pad last frame with 0xFF u16_to_be(sli_cpc_get_crc_sw(frame.data, sizeof(frame.data)), (uint8_t *)&frame.crc); frame.seq_neg = (uint8_t)(0xff - frame.seq); - ret = write(uart_fd, &frame, sizeof(frame)); - FATAL_SYSCALL_ON(ret != sizeof(frame)); + sret = write(uart_fd, &frame, sizeof(frame)); + FATAL_SYSCALL_ON(sret != sizeof(frame)); - ret = read(uart_fd, &answer, sizeof(answer)); - FATAL_SYSCALL_ON(ret != sizeof(answer)); + sret = read(uart_fd, &answer, sizeof(answer)); + FATAL_SYSCALL_ON(sret != sizeof(answer)); switch (answer) { case XMODEM_CMD_NAK: @@ -208,56 +206,46 @@ sl_status_t xmodem_uart_firmware_upgrade(const char* image_file, const char *dev return SL_STATUS_FAIL; } } - TRACE_XMODEM("Finished sending image file. Sent a total of %d Bytes.", (size_t)(image_file_data - mmapped_image_file_data)); + TRACE_XMODEM("Finished sending image file. Sent a total of %zd Bytes.", (size_t)(image_file_data - mmapped_image_file_data)); TRACE_XMODEM("Transfer of file \"%s\" completed with %u retransmits.", image_file, retransmit_count); } trace_no_timestamp("\n"); - /* Complete the transfer by sending EOF symbol */ - { - const uint8_t eof = XMODEM_CMD_EOT; - TRACE_XMODEM("Sending EOT symbol to complete image file transfer."); - ret = write(uart_fd, &eof, sizeof(eof)); - FATAL_SYSCALL_ON(ret != sizeof(eof)); - } + // Complete the transfer by sending EOF symbol + const uint8_t eof = XMODEM_CMD_EOT; + TRACE_XMODEM("Sending EOT symbol to complete image file transfer."); + sret = write(uart_fd, &eof, sizeof(eof)); + FATAL_SYSCALL_ON(sret != sizeof(eof)); - { - if (!wait_for_bootloader_string(uart_fd, BTL_UPLOAD_CONFIRMATION)) { - TRACE_XMODEM("Failed to receive upload confirmation from bootloader."); - return SL_STATUS_FAIL; - } - TRACE_XMODEM("Received upload confirmation from bootloader. Device restarting, waiting for bootloader menu..."); + if (!wait_for_bootloader_string(uart_fd, BTL_UPLOAD_CONFIRMATION)) { + TRACE_XMODEM("Failed to receive upload confirmation from bootloader."); + return SL_STATUS_FAIL; } + TRACE_XMODEM("Received upload confirmation from bootloader. Device restarting, waiting for bootloader menu..."); - { - if (!wait_for_bootloader_string(uart_fd, BTL_MENU_PROMPT)) { - TRACE_XMODEM("Failed to restart device after upgrade."); - return SL_STATUS_FAIL; - } - TRACE_XMODEM("Device restarted successfully."); + if (!wait_for_bootloader_string(uart_fd, BTL_MENU_PROMPT)) { + TRACE_XMODEM("Failed to restart device after upgrade."); + return SL_STATUS_FAIL; } + TRACE_XMODEM("Device restarted successfully."); - /* Send '2' in order to run the new image */ - { - const uint8_t run_gbl = '2'; - TRACE_XMODEM("Received bootloader menu, send \"2\" to run the new image file."); - ret = write(uart_fd, (const void *)&run_gbl, sizeof(run_gbl)); - FATAL_SYSCALL_ON(ret != sizeof(run_gbl)); - } + // Send '2' in order to run the new image + const uint8_t run_gbl = '2'; + TRACE_XMODEM("Received bootloader menu, send \"2\" to run the new image file."); + sret = write(uart_fd, (const void *)&run_gbl, sizeof(run_gbl)); + FATAL_SYSCALL_ON(sret != sizeof(run_gbl)); - /* Cleanup */ - { - TRACE_XMODEM("Cleaning up..."); - ret = munmap(mmapped_image_file_data, mmapped_image_file_len); - FATAL_SYSCALL_ON(ret != 0); + // Cleanup + TRACE_XMODEM("Cleaning up..."); + ret = munmap(mmapped_image_file_data, mmapped_image_file_len); + FATAL_SYSCALL_ON(ret != 0); - ret = close(image_file_fd); - FATAL_SYSCALL_ON(ret != 0); + ret = close(image_file_fd); + FATAL_SYSCALL_ON(ret != 0); - ret = close(uart_fd); - FATAL_SYSCALL_ON(ret != 0); - } + ret = close(uart_fd); + FATAL_SYSCALL_ON(ret != 0); return SL_STATUS_OK; } diff --git a/include/cpcd/board_controller.h b/include/cpcd/board_controller.h index 760f734..742b95a 100644 --- a/include/cpcd/board_controller.h +++ b/include/cpcd/board_controller.h @@ -22,4 +22,4 @@ void board_controller_get_config_vcom(const char *ip_address, unsigned int *baudrate, bool *flowcontrol); -#endif //BOARD_CONTROLLER_H +#endif // BOARD_CONTROLLER_H diff --git a/include/cpcd/config.h b/include/cpcd/config.h index 4917484..3b4a1e1 100644 --- a/include/cpcd/config.h +++ b/include/cpcd/config.h @@ -15,8 +15,8 @@ * ******************************************************************************/ -#ifndef CONFIG_H -#define CONFIG_H +#ifndef CPCD_CONFIG_H +#define CPCD_CONFIG_H #include #include @@ -48,7 +48,7 @@ typedef struct __attribute__((packed)) { bool use_encryption; - char *binding_key_file; + const char *binding_key_file; bool binding_key_override; @@ -94,9 +94,9 @@ typedef struct __attribute__((packed)) { const char *uart_validation_test_option; - long stats_interval; + int stats_interval; - rlim_t rlimit_nofile; + int rlimit_nofile; } config_t; extern config_t config; @@ -107,4 +107,4 @@ void config_restart_cpcd(char **argv); void config_restart_cpcd_without_fw_update_args(void); void config_restart_cpcd_without_bind_arg(void); -#endif //CONFIG_H +#endif // CPCD_CONFIG_H diff --git a/include/cpcd/core.h b/include/cpcd/core.h index 33a254c..132cbdc 100644 --- a/include/cpcd/core.h +++ b/include/cpcd/core.h @@ -114,9 +114,7 @@ void core_remote_ep_is_opened(uint8_t ep_id, on_is_open_query_completion_t server_callback, void *server_ctx); -/* - * Internal state for the endpoints. Will be filled by cpc_register_endpoint() - */ +// Internal state for the endpoints. Will be filled by cpc_register_endpoint() typedef struct endpoint { uint8_t id; uint8_t flags; @@ -136,6 +134,7 @@ typedef struct endpoint { struct timespec last_iframe_sent_timestamp; uint32_t smoothed_rtt; uint32_t rtt_variation; + bool closed_by_server; #if defined(ENABLE_ENCRYPTION) bool encrypted; uint32_t frame_counter_tx; diff --git a/include/cpcd/event.h b/include/cpcd/event.h index 68370a9..f485278 100644 --- a/include/cpcd/event.h +++ b/include/cpcd/event.h @@ -19,7 +19,7 @@ #ifndef CPCD_EVENT_H #define CPCD_EVENT_H -#include "lib/sl_cpc.h" +#include "sl_cpc.h" typedef struct { cpc_event_type_t type; @@ -28,4 +28,4 @@ typedef struct { uint8_t payload[]; } cpcd_event_buffer_t; -#endif //CPCD_EVENT_H +#endif // CPCD_EVENT_H diff --git a/include/cpcd/exchange.h b/include/cpcd/exchange.h index 9324cb2..caa6042 100644 --- a/include/cpcd/exchange.h +++ b/include/cpcd/exchange.h @@ -18,10 +18,10 @@ #ifndef CPCD_EXCHANGE_H #define CPCD_EXCHANGE_H -#include "lib/sl_cpc.h" +#include "sl_cpc.h" -/* NOTE: New exchange types must be added to the end of the enum to prevent - * an incompatibility between older library versions */ +// NOTE: New exchange types must be added to the end of the enum to prevent +// an incompatibility between older library versions SL_ENUM_GENERIC(cpcd_exchange_type_t, uint8_t) { EXCHANGE_ENDPOINT_STATUS_QUERY, @@ -43,4 +43,4 @@ typedef struct { uint8_t payload[]; } cpcd_exchange_buffer_t; -#endif //CPCD_EXCHANGE_H +#endif // CPCD_EXCHANGE_H diff --git a/include/cpcd/exit.h b/include/cpcd/exit.h index df2d11d..126305d 100644 --- a/include/cpcd/exit.h +++ b/include/cpcd/exit.h @@ -18,6 +18,8 @@ #ifndef EXIT_H #define EXIT_H +#include + /***************************************************************************//** * Initializes daemon exit mechanisms. ******************************************************************************/ diff --git a/include/cpcd/gpio.h b/include/cpcd/gpio.h index 5a817fa..8781101 100644 --- a/include/cpcd/gpio.h +++ b/include/cpcd/gpio.h @@ -63,9 +63,7 @@ gpio_value_t gpio_read(gpio_t gpio); int gpio_get_epoll_fd(gpio_t gpio); -/* - * Clears a single gpio IRQ event. - */ +// Clears a single gpio IRQ event. void gpio_clear_irq(gpio_t gpio); -#endif /* GPIO_H */ +#endif // GPIO_H diff --git a/include/cpcd/logging.h b/include/cpcd/logging.h index 852288e..527ebdb 100644 --- a/include/cpcd/logging.h +++ b/include/cpcd/logging.h @@ -24,6 +24,8 @@ #include #include +#include + /// Struct representing CPC Core debug counters. typedef struct { uint32_t endpoint_opened; @@ -45,15 +47,15 @@ typedef struct { void logging_init(void); -void init_file_logging(); +void init_file_logging(void); void init_stats_logging(void); void logging_kill(void); -void trace(const bool force_stdout, const char* string, ...); +void trace(const bool force_stdout, const char* string, ...) __attribute__((format(printf, 2, 3))); -void trace_no_timestamp(const char* string, ...); +void trace_no_timestamp(const char* string, ...) __attribute__((format(printf, 1, 2))); void trace_frame(const char* string, const void* buffer, size_t len); @@ -210,8 +212,6 @@ extern core_debug_counters_t secondary_core_debug_counters; #define OUT_FILE stderr -__attribute__((noreturn)) void signal_crash(void); - #define CRASH() do { signal_crash(); } while (0) #define WARN(msg, ...) \ @@ -253,7 +253,7 @@ __attribute__((noreturn)) void signal_crash(void); } \ } while (0) -/* Special version used specifically when the trace file hasn't been opened yet (error while creating it) */ +// Special version used specifically when the trace file hasn't been opened yet (error while creating it) #define FATAL_SYSCALL_NO_TRACE_FILE_ON(cond) \ do { \ if (cond) { \ @@ -277,4 +277,4 @@ __attribute__((noreturn)) void signal_crash(void); CRASH(); \ } \ } while (0) -#endif //TRACING_H +#endif // TRACING_H diff --git a/include/cpcd/server_core.h b/include/cpcd/server_core.h index dceca50..851a6f2 100644 --- a/include/cpcd/server_core.h +++ b/include/cpcd/server_core.h @@ -18,7 +18,6 @@ #ifndef SERVER_CORE_H #define SERVER_CORE_H -#define _GNU_SOURCE #include #include @@ -48,4 +47,4 @@ bool server_core_reset_is_received_reset_reason(void); char* server_core_get_secondary_app_version(void); -#endif //SERVER_CORE_H +#endif // SERVER_CORE_H diff --git a/include/cpcd/sl_slist.h b/include/cpcd/sl_slist.h index 70db04f..3827c70 100644 --- a/include/cpcd/sl_slist.h +++ b/include/cpcd/sl_slist.h @@ -118,8 +118,6 @@ void sl_slist_insert(sl_slist_node_t *item, * @param head Pointer to pointer of the head element of list. * * @param item Pointer to the item to remove. - * - * @note (1) An EFM_ASSERT is thrown if the item is not found within the list. ******************************************************************************/ void sl_slist_remove(sl_slist_node_t **head, sl_slist_node_t *item); @@ -138,6 +136,16 @@ void sl_slist_sort(sl_slist_node_t **head, bool (*cmp_fnct)(sl_slist_node_t *item_l, sl_slist_node_t *item_r)); +/******************************************************************************* + * Checks if the list is empty. + * + * @param head Pointer to the head element of the list. + ******************************************************************************/ +static inline bool sl_slist_is_empty(sl_slist_node_t *head) +{ + return head == NULL; +} + /** @} (end addtogroup slist) */ #ifdef __cplusplus diff --git a/include/cpcd/sleep.h b/include/cpcd/sleep.h index eaa1ef9..45b4833 100644 --- a/include/cpcd/sleep.h +++ b/include/cpcd/sleep.h @@ -20,7 +20,7 @@ #include -/** Helpers around the nanosleep POSIX system call */ +// Helpers around the nanosleep POSIX system call int sleep_us(uint32_t us); @@ -31,4 +31,4 @@ static inline int sleep_ms(uint32_t ms) int sleep_s(uint32_t s); -#endif /* SLEEP_H */ +#endif // SLEEP_H diff --git a/include/cpcd/xmodem.h b/include/cpcd/xmodem.h index 3d12284..6d30ceb 100644 --- a/include/cpcd/xmodem.h +++ b/include/cpcd/xmodem.h @@ -46,4 +46,4 @@ typedef struct { uint16_t crc; ///< CRC } __attribute__((packed)) XmodemFrame_t; -#endif /* XMODEM_H */ +#endif // XMODEM_H diff --git a/lib/bindings/rust/README.txt b/lib/bindings/rust/README.txt index e655e23..e3c6f60 100644 --- a/lib/bindings/rust/README.txt +++ b/lib/bindings/rust/README.txt @@ -5,3 +5,4 @@ cargo +nightly generate-lockfile -Z minimal-versions cargo update regex --precise 1.5.6 cargo update shlex --precise 1.3.0 cargo update log --precise 0.4.20 +cargo --locked audit diff --git a/lib/sl_cpc.c b/lib/sl_cpc.c index 843fd30..abe638b 100644 --- a/lib/sl_cpc.c +++ b/lib/sl_cpc.c @@ -15,6 +15,10 @@ * ******************************************************************************/ +#include "config.h" + +#include "sl_cpc.h" + #include #include #include @@ -41,9 +45,6 @@ #include "cpcd/sl_slist.h" #include "cpcd/utils.h" -#include "sl_cpc.h" -#include "version.h" - #ifdef COMPILE_LTTNG #include #define LTTNG_TRACE(string, ...) tracef(string, ##__VA_ARGS__) @@ -117,14 +118,14 @@ static size_t get_time_string(char *slice, size_t slice_len) return 0; } - /* XXXX-XX-XXTXX:XX:XX + .XXXXXX + Z */ + // XXXX-XX-XXTXX:XX:XX + .XXXXXX + Z strftime(slice, 19 + 1, "%FT%T", &tm); snprintf(slice + 19, 7 + 1, ".%06lu", (long)now.tv_nsec / 1000); slice[26] = 'Z'; return TIME_STR_LEN; } -static void lib_trace(FILE *__restrict __stream, const char* string, ...) +__attribute__((format(printf, 2, 3))) static void lib_trace(FILE *__restrict __stream, const char* string, ...) { va_list vl; va_start(vl, string); @@ -206,7 +207,7 @@ static int cpc_query_exchange(sli_cpc_handle_t *lib_handle, int fd, cpcd_exchang query = zalloc(query_len); if (query == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", query_len); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", query_len); SET_CPC_RET(-ENOMEM); RETURN_CPC_RET; } @@ -223,7 +224,7 @@ static int cpc_query_exchange(sli_cpc_handle_t *lib_handle, int fd, cpcd_exchang TRACE_LIB_ERRNO(lib_handle, "send(%d) failed", fd); SET_CPC_RET(-errno); } else { - TRACE_LIB_ERROR(lib_handle, -EBADE, "send(%d) failed, ret = %d", fd, bytes_written); + TRACE_LIB_ERROR(lib_handle, -EBADE, "send(%d) failed, ret = %zd", fd, bytes_written); SET_CPC_RET(-EBADE); } goto free_query; @@ -238,7 +239,7 @@ static int cpc_query_exchange(sli_cpc_handle_t *lib_handle, int fd, cpcd_exchang TRACE_LIB_ERRNO(lib_handle, "recv(%d) failed", fd); SET_CPC_RET(-errno); } else { - TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %d", fd, bytes_read); + TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %zd", fd, bytes_read); SET_CPC_RET(-EBADE); } goto free_query; @@ -263,7 +264,7 @@ static int cpc_query_receive(sli_cpc_handle_t *lib_handle, int fd, void *payload query = zalloc(query_len); if (query == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", query_len); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", query_len); SET_CPC_RET(-ENOMEM); RETURN_CPC_RET; } @@ -277,7 +278,7 @@ static int cpc_query_receive(sli_cpc_handle_t *lib_handle, int fd, void *payload TRACE_LIB_ERRNO(lib_handle, "recv(%d) failed", fd); SET_CPC_RET(-errno); } else { - TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %d", fd, bytes_read); + TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %zd", fd, bytes_read); SET_CPC_RET(-EBADE); } @@ -383,7 +384,7 @@ static int get_secondary_app_version(sli_cpc_handle_t *lib_handle) lib_handle->secondary_app_version = zalloc((size_t)app_string_size + 1); if (lib_handle->secondary_app_version == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", (size_t)app_string_size + 1); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", (size_t)app_string_size + 1); SET_CPC_RET(-ENOMEM); RETURN_CPC_RET; } @@ -599,7 +600,7 @@ static int sli_cpc_deinit(bool atomic, cpc_handle_t *handle) tmp_ret = pthread_join(lib_handle->reset_thread, NULL); if (tmp_ret) { - TRACE_LIB_ERROR(lib_handle, -tmp_ret, "pthread_join() failed", lib_handle->reset_sock_fd); + TRACE_LIB_ERROR(lib_handle, -tmp_ret, "pthread_join() failed"); } } @@ -655,19 +656,19 @@ int cpc_init(cpc_handle_t *handle, const char *instance_name, bool enable_tracin lib_handle->pid = getpid(); - /* Save the parameters internally for possible further re-init */ + // Save the parameters internally for possible further re-init lib_handle->enable_tracing = enable_tracing; lib_handle->reset_callback = reset_callback; if (instance_name == NULL) { - /* If the instance name is NULL, use the default name */ + // If the instance name is NULL, use the default name lib_handle->instance_name = strdup(DEFAULT_INSTANCE_NAME); if (lib_handle->instance_name == NULL) { SET_CPC_RET(-errno); goto free_lib_handle; } } else { - /* Instead, use the one supplied by the user */ + // Instead, use the one supplied by the user lib_handle->instance_name = strdup(instance_name); if (lib_handle->instance_name == NULL) { SET_CPC_RET(-errno); @@ -675,7 +676,7 @@ int cpc_init(cpc_handle_t *handle, const char *instance_name, bool enable_tracin } } - /* Create the control socket path */ + // Create the control socket path { int nchars; const size_t size = sizeof(server_addr.sun_path) - 1; @@ -684,7 +685,7 @@ int cpc_init(cpc_handle_t *handle, const char *instance_name, bool enable_tracin nchars = snprintf(server_addr.sun_path, size, "%s/cpcd/%s/ctrl.cpcd.sock", CPC_SOCKET_DIR, lib_handle->instance_name); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer if (nchars < 0 || (size_t) nchars >= size) { TRACE_LIB_ERROR(lib_handle, -ERANGE, "socket path '%s/cpcd/%s/ctrl.cpcd.sock' does not fit in buffer", CPC_SOCKET_DIR, lib_handle->instance_name); SET_CPC_RET(-ERANGE); @@ -771,13 +772,13 @@ int cpc_init(cpc_handle_t *handle, const char *instance_name, bool enable_tracin lib_handle_item = zalloc(sizeof(sli_handle_list_item_t)); if (lib_handle_item == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_handle_list_item_t)); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_handle_list_item_t)); SET_CPC_RET(-ENOMEM); goto destroy_mutex; } if (lib_handle->reset_callback) { - /* Create the reset socket path */ + // Create the reset socket path { int nchars; const size_t size = sizeof(server_addr.sun_path) - 1; @@ -786,7 +787,7 @@ int cpc_init(cpc_handle_t *handle, const char *instance_name, bool enable_tracin nchars = snprintf(server_addr.sun_path, size, "%s/cpcd/%s/reset.cpcd.sock", CPC_SOCKET_DIR, lib_handle->instance_name); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer if (nchars < 0 || (size_t) nchars >= size) { TRACE_LIB_ERROR(lib_handle, -ERANGE, "socket path '%s/cpcd/%s/reset.cpcd.sock' does not fit in buffer", CPC_SOCKET_DIR, lib_handle->instance_name); SET_CPC_RET(-ERANGE); @@ -920,7 +921,7 @@ int cpc_restart(cpc_handle_t *handle) sli_cpc_handle_t *lib_handle_copy = zalloc(sizeof(sli_cpc_handle_t)); if (lib_handle_copy == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_cpc_handle_t)); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_cpc_handle_t)); SET_CPC_RET(-ENOMEM); unlock_cpc_api(&cpc_api_lock); @@ -941,7 +942,7 @@ int cpc_restart(cpc_handle_t *handle) lib_handle_item_copy = zalloc(sizeof(sli_handle_list_item_t)); if (lib_handle_item_copy == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_handle_list_item_t)); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_handle_list_item_t)); SET_CPC_RET(-ENOMEM); free(lib_handle_copy->instance_name); @@ -1108,14 +1109,14 @@ int cpc_open_endpoint(cpc_handle_t handle, cpc_endpoint_t *endpoint, uint8_t id, ep_addr.sun_family = AF_UNIX; - /* Create the endpoint socket path */ + // Create the endpoint socket path { int nchars; const size_t size = sizeof(ep_addr.sun_path) - 1; nchars = snprintf(ep_addr.sun_path, size, "%s/cpcd/%s/ep%d.cpcd.sock", CPC_SOCKET_DIR, lib_handle->instance_name, id); - /* Make sure the path fitted entirely in the struct sockaddr_un's static buffer */ + // Make sure the path fitted entirely in the struct sockaddr_un's static buffer if (nchars < 0 || (size_t) nchars >= size) { TRACE_LIB_ERROR(lib_handle, -ERANGE, "socket path '%s/cpcd/%s/ep%d.cpcd.sock' does not fit in buffer", CPC_SOCKET_DIR, lib_handle->instance_name, id); SET_CPC_RET(-ERANGE); @@ -1125,7 +1126,7 @@ int cpc_open_endpoint(cpc_handle_t handle, cpc_endpoint_t *endpoint, uint8_t id, ep = zalloc(sizeof(sli_cpc_endpoint_t)); if (ep == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_cpc_endpoint_t)); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_cpc_endpoint_t)); SET_CPC_RET(-ERANGE); goto cleanup; } @@ -1217,7 +1218,7 @@ int cpc_open_endpoint(cpc_handle_t handle, cpc_endpoint_t *endpoint, uint8_t id, ep_handle_item = zalloc(sizeof(sli_handle_list_item_t)); if (ep_handle_item == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_handle_list_item_t)); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_handle_list_item_t)); SET_CPC_RET(-ENOMEM); goto destroy_mutex; } @@ -1309,7 +1310,7 @@ int cpc_close_endpoint(cpc_endpoint_t *endpoint) increment_ref_count(&lib_handle->ref_count); if (ep->ref_count != 0) { - TRACE_LIB_ERROR(lib_handle, -EPERM, "cannot close a handle (%p) that is in use", *endpoint); + TRACE_LIB_ERROR(lib_handle, -EPERM, "cannot close a handle (%p) that is in use", endpoint); SET_CPC_RET(-EPERM); unlock_cpc_api(&cpc_api_lock); @@ -1515,7 +1516,7 @@ ssize_t cpc_write_endpoint(cpc_endpoint_t endpoint, const void *data, size_t dat unlock_cpc_api(&cpc_api_lock); if (data_length > lib_handle->max_write_size) { - TRACE_LIB_ERROR(lib_handle, -EINVAL, "payload too large (%d > %d)", data_length, lib_handle->max_write_size); + TRACE_LIB_ERROR(lib_handle, -EINVAL, "payload too large (%zd > %zd)", data_length, lib_handle->max_write_size); SET_CPC_RET(-EINVAL); goto cleanup; @@ -1539,14 +1540,12 @@ ssize_t cpc_write_endpoint(cpc_endpoint_t endpoint, const void *data, size_t dat TRACE_LIB(lib_handle, "wrote to EP #%d", ep->id); - /* - * The socket type between the library and the daemon are of type - * SOCK_SEQPACKET. Unlike stream sockets, it is technically impossible - * for DGRAM or SEQPACKET to do partial writes. The man page is ambiguous - * about the return value in the our case, but research showed that it should - * never happens. If it did happen,it would cause problems in - * dealing with partially sent messages. - */ + // The socket type between the library and the daemon are of type + // SOCK_SEQPACKET. Unlike stream sockets, it is technically impossible + // for DGRAM or SEQPACKET to do partial writes. The man page is ambiguous + // about the return value in the our case, but research showed that it should + // never happens. If it did happen,it would cause problems in + // dealing with partially sent messages. assert((size_t)bytes_written == data_length); cleanup: @@ -2013,7 +2012,7 @@ const char* cpc_get_secondary_app_version(cpc_handle_t handle) secondary_app_version_len = strlen(lib_handle->secondary_app_version) + 1; secondary_app_version = zalloc(secondary_app_version_len); if (secondary_app_version == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", secondary_app_version_len); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", secondary_app_version_len); } else { memcpy(secondary_app_version, lib_handle->secondary_app_version, secondary_app_version_len); } @@ -2239,7 +2238,7 @@ int cpc_init_endpoint_event(cpc_handle_t handle, cpc_endpoint_event_handle_t *ev evt = zalloc(sizeof(sli_cpc_endpoint_event_handle_t)); if (evt == NULL) { - TRACE_LIB_ERROR(evt->lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_cpc_endpoint_event_handle_t)); + TRACE_LIB_ERROR(evt->lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_cpc_endpoint_event_handle_t)); SET_CPC_RET(-ENOMEM); goto cleanup; @@ -2285,7 +2284,7 @@ int cpc_init_endpoint_event(cpc_handle_t handle, cpc_endpoint_event_handle_t *ev ep_evt_handle_item = zalloc(sizeof(sli_handle_list_item_t)); if (ep_evt_handle_item == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", sizeof(sli_handle_list_item_t)); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", sizeof(sli_handle_list_item_t)); SET_CPC_RET(-ENOMEM); goto destroy_mutex; } @@ -2406,7 +2405,7 @@ int cpc_read_endpoint_event(cpc_endpoint_event_handle_t event_handle, cpc_event_ TRACE_LIB_ERRNO(lib_handle, "recv(%d) failed", evt->sock_fd); SET_CPC_RET(-errno); } else { - TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %d", evt->sock_fd, tmp_ret2); + TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %zd", evt->sock_fd, tmp_ret2); SET_CPC_RET(-EBADE); } goto unlock_mutex; @@ -2416,7 +2415,7 @@ int cpc_read_endpoint_event(cpc_endpoint_event_handle_t event_handle, cpc_event_ event = zalloc((size_t)tmp_ret2); if (event == NULL) { - TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%d) failed", tmp_ret2); + TRACE_LIB_ERROR(lib_handle, -ENOMEM, "alloc(%zd) failed", tmp_ret2); SET_CPC_RET(-ENOMEM); goto unlock_mutex; } @@ -2428,7 +2427,7 @@ int cpc_read_endpoint_event(cpc_endpoint_event_handle_t event_handle, cpc_event_ TRACE_LIB_ERRNO(lib_handle, "recv(%d) failed", evt->sock_fd); SET_CPC_RET(-errno); } else { - TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %d", evt->sock_fd, tmp_ret2); + TRACE_LIB_ERROR(lib_handle, -EBADE, "recv(%d) failed, ret = %zd", evt->sock_fd, tmp_ret2); SET_CPC_RET(-EBADE); } goto free_event; diff --git a/main.c b/main.c index d4b9efb..03e1111 100644 --- a/main.c +++ b/main.c @@ -14,7 +14,8 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE + +#include "config.h" #include @@ -35,13 +36,12 @@ #include "cpcd/security.h" #include "cpcd/server_core.h" -#include "version.h" #include "driver/driver_kill.h" #include "server_core/epoll/epoll.h" pthread_t main_thread; // Current thread -/* Global copy of argv to be able to restart the daemon with the same arguments. */ +// Global copy of argv to be able to restart the daemon with the same arguments. char **argv_g = 0; int argc_g = 0; @@ -63,7 +63,6 @@ int main(int argc, char *argv[]) PRINT_INFO("[CPCd v%s] [Library API v%d] [RCP Protocol v%d]", PROJECT_VER, LIBRARY_API_VERSION, PROTOCOL_VERSION); PRINT_INFO("Git commit: %s / branch: %s", GIT_SHA1, GIT_REFSPEC); - PRINT_INFO("Sources hash: %s", SOURCES_HASH); if (geteuid() == 0) { WARN("Running CPCd as 'root' is not recommended. Proceed at your own risk."); diff --git a/misc/board_controller.c b/misc/board_controller.c index 68b16b9..ca53635 100644 --- a/misc/board_controller.c +++ b/misc/board_controller.c @@ -14,7 +14,8 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE + +#include "config.h" #include #include diff --git a/misc/config.c b/misc/config.c index 4ab1e09..b46760e 100644 --- a/misc/config.c +++ b/misc/config.c @@ -14,10 +14,11 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE +#include "config.h" + +#include #include -#include #include #include #include @@ -40,8 +41,6 @@ #include "cpcd/sleep.h" #include "cpcd/utils.h" -#include "version.h" - #ifndef DEFAULT_INSTANCE_NAME #define DEFAULT_INSTANCE_NAME "cpcd_0" #endif @@ -451,7 +450,7 @@ static void config_parse_cli_arg(int argc, char *argv[]) config.file_path = optarg; break; case 's': - config.stats_interval = strtol(optarg, NULL, 0); + config.stats_interval = (int)strtol(optarg, NULL, 0); FATAL_ON(config.stats_interval <= 0); break; case 'h': @@ -836,7 +835,7 @@ static void config_parse_config_file(void) config.traces_folder = strdup(val); FATAL_ON(config.traces_folder == NULL); } else if (0 == strcmp(name, "rlimit_nofile")) { - config.rlimit_nofile = strtoul(val, &endptr, 10); + config.rlimit_nofile = (int)strtoul(val, &endptr, 10); if (*endptr != '\0') { FATAL("Config file error : bad rlimit_nofile value"); } @@ -1058,12 +1057,12 @@ static void config_set_rlimit_nofile(void) ret = getrlimit(RLIMIT_NOFILE, &limit); FATAL_SYSCALL_ON(ret < 0); - if (limit.rlim_cur < config.rlimit_nofile) { - if (config.rlimit_nofile > limit.rlim_max) { + if (limit.rlim_cur < (rlim_t)config.rlimit_nofile) { + if ((rlim_t)config.rlimit_nofile > limit.rlim_max) { FATAL("The OS doesn't support our requested RLIMIT_NOFILE value"); } - limit.rlim_cur = config.rlimit_nofile; + limit.rlim_cur = (rlim_t)config.rlimit_nofile; ret = setrlimit(RLIMIT_NOFILE, &limit); FATAL_SYSCALL_ON(ret < 0); @@ -1083,7 +1082,6 @@ static void config_print_version(FILE *stream, int exit_code) fprintf(stream, "%s\n", PROJECT_VER); fprintf(stream, "GIT commit: %s\n", GIT_SHA1); fprintf(stream, "GIT branch: %s\n", GIT_REFSPEC); - fprintf(stream, "Sources hash: %s\n", SOURCES_HASH); exit(exit_code); } diff --git a/misc/version.h.in b/misc/config.h.in similarity index 73% rename from misc/version.h.in rename to misc/config.h.in index 9af5201..86f9b2c 100644 --- a/misc/version.h.in +++ b/misc/config.h.in @@ -15,18 +15,33 @@ * ******************************************************************************/ -#ifndef VERSION_H -#define VERSION_H +#ifndef CONFIG_H +#define CONFIG_H -#define LIBRARY_API_VERSION @CPC_LIBRARY_API_VERSION@ -#define PROTOCOL_VERSION @CPC_PROTOCOL_VERSION@ -#define SOURCES_HASH "@SOURCES_HASH@" #define PROJECT_NAME "@PROJECT_NAME@" #define PROJECT_VER "@PROJECT_VERSION@" #define PROJECT_VER_MAJOR @PROJECT_VERSION_MAJOR@ #define PROJECT_VER_MINOR @PROJECT_VERSION_MINOR@ #define PROJECT_VER_PATCH @PROJECT_VERSION_PATCH@ #define PROJECT_VER_TWEAK @PROJECT_VERSION_TWEAK@ + #define PROJECT_MAX_VERSION_SIZE 16 -#endif //VERSION_H +#define LIBRARY_API_VERSION @CPC_LIBRARY_API_VERSION@ +#define PROTOCOL_VERSION @CPC_PROTOCOL_VERSION@ + +#define CPC_SOCKET_DIR "@CPC_SOCKET_DIR@" +#define DEFAULT_INSTANCE_NAME "@DEFAULT_INSTANCE_NAME@" +#define CPCD_CONFIG_FILE_PATH "@CPCD_CONFIG_FILE_PATH@" +#define CPCD_REBOOT_TIME_MS @CPCD_REBOOT_TIME_MS@ + +#define GIT_SHA1 "@GIT_SHA1@" +#define GIT_REFSPEC "@GIT_REFSPEC@" + +#cmakedefine USE_LEGACY_GPIO_SYSFS +#cmakedefine ENABLE_ENCRYPTION +#cmakedefine HAVE_BACKTRACE +#cmakedefine COMPILE_LTTNG +#cmakedefine TARGET_TESTING + +#endif // CONFIG_H diff --git a/misc/exit.c b/misc/exit.c index 95b4245..47dacf1 100644 --- a/misc/exit.c +++ b/misc/exit.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -134,7 +136,9 @@ __attribute__((noreturn)) void signal_crash(void) if (pthread_equal(pthread_self(), main_thread)) { exit_daemon(); } else { - write(crash_eventfd, &event_value, sizeof(event_value)); + ssize_t wc; + wc = write(crash_eventfd, &event_value, sizeof(event_value)); + (void)wc; } pthread_exit(NULL); @@ -165,7 +169,9 @@ __attribute__((noreturn)) void software_graceful_exit(void) if (pthread_self() == main_thread) { exit_daemon(); } else { - write(graceful_exit_eventfd, &event_value, sizeof(event_value)); + ssize_t wc; + wc = write(graceful_exit_eventfd, &event_value, sizeof(event_value)); + (void)wc; } pthread_exit(NULL); diff --git a/misc/gpio.c b/misc/gpio.c index 2894d48..9e40a6f 100644 --- a/misc/gpio.c +++ b/misc/gpio.c @@ -1,3 +1,5 @@ +#include "config.h" + #include #include @@ -11,6 +13,14 @@ #include "cpcd/gpio.h" #include "cpcd/logging.h" +// POSIX defines the second argument of ioctl function as int. That's +// how musl defines it too. But Glibc, Linux kernel and BSD OSes define +// it as unsigned long. This mismatch causes a compilation warning [1]. +// [1] https://www.openwall.com/lists/musl/2020/01/20/2 +#if defined(__GLIBC__) +#define ioctl(d, req, ...) ioctl((d), (unsigned int)(req), __VA_ARGS__) +#endif + static const char* direction_to_str(gpio_direction_t direction) { switch (direction) { @@ -84,7 +94,7 @@ gpio_t gpio_init(const char *gpio_chip, unsigned int gpio_pin, gpio_direction_t break; } - ret = ioctl(chip_fd, GPIO_GET_LINEEVENT_IOCTL, &rq); + ret = ioctl(chip_fd, (int)GPIO_GET_LINEEVENT_IOCTL, &rq); if (ret < 0) { FATAL("%s : The kernel must be configured with CONFIG_GPIO_CDEV_V1=y", strerror(errno)); } @@ -94,12 +104,13 @@ gpio_t gpio_init(const char *gpio_chip, unsigned int gpio_pin, gpio_direction_t ret = fcntl(gpio, F_SETFL, O_NONBLOCK); FATAL_SYSCALL_ON(ret < 0); } else { - struct gpiohandle_request rq = { 0 }; + struct gpiohandle_request rq; + memset(&rq, 0, sizeof(rq)); rq.lineoffsets[0] = gpio_pin; rq.flags = GPIOHANDLE_REQUEST_OUTPUT; rq.lines = 1; - ret = ioctl(chip_fd, GPIO_GET_LINEHANDLE_IOCTL, &rq); + ret = ioctl(chip_fd, (int)GPIO_GET_LINEHANDLE_IOCTL, &rq); if (ret < 0) { FATAL("%s : The kernel must be configured with CONFIG_GPIO_CDEV_V1=y", strerror(errno)); } @@ -132,7 +143,7 @@ void gpio_write(gpio_t gpio, gpio_value_t value) data.values[0] = value; - ret = ioctl(gpio, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); + ret = ioctl(gpio, (int)GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); FATAL_SYSCALL_ON(ret < 0); } @@ -141,7 +152,7 @@ gpio_value_t gpio_read(gpio_t gpio) struct gpiohandle_data data; int ret; - ret = ioctl(gpio, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); + ret = ioctl(gpio, (int)GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); FATAL_SYSCALL_ON(ret < 0); return (gpio_value_t) data.values[0]; @@ -149,7 +160,7 @@ gpio_value_t gpio_read(gpio_t gpio) int gpio_get_epoll_fd(gpio_t gpio) { - // The epoll file descriptor it the gpio_t itself + // The epoll file descriptor is the gpio_t itself return gpio; } diff --git a/misc/gpio_sysfs.c b/misc/gpio_sysfs.c index d3a511f..0c4e1c7 100644 --- a/misc/gpio_sysfs.c +++ b/misc/gpio_sysfs.c @@ -14,7 +14,8 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE + +#include "config.h" #include #include @@ -174,9 +175,11 @@ int gpio_get_epoll_fd(gpio_sysfs_t *gpio) void gpio_clear_irq(gpio_sysfs_t *gpio) { char buf[8]; + ssize_t ret; lseek(gpio->irq_fd, 0, SEEK_SET); - read(gpio->irq_fd, buf, sizeof(buf)); + ret = read(gpio->irq_fd, buf, sizeof(buf)); + (void)ret; } void gpio_write(gpio_sysfs_t *gpio, gpio_value_t value) diff --git a/misc/logging.c b/misc/logging.c index 964253e..e55998f 100644 --- a/misc/logging.c +++ b/misc/logging.c @@ -15,7 +15,8 @@ * ******************************************************************************/ -#define _GNU_SOURCE +#include "config.h" + #include #include @@ -145,8 +146,8 @@ static void async_logger_init(async_logger_t* logger, int file_descriptor, const logger->buffer = zalloc(logger->buffer_size); NO_LOGGING_FATAL_ON(logger->buffer == NULL); - /* Lock the buffer in RAM since it's a long buffer and we will use it often to prevent - * page faults. */ + // Lock the buffer in RAM since it's a long buffer and we will use it often to prevent + // page faults. ret = mlock(logger->buffer, logger->buffer_size); NO_LOGGING_FATAL_SYSCALL_ON(ret != 0); @@ -188,7 +189,7 @@ static void file_logging_init(void) ret = access(config.traces_folder, W_OK); NO_LOGGING_FATAL_SYSCALL_ON(ret < 0); - /* Build file string and open file */ + // Build file string and open file { time_t t = time(NULL); struct tm tm = *localtime(&t); @@ -206,7 +207,7 @@ static void file_logging_init(void) tm.tm_min, tm.tm_sec); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer NO_LOGGING_FATAL_SYSCALL_ON(nchars < 0 || (size_t) nchars >= sizeof(buf)); file_logger.file = fopen(buf, "w+"); @@ -235,7 +236,7 @@ static void async_logger_write(async_logger_t* logger, void* data, size_t length pthread_mutex_lock(&logger->mutex); { if (logger->buffer_size - logger->buffer_count < length) { - /* Overflowing traces are discarded */ + // Overflowing traces are discarded fprintf(stderr, "WARNING : %s logger buffer full, lost log.\n", logger->name); logger->lost_logs++; } else { @@ -244,15 +245,15 @@ static void async_logger_write(async_logger_t* logger, void* data, size_t length if (remaining >= length) { memcpy(&logger->buffer[logger->buffer_head], data, length); logger->buffer_head += length; - } else { /* Split write at buffer boundary */ + } else { // Split write at buffer boundary memcpy(&logger->buffer[logger->buffer_head], data, remaining); - memcpy(&logger->buffer[0], data + remaining, length - remaining); + memcpy(&logger->buffer[0], (const uint8_t *)data + remaining, length - remaining); logger->buffer_head = length - remaining; } logger->buffer_count += length; - /* Register the high water mark */ + // Register the high water mark if (logger->buffer_count > logger->highwater_mark) { logger->highwater_mark = logger->buffer_count; } @@ -264,9 +265,9 @@ static void async_logger_write(async_logger_t* logger, void* data, size_t length pthread_mutex_unlock(&logger->mutex); if (do_signal == true) { - /* Don't wake up the logger thread until sufficient data is present. - * It will wake up at regular interval anyway to keep stdout traces (in a - * terminal for example) fluid. */ + // Don't wake up the logger thread until sufficient data is present. + // It will wake up at regular interval anyway to keep stdout traces (in a + // terminal for example) fluid. if (count_cpy >= ASYNC_LOGGER_DONT_TRIGG_UNLESS_THIS_CHUNK_SIZE) { pthread_cond_signal(&logger->condition); } @@ -280,12 +281,12 @@ static void* async_logger_thread_func(void* param) ssize_t ret; while (1) { - /* Lock the mutex because we need to condition wait on the predicate 'buffer_count' - * which is altered by both the producers and this consumer */ + // Lock the mutex because we need to condition wait on the predicate 'buffer_count' + // which is altered by both the producers and this consumer pthread_mutex_lock(&logger->mutex); { - /* Wait until there is at least the preferred no-wake-up-until data amount, a timeout or - * a graceful exit request has been sent to us. */ + // Wait until there is at least the preferred no-wake-up-until data amount, a timeout or + // a graceful exit request has been sent to us. while (logger->buffer_count < ASYNC_LOGGER_DONT_TRIGG_UNLESS_THIS_CHUNK_SIZE && gracefully_exit == false) { struct timespec max_wait; @@ -299,22 +300,21 @@ static void* async_logger_thread_func(void* param) FATAL_ON(ret != 0 && ret != ETIMEDOUT); if (ret == ETIMEDOUT) { - /* We have timed out or a graceful exit is pending, don't block on the condition again - * and start writing the data we have to far. */ + // We have timed out or a graceful exit is pending, don't block on the condition again + // and start writing the data we have to far. break; } } - /* We will write as much data as we have on hand */ + // We will write as much data as we have on hand chunk_size = logger->buffer_count; - } /* Unlock the mutex to allow other threads to continue to write data. */ + } // Unlock the mutex to allow other threads to continue to write data. pthread_mutex_unlock(&logger->mutex); if (chunk_size == 0) { if (gracefully_exit == true) { - /* Graceful exit requested and no data, kill this thread right away. */ + // Graceful exit requested and no data, kill this thread right away. char buf[256]; - int ret; ret = snprintf(buf, sizeof(buf), "Logger buffer size = %zu, highwater mark = %zu : %.2f%%. Lost logs : %zu\n", @@ -322,8 +322,9 @@ static void* async_logger_thread_func(void* param) logger->highwater_mark, 100.0f * ((float) logger->highwater_mark / (float) logger->buffer_size), logger->lost_logs); - /* Dont check for 'ret' overflow, we know 256 bytes was sufficient. */ - (void)write(logger->fd, buf, (size_t)ret); + ret = write(logger->fd, buf, (size_t)ret); + // Dont check for 'ret' overflow, we know 256 bytes was sufficient. + (void)ret; fsync(logger->fd); if (logger->fd != STDOUT_FILENO) { ret = fclose(logger->file); @@ -332,25 +333,25 @@ static void* async_logger_thread_func(void* param) free(logger->buffer); pthread_exit(NULL); } else { - /* We have timed out, and there's not even a single byte of logging data available. - * Skip the rest and go back to waiting for data. */ + // We have timed out, and there's not even a single byte of logging data available. + // Skip the rest and go back to waiting for data. continue; } } - /* Remaining bytes between the tail and end end of the circular buffer */ + // Remaining bytes between the tail and end end of the circular buffer size_t remaining = logger->buffer_size - logger->buffer_tail; - /* This consumer thread is the only one manipulating the tail, so we can safely use it while the - * lock is not held to write a chunk of data to the file. We can safely write this chunk and take - * the time we want outside of the lock because as far as the producers are concerned, - * this chunk is still in the buffer and cannot be overridden. */ + // This consumer thread is the only one manipulating the tail, so we can safely use it while the + // lock is not held to write a chunk of data to the file. We can safely write this chunk and take + // the time we want outside of the lock because as far as the producers are concerned, + // this chunk is still in the buffer and cannot be overridden. { if (remaining >= chunk_size) { write_until_success_or_error(logger->fd, &logger->buffer[logger->buffer_tail], chunk_size); - } else { /* Split write at the buffer boundary */ + } else { // Split write at the buffer boundary write_until_success_or_error(logger->fd, &logger->buffer[logger->buffer_tail], remaining); @@ -361,8 +362,8 @@ static void* async_logger_thread_func(void* param) } } - /* Now that the chunk is written, take back the lock to update the tail and decrease the - * count, which is the shared variable. */ + // Now that the chunk is written, take back the lock to update the tail and decrease the + // count, which is the shared variable. pthread_mutex_lock(&logger->mutex); { if (remaining >= chunk_size) { @@ -391,14 +392,14 @@ static void file_log(void* data, size_t length) void logging_init(void) { - /* Completely initialize stdout logging no matter what, because we still print some - * info /early info even if the complete logging is not enabled. */ + // Completely initialize stdout logging no matter what, because we still print some + // info /early info even if the complete logging is not enabled. stdout_logging_init(); - /* Partially init the file logger (the log struct) to be able to record early log and - * write them later on if the config file enables it. */ + // Partially init the file logger (the log struct) to be able to record early log and + // write them later on if the config file enables it. async_logger_init(&file_logger, - -1, /* No file descriptor for the moment */ + -1, // No file descriptor for the moment "file"); } @@ -406,7 +407,7 @@ static void logging_print_stats(epoll_private_data_t *event_private_data) { int fd_timer = event_private_data->file_descriptor; - /* Ack the timer */ + // Ack the timer { uint64_t expiration; ssize_t ret; @@ -486,7 +487,7 @@ static void logging_print_stats(epoll_private_data_t *event_private_data) void init_stats_logging(void) { - /* Setup timer */ + // Setup timer stats_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); FATAL_SYSCALL_ON(stats_timer_fd < 0); @@ -500,7 +501,7 @@ void init_stats_logging(void) FATAL_SYSCALL_ON(ret < 0); - /* Setup epoll */ + // Setup epoll { logging_private_data = (epoll_private_data_t*) zalloc(sizeof(epoll_private_data_t)); FATAL_ON(logging_private_data == NULL); @@ -512,14 +513,14 @@ void init_stats_logging(void) } } -void init_file_logging() +void init_file_logging(void) { file_logging_init(); } void logging_kill(void) { - /* Note we don't cancel the threads, we let them finish */ + // Note we don't cancel the threads, we let them finish gracefully_exit = true; @@ -558,7 +559,7 @@ static size_t get_time_string(char *slice, size_t slice_len) return 0; } - /* XXXX-XX-XXTXX:XX:XX + .XXXXXX + Z */ + // XXXX-XX-XXTXX:XX:XX + .XXXXXX + Z strftime(slice, 19 + 1, "%FT%T", &tm); snprintf(slice + 19, 7 + 1, ".%06lu", (long)now.tv_nsec / 1000); slice[26] = 'Z'; @@ -574,7 +575,7 @@ void trace(const bool force_stdout, const char* string, ...) return; } - /* Append the time stamp */ + // Append the time stamp { log_string[log_string_length++] = '['; log_string_length += get_time_string(log_string + log_string_length, sizeof(log_string) - log_string_length); @@ -582,7 +583,7 @@ void trace(const bool force_stdout, const char* string, ...) log_string[log_string_length++] = ' '; } - /* Append formated text */ + // Append formated text { va_list vl; @@ -596,7 +597,7 @@ void trace(const bool force_stdout, const char* string, ...) if ((size_t)nchar >= size) { fprintf(stderr, "Truncated log message"); - /* The string was truncated, terminate it properly*/ + // The string was truncated, terminate it properly log_string[sizeof(log_string) - 1] = '\n'; log_string_length = sizeof(log_string); } else { @@ -623,7 +624,7 @@ void trace_no_timestamp(const char* string, ...) return; } - /* Append formated text */ + // Append formated text { va_list vl; @@ -637,7 +638,7 @@ void trace_no_timestamp(const char* string, ...) if ((size_t)nchar >= size) { fprintf(stderr, "Truncated log message"); - /* The string was truncated, terminate it properly*/ + // The string was truncated, terminate it properly log_string[sizeof(log_string) - 1] = '\n'; log_string_length = sizeof(log_string); } else { @@ -664,7 +665,7 @@ static inline void byte_to_hex(uint8_t byte, char str[2]) void trace_frame(const char* string, const void* buffer, size_t len) { - char log_string[4096]; /* Arbitrary size. Large buffer frames will most likely overflow. */ + char log_string[4096]; // Arbitrary size. Large buffer frames will most likely overflow. size_t log_string_length = 0; uint8_t* frame = (uint8_t*) buffer; @@ -672,7 +673,7 @@ void trace_frame(const char* string, const void* buffer, size_t len) return; } - /* Append the time stamp */ + // Append the time stamp { log_string[log_string_length++] = '['; log_string_length += get_time_string(log_string + log_string_length, sizeof(log_string) - log_string_length); @@ -682,11 +683,11 @@ void trace_frame(const char* string, const void* buffer, size_t len) } } - /* Append string up to buffer */ + // Append string up to buffer for (size_t i = 0; string[i] != '\0'; i++) { - /* Edge case where the string itself can fill the whole buffer.. */ + // Edge case where the string itself can fill the whole buffer.. if (log_string_length >= sizeof(log_string)) { - /* Flush the buffer */ + // Flush the buffer if (config.stdout_tracing) { stdio_log(log_string, log_string_length); } @@ -694,19 +695,19 @@ void trace_frame(const char* string, const void* buffer, size_t len) file_log(log_string, log_string_length); } - /* Start at the beginning */ + // Start at the beginning log_string_length = 0; } log_string[log_string_length++] = string[i]; } - /* Append hex data */ + // Append hex data for (size_t i = 0; i != len; i++) { - /* In the case of large buffer, its possible we reach the end of the buffer - * in the middle of the parsing, flush the buffer */ + // In the case of large buffer, its possible we reach the end of the buffer + // in the middle of the parsing, flush the buffer if (log_string_length >= sizeof(log_string) - sizeof("xx:")) { - /* Flush the buffer */ + // Flush the buffer if (config.stdout_tracing) { stdio_log(log_string, log_string_length); } @@ -714,7 +715,7 @@ void trace_frame(const char* string, const void* buffer, size_t len) file_log(log_string, log_string_length); } - /* Start at the beginning */ + // Start at the beginning log_string_length = 0; } @@ -724,7 +725,7 @@ void trace_frame(const char* string, const void* buffer, size_t len) log_string[log_string_length++] = ':'; } - /* Newline terminate the string (overriding the last semicolon)*/ + // Newline terminate the string (overriding the last semicolon) if (log_string_length) { log_string[log_string_length - 1] = '\n'; diff --git a/misc/sl_slist.c b/misc/sl_slist.c index 4955144..0febcd6 100644 --- a/misc/sl_slist.c +++ b/misc/sl_slist.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -136,8 +138,6 @@ void sl_slist_remove(sl_slist_node_t **head, return; } } - - EFM_ASSERT(node_ptr != NULL); } /***************************************************************************//** diff --git a/misc/sleep.c b/misc/sleep.c index 668a169..2565696 100644 --- a/misc/sleep.c +++ b/misc/sleep.c @@ -15,8 +15,10 @@ * ******************************************************************************/ -#include /* EINTR errno */ -#include /* struct_timespec time_t nanosleep() */ +#include "config.h" + +#include // EINTR errno +#include // struct_timespec time_t nanosleep() #include "cpcd/sleep.h" @@ -24,18 +26,18 @@ int sleep_us(uint32_t us) { int ret; struct timespec ts; - /* Take the hot path if timeout is below one second */ + // Take the hot path if timeout is below one second if (us < 1000000) { ts.tv_sec = 0; - /* This is a safe cast: worst case scenario is the result gives 999999000, - * which always fits in a long (>=i32) */ + // This is a safe cast: worst case scenario is the result gives 999999000, + // which always fits in a long (>=i32) ts.tv_nsec = (long)(us * 1000); } else { - /* There is no portable way to get the maximum value of time_t, so we cast - * and pray. */ + // There is no portable way to get the maximum value of time_t, so we cast + // and pray. ts.tv_sec = (time_t)(us / 1000000); - /* This is a safe cast: worst case scenario is the result gives 999'999'999, - * which always fits in a long (>=i32) */ + // This is a safe cast: worst case scenario is the result gives 999'999'999, + // which always fits in a long (>=i32) ts.tv_nsec = (long)((us % 1000000) * 1000); } do { @@ -48,8 +50,7 @@ int sleep_s(uint32_t s) { int ret; struct timespec ts; - /* There is no portable way to get the maximum value of time_t, so we cast and - * pray. */ + // There is no portable way to get the maximum value of time_t, so we cast and pray. ts.tv_sec = (time_t)s; ts.tv_nsec = 0; do { diff --git a/misc/utils.c b/misc/utils.c index 041df7e..d67fa42 100644 --- a/misc/utils.c +++ b/misc/utils.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include @@ -31,32 +33,30 @@ int recursive_mkdir(const char *dir, size_t len, const mode_t mode) tmp = (char *)zalloc(len + 1); FATAL_ON(tmp == NULL); - /* copy path */ + // Copy path ret = snprintf(tmp, len + 1, "%s", dir); FATAL_ON(ret < 0 || (size_t) ret >= (len + 1)); - /* remove trailing slash */ + // Remove trailing slash if (tmp[len - 1] == '/') { tmp[len - 1] = '\0'; } - /* check if path exists and is a directory */ + // Check if path exists and is a directory ret = stat(tmp, &sb); if (ret == 0) { - /* ret is 0 if S_ISDIR returns a non-zero value, meaning that the path is a directory */ + // ret is 0 if S_ISDIR returns a non-zero value, meaning that the path is a directory ret = S_ISDIR(sb.st_mode) != 0 ? 0 : -1; goto cleanup; } - /* recursive mkdir */ + // Recursive mkdir for (p = tmp + 1; *p; p++) { if (*p == '/') { *p = 0; - /* - * mkdir first and then check stat to avoid potential - * time of check/time of use issues - */ + // mkdir first and then check stat to avoid potential + // time of check/time of use issues ret = mkdir(tmp, mode); if (ret < 0) { if (errno != EEXIST) { @@ -92,7 +92,7 @@ int recursive_mkdir(const char *dir, size_t len, const mode_t mode) ret = S_ISDIR(sb.st_mode) != 0 ? 0 : -1; - /* Fall through to return ret */ + // Fall through to return ret cleanup: free(tmp); diff --git a/modes/binding.c b/modes/binding.c index 624cd23..3859336 100644 --- a/modes/binding.c +++ b/modes/binding.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include "cpcd/config.h" diff --git a/modes/firmware_update.c b/modes/firmware_update.c index c48a8dd..bea39fd 100644 --- a/modes/firmware_update.c +++ b/modes/firmware_update.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -33,14 +35,12 @@ #include "driver/driver_spi.h" #include "driver/driver_xmodem.h" #include "driver/driver_ezsp.h" -#include "version.h" #define RESET_TIMEOUT_MS 500 extern char *server_core_secondary_app_version; extern uint8_t server_core_secondary_protocol_version; extern sl_cpc_bootloader_t server_core_secondary_bootloader_type; -extern bool secondary_already_running_bootloader; static void reboot_secondary_with_pins_into_bootloader(void); static void reboot_secondary_by_cpc(server_core_mode_t mode); @@ -206,11 +206,12 @@ static void reboot_secondary_with_pins_into_bootloader(void) int ret; struct epoll_event ev; static int fd_epoll; + bus_t bus = config.bus; reset_gpio = gpio_init(config.fwu_reset_chip, (unsigned int)config.fwu_spi_reset_pin, GPIO_DIRECTION_OUT, GPIO_EDGE_NO_EDGE); wake_gpio = gpio_init(config.fwu_wake_chip, (unsigned int)config.fwu_spi_wake_pin, GPIO_DIRECTION_OUT, GPIO_EDGE_NO_EDGE); - if (config.bus == SPI) { + if (bus == SPI) { irq_gpio = gpio_init(config.spi_irq_chip, config.spi_irq_pin, GPIO_DIRECTION_IN, GPIO_EDGE_FALLING); // Create the epoll set @@ -236,7 +237,7 @@ static void reboot_secondary_with_pins_into_bootloader(void) // will stay in bootloader mode gpio_write(reset_gpio, GPIO_VALUE_HIGH); - if (config.bus == SPI) { + if (bus == SPI) { // Make sure the falling-edge caused by the chip entering reset is cleared gpio_clear_irq(irq_gpio); @@ -277,7 +278,7 @@ static void reboot_secondary_with_pins_into_bootloader(void) gpio_deinit(wake_gpio); gpio_deinit(reset_gpio); - if (config.bus == SPI) { + if (bus == SPI) { gpio_deinit(irq_gpio); } diff --git a/modes/normal.c b/modes/normal.c index 2ff52ac..56d89f7 100644 --- a/modes/normal.c +++ b/modes/normal.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include "cpcd/config.h" diff --git a/modes/uart_validation.c b/modes/uart_validation.c index ea6d661..e7100c1 100644 --- a/modes/uart_validation.c +++ b/modes/uart_validation.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -32,49 +34,49 @@ #define TIMEOUT_SECONDS 5 #define TIME_BETWEEN_RETRIES_US 1000000 -/* Flag set when waiting on external reset */ +// Flag set when waiting on external reset static bool wait_on_reset_external; -/* Flag set when external reset status is received */ +// Flag set when external reset status is received static bool reset_external_received; -/* Flag set when waiting on software reset */ +// Flag set when waiting on software reset static bool wait_on_reset_software; -/* Flag set when software reset status is received */ +// Flag set when software reset status is received static bool reset_software_received; -/* Flag set when secondary cpc version is received */ +// Flag set when secondary cpc version is received static bool secondary_cpc_version_received; -/* Flag set when fc validation value is received */ +// Flag set when fc validation value is received static bool fc_validation_value_received; -/* Flow control validation value */ +// Flow control validation value static uint32_t fc_validation_value; -/* Flag set when uframe processing is received */ +// Flag set when uframe processing is received static bool uframe_processing_received; -/* Flag set when enter irq is received */ +// Flag set when enter irq is received static bool enter_irq_received; -/* Flag set when noop is received */ +// Flag set when noop is received static bool noop_received; -/* Server core communication */ +// Server core communication static int server_core_fd; static epoll_private_data_t server_core_epoll_pdata; -/* Setup/teardown server core sockets */ +// Setup/teardown server core sockets static void setup_server_core_sockets(void); static void teardown_server_core_sockets(void); -/* Main tests */ +// Main tests static void test_1_rx_tx(void); static void test_2_rts_cts(void); -/* Sub tests */ +// Sub tests static void open_uart_port_subtest(bool flowcontrol); static void reset_external_subtest(void); static void reset_software_subtest(void); @@ -85,11 +87,11 @@ static void send_noop_subtest(void); static uint32_t send_data_subtest(void); static uint32_t get_fc_validation_value_subtest(void); -/* Helpers */ +// Helpers static void compare_fc_validation_values(uint32_t reference_value, uint32_t received_value); static void wait(uint32_t mseconds); -/* Callbacks */ +// Callbacks static void reset_software_callback(sl_status_t status, sl_cpc_system_status_t reset_status); @@ -119,9 +121,6 @@ static void enter_irq_callback(sli_cpc_property_id_t property_id, static void noop_callback(sl_status_t status); -/* External functions */ -__attribute__((noreturn)) void software_graceful_exit(void); - static void server_core_write_callback(epoll_private_data_t *private_data) { ssize_t ret; @@ -238,11 +237,11 @@ static void test_2_rts_cts(void) uint32_t irq_start_in_ms = 500, irq_end_in_ms = 3000; enter_irq_subtest(irq_start_in_ms, irq_end_in_ms); wait(irq_start_in_ms + irq_start_in_ms); - uint32_t fc_validation_value = send_data_subtest(); + uint32_t local_fc_validation_value = send_data_subtest(); wait(irq_end_in_ms); uint32_t received_fc_validation_value = get_fc_validation_value_subtest(); enable_uframe_processing_subtest(false); - compare_fc_validation_values(fc_validation_value, received_fc_validation_value); + compare_fc_validation_values(local_fc_validation_value, received_fc_validation_value); PRINT_INFO("Validating Host RTS <-> Secondary CTS..."); send_noop_subtest(); diff --git a/script/cpc_iostream_bridge.py b/script/cpc_iostream_bridge.py old mode 100644 new mode 100755 index 1f9b38f..efb54a8 --- a/script/cpc_iostream_bridge.py +++ b/script/cpc_iostream_bridge.py @@ -1,12 +1,16 @@ #!/usr/bin/env python3 +import argparse +import pathlib +import signal import socket -import threading -import libcpc import sys -import signal +import threading import time -import argparse + +sys.path.append(str(pathlib.Path(__file__).parents[1].joinpath("lib/bindings/python/src"))) + +import libcpc verbose = False reset_flag = False diff --git a/security/private/keys/keys.c b/security/private/keys/keys.c index 6e54580..eeef096 100644 --- a/security/private/keys/keys.c +++ b/security/private/keys/keys.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -79,11 +81,9 @@ static nonce_t nonce_secondary; static bool security_session_reset_triggered; #if defined(UNIT_TESTING) -/* - * Emulate nonces as they should be on the secondary: - * - secondary_nonce_primary: packets sent from host to secondary - * - secondary_nonce_secondary: packets sent from secondary to host - */ +// Emulate nonces as they should be on the secondary: +// - secondary_nonce_primary: packets sent from host to secondary +// - secondary_nonce_secondary: packets sent from secondary to host static nonce_t secondary_nonce_primary; static nonce_t secondary_nonce_secondary; #endif @@ -101,11 +101,9 @@ static FILE* security_open_or_create_plaintext_binding_key_file(const char *file static void security_nonce_init(nonce_t *nonce) { - /* - * only setting frame_counter to zero matters, other attributes - * will be initialized when the session id is computed, but do it - * for completeness - */ + // only setting frame_counter to zero matters, other attributes + // will be initialized when the session id is computed, but do it + // for completeness nonce->iv.endpoint_id = 0; memset(&nonce->iv.session_id, 0x0, sizeof(nonce->iv.session_id)); nonce->iv.frame_counter = 0; @@ -147,32 +145,24 @@ static void security_nonce_xfer_finalize(nonce_t *nonce, uint32_t *frame_counter } if (increment) { - /* - * Secondary's architecture is Little Endian, so we need to make sure the - * host uses the same way of storing the frame counter or there will be - * mismatch on Big Endian architecture. - */ + // Secondary's architecture is Little Endian, so we need to make sure the + // host uses the same way of storing the frame counter or there will be + // mismatch on Big Endian architecture. (*frame_counter)++; if (*frame_counter == NONCE_FRAME_COUNTER_MAX_VALUE) { - /* - * Set security in reset mode only if it's currently "initialized". This - * is to prevent a scenario where it's first reset because of a TX packet, - * and then reset again by an RX packet. - */ + // Set security in reset mode only if it's currently "initialized". This + // is to prevent a scenario where it's first reset because of a TX packet, + // and then reset again by an RX packet. if (security_get_state() == SECURITY_STATE_INITIALIZED) { - /* - * Keep track of the endpoint that triggered the endpoint - */ + // Keep track of the endpoint that triggered the endpoint security_session_reset_triggered = true; - /* - * make sure packets on user endpoins are blocked - * while security session is being reset. - */ + // make sure packets on user endpoins are blocked + // while security session is being reset. security_set_state(SECURITY_STATE_RESETTING); - /* Notify the security thread to renegotiate a new session */ + // Notify the security thread to renegotiate a new session security_post_command(SECURITY_COMMAND_RESET_SESSION); } } @@ -255,10 +245,10 @@ void security_keys_init(void) int ret; const char app_custom[] = "CPCD custom"; - /* Perform MbedTLS runtime version check */ + // Perform MbedTLS runtime version check FATAL_ON(MBEDTLS_VERSION_CHECK); - /* Perform an initial self tests */ + // Perform an initial self tests #if defined(MBEDTLS_SELF_TEST) FATAL_ON(mbedtls_gcm_self_test(0) != 0); FATAL_ON(mbedtls_ctr_drbg_self_test(0) != 0); @@ -293,10 +283,8 @@ void security_keys_init(void) void security_keys_reset(void) { - /* - * Clear GCM context and underlying cipher sub-context - * and reinit the context for next session - */ + // Clear GCM context and underlying cipher sub-context + // and reinit the context for next session mbedtls_gcm_free(&gcm_context); mbedtls_gcm_init(&gcm_context); @@ -318,7 +306,7 @@ static void security_keys_init_ecdh(void) mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&our_public_key); - /* Initialize context and generate keypair */ + // Initialize context and generate keypair ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519); if (ret != 0) { FATAL("ECDH: Failed to load private key variable. ret=%d", ret); @@ -435,13 +423,13 @@ void security_compute_session_key_and_id(uint8_t * random1, uint8_t session_key[SESSION_KEY_LENGTH_BYTES] = { 0 }; if (security_get_state() == SECURITY_STATE_RESETTING) { - /* if security is resetting, clear previous context and reset nonces */ + // if security is resetting, clear previous context and reset nonces security_keys_reset(); } - /* Generate Session ID and Session Key */ + // Generate Session ID and Session Key { - /* Both devices will construct a string of bits: Rand-3 = Rand-1[0:255] || Rand-2[0:255] */ + // Both devices will construct a string of bits: Rand-3 = Rand-1[0:255] || Rand-2[0:255] memcpy(&random3[0], random1, half_random_len); memcpy(&random3[half_random_len], random2, half_random_len); @@ -452,12 +440,9 @@ void security_compute_session_key_and_id(uint8_t * random1, 0); //is not sha224 FATAL_ON(ret != 0); - /* - * The resulting 32-byte number will be split into two 8-byte values as follows: - * Result = Session-ID-Host || Session-ID-NCP || Discarded data - * - * As the session id in nonce is only 7 bytes, drop the last byte of each 8-byte value. - */ + // The resulting 32-byte number will be split into two 8-byte values as follows: + // Result = Session-ID-Host || Session-ID-NCP || Discarded data + // As the session id in nonce is only 7 bytes, drop the last byte of each 8-byte value. security_nonce_set_session_id(&nonce_primary, &sha256_random3[0], SESSION_ID_LENGTH_BYTES); security_nonce_set_session_id(&nonce_secondary, @@ -472,13 +457,13 @@ void security_compute_session_key_and_id(uint8_t * random1, SESSION_ID_LENGTH_BYTES); #endif - /* To generate the session key a second string of bits is constructed: Rand-4 = Rand-1[256:511] || Rand-2[256:511] || Binding Key[0:128] */ + // To generate the session key a second string of bits is constructed: Rand-4 = Rand-1[256:511] || Rand-2[256:511] || Binding Key[0:128] memcpy(&random4[0], &random1[half_random_len], half_random_len); memcpy(&random4[half_random_len], &random2[half_random_len], half_random_len); memcpy(&random4[2 * half_random_len], binding_key, BINDING_KEY_LENGTH_BYTES); - /* Both devices perform SHA256 on RAND-4 - * The resulting 256 bit number is then used as the session key */ + // Both devices perform SHA256 on RAND-4 + // The resulting 256 bit number is then used as the session key ret = mbedtls_sha256(random4, sizeof(random4), session_key, @@ -486,7 +471,7 @@ void security_compute_session_key_and_id(uint8_t * random1, FATAL_ON(ret != 0); } - /* The session key is then used to encrypt all remaining communication */ + // The session key is then used to encrypt all remaining communication ret = mbedtls_gcm_setkey(&gcm_context, MBEDTLS_CIPHER_ID_AES, session_key, SESSION_KEY_LENGTH_BYTES * 8); FATAL_ON(ret != 0); @@ -549,27 +534,26 @@ void security_load_binding_key_from_file(void) string_len = strlen(line); - /* Prune possible line feeds */ + // Prune possible line feeds if (line[string_len - 1] == '\n' || line[string_len - 1] == '\r') { line[string_len - 1] = '\0'; string_len--; } - /* Assert that the key is 128 bit long */ + // Assert that the key is 128 bit long if (string_len != BINDING_KEY_LENGTH_BYTES * 2) { FATAL("The binding key \'%s\' : [%s] is %u bits long, should be %u bits long", config.binding_key_file, line, (unsigned int)(string_len * 4), BINDING_KEY_LENGTH_BYTES * 8); } - /* Make sure that all chars are hex symbols */ + // Make sure that all chars are hex symbols for (i = 0; i != BINDING_KEY_LENGTH_BYTES * 2; i++) { if (isxdigit(line[i]) == 0) { FATAL("Character number %u of the binding key is not a hexadecimal digit : %c", (unsigned int)i, line[i]); } } - /* Parse the binding key string into a binary array*/ + // Parse the binding key string into a binary array { - size_t i; unsigned chr; for (i = 0; i < BINDING_KEY_LENGTH_BYTES * 2; i += 2 ) { @@ -580,7 +564,7 @@ void security_load_binding_key_from_file(void) } } - /* line was internally malloc'ed by getline() */ + // line was internally malloc'ed by getline() free(line); TRACE_SECURITY("Loaded valid binding key"); @@ -629,7 +613,7 @@ sl_status_t __security_encrypt(sl_cpc_endpoint_t *ep, sl_cpc_security_frame_t *s FATAL_ON(tag_len != TAG_LENGTH_BYTES); - /* set the endpoint in the nonce */ + // set the endpoint in the nonce security_nonce_xfer_init(&nonce_primary, ep->id, sec_frame->frame_counter, true); status = mbedtls_gcm_crypt_and_tag(&gcm_context, @@ -641,13 +625,13 @@ sl_status_t __security_encrypt(sl_cpc_endpoint_t *ep, sl_cpc_security_frame_t *s // authenticated but not encrypted header, header_len, - payload, //The input buffer is the payload + payload, // The input buffer is the payload output, tag_len, tag); if (status == 0) { - /* only upon successful encryption increase frame counter */ + // only upon successful encryption increase frame counter security_nonce_xfer_finalize(&nonce_primary, &ep->frame_counter_tx, false); return SL_STATUS_OK; @@ -655,7 +639,7 @@ sl_status_t __security_encrypt(sl_cpc_endpoint_t *ep, sl_cpc_security_frame_t *s security_nonce_xfer_finalize(&nonce_primary, &ep->frame_counter_tx, false); - /* convert mbedtls error code to sl_status */ + // convert mbedtls error code to sl_status if (status == MBEDTLS_ERR_GCM_BAD_INPUT) { return SL_STATUS_INVALID_PARAMETER; } else { @@ -694,7 +678,7 @@ sl_status_t __security_decrypt(sl_cpc_endpoint_t *ep, security_nonce_xfer_finalize(&nonce_secondary, &ep->frame_counter_rx, false); - /* convert mbedtls error code to sl_status */ + // convert mbedtls error code to sl_status if (status == MBEDTLS_ERR_GCM_BAD_INPUT) { return SL_STATUS_INVALID_PARAMETER; } else if (status == MBEDTLS_ERR_GCM_AUTH_FAILED) { @@ -715,7 +699,7 @@ sl_status_t __security_encrypt_secondary(sl_cpc_endpoint_t *ep, FATAL_ON(tag_len != TAG_LENGTH_BYTES); - /* set the endpoint in the nonce */ + // set the endpoint in the nonce security_nonce_xfer_init(&secondary_nonce_secondary, ep->id, ep->frame_counter_tx, false); status = mbedtls_gcm_crypt_and_tag(&gcm_context, @@ -727,13 +711,13 @@ sl_status_t __security_encrypt_secondary(sl_cpc_endpoint_t *ep, // authenticated but not encrypted header, header_len, - payload, //The input buffer is the payload + payload, // The input buffer is the payload output, tag_len, tag); if (status == 0) { - /* only upon successful encryption increase frame counter */ + // only upon successful encryption increase frame counter security_nonce_xfer_finalize(&secondary_nonce_secondary, &ep->frame_counter_tx, true); return SL_STATUS_OK; @@ -741,7 +725,7 @@ sl_status_t __security_encrypt_secondary(sl_cpc_endpoint_t *ep, security_nonce_xfer_finalize(&secondary_nonce_secondary, &ep->frame_counter_tx, false); - /* convert mbedtls error code to sl_status */ + // convert mbedtls error code to sl_status if (status == MBEDTLS_ERR_GCM_BAD_INPUT) { return SL_STATUS_INVALID_PARAMETER; } else { @@ -780,7 +764,7 @@ sl_status_t __security_decrypt_secondary(sl_cpc_endpoint_t *ep, security_nonce_xfer_finalize(&secondary_nonce_primary, &ep->frame_counter_rx, false); - /* convert mbedtls error code to sl_status */ + // convert mbedtls error code to sl_status if (status == MBEDTLS_ERR_GCM_BAD_INPUT) { return SL_STATUS_INVALID_PARAMETER; } else if (status == MBEDTLS_ERR_GCM_AUTH_FAILED) { @@ -794,9 +778,7 @@ sl_status_t __security_decrypt_secondary(sl_cpc_endpoint_t *ep, void security_xfer_rollback(sl_cpc_endpoint_t *ep) { #if defined(ENABLE_ENCRYPTION) - sl_cpc_security_state_t security_state = security_get_state(); - - if (security_state == SECURITY_STATE_INITIALIZED) { + if (security_get_state() == SECURITY_STATE_INITIALIZED) { ep->frame_counter_rx--; TRACE_SECURITY("Rolled back frame counter on ep #%d, counter decremented", ep->id); } diff --git a/security/private/keys/keys.h b/security/private/keys/keys.h index fbda4e4..e639862 100644 --- a/security/private/keys/keys.h +++ b/security/private/keys/keys.h @@ -47,7 +47,6 @@ uint8_t* security_keys_get_ecdh_public_key(void); void security_load_binding_key_from_file(void); -void security_set_state_disabled(void); void security_keys_generate_shared_key(uint8_t *peer_public_key); mbedtls_ctr_drbg_context* security_keys_get_rng_context(void); @@ -82,4 +81,4 @@ sl_status_t __security_decrypt_secondary(sl_cpc_endpoint_t *ep, const uint8_t *tag, const size_t tag_len); #endif // UNIT_TESTING -#endif //SECURITY_KEYS_H +#endif // SECURITY_KEYS_H diff --git a/security/private/protocol/protocol.c b/security/private/protocol/protocol.c index 4899af1..f99be7b 100644 --- a/security/private/protocol/protocol.c +++ b/security/private/protocol/protocol.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include @@ -274,7 +276,7 @@ void security_initialize_session(void) sizeof(random1)); FATAL_ON(ret != 0); - /* Send random1 and receive random 2 */ + // Send random1 and receive random 2 status = security_send_session_init_request(random1, &protocol_response); if (status != SL_STATUS_OK) { @@ -296,6 +298,6 @@ void security_initialize_session(void) TRACE_SECURITY("Session initialized"); - /* Notify server_core that security is ready */ + // Notify server_core that security is ready server_core_notify_security_ready(); } diff --git a/security/private/protocol/protocol.h b/security/private/protocol/protocol.h index 48af529..e099ba8 100644 --- a/security/private/protocol/protocol.h +++ b/security/private/protocol/protocol.h @@ -21,7 +21,7 @@ #include "cpcd/sl_status.h" #include "security/private/keys/keys.h" -#include "lib/sl_cpc.h" +#include "sl_cpc.h" #define SLI_SECURITY_PROTOCOL_HEADER_LENGTH (sizeof(uint16_t) + sizeof(sl_cpc_security_id_t)) @@ -90,4 +90,4 @@ void security_initialize_session(void); void security_reset_session(void); -#endif //SECURITY_PROTOCOL_H +#endif // SECURITY_PROTOCOL_H diff --git a/security/private/thread/command_synchronizer.c b/security/private/thread/command_synchronizer.c index d183ff3..9bb4a4a 100644 --- a/security/private/thread/command_synchronizer.c +++ b/security/private/thread/command_synchronizer.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include "cpcd/config.h" @@ -23,7 +25,7 @@ #include "security/security.h" #include "security/private/thread/command_synchronizer.h" -/* Inter-thread command sending synchronization */ +// Inter-thread command sending synchronization static struct { sl_cpc_security_command_t command_type; pthread_cond_t command_in_process_condition; @@ -43,8 +45,8 @@ void security_post_command(sl_cpc_security_command_t command) FATAL("Tried to send a security command when encryption is disabled"); } - /* A condition is used in pair with a mutex to check against the condition's predicate - * (i.e security_event_binary_synchronizer.event_type) */ + // A condition is used in pair with a mutex to check against the condition's predicate + // (i.e security_event_binary_synchronizer.event_type) pthread_mutex_lock(&command_binary_synchronizer.command_in_progress_mutex); { while (command_binary_synchronizer.command_type != SECURITY_COMMAND_NONE) { @@ -53,10 +55,10 @@ void security_post_command(sl_cpc_security_command_t command) FATAL_ON(ret != 0); } - /* Here we know that no security event request is pending and have the lock to update it */ + // Here we know that no security event request is pending and have the lock to update it command_binary_synchronizer.command_type = command; - /* Kick the condition to notify the security thread that a event is requested */ + // Kick the condition to notify the security thread that a event is requested ret = pthread_cond_signal(&command_binary_synchronizer.command_in_process_condition); FATAL_ON(ret != 0); } @@ -72,11 +74,11 @@ sl_cpc_security_command_t security_wait_for_command(void) int ret; sl_cpc_security_command_t command; - /* A condition is used in pair with a mutex to check against the condition's predicate - * (i.e security_event_binary_synchronizer.event_type) */ + // A condition is used in pair with a mutex to check against the condition's predicate + // (i.e security_event_binary_synchronizer.event_type) pthread_mutex_lock(&command_binary_synchronizer.command_in_progress_mutex); { - /* Wait until there is an event */ + // Wait until there is an event while (command_binary_synchronizer.command_type == SECURITY_COMMAND_NONE) { ret = pthread_cond_wait(&command_binary_synchronizer.command_in_process_condition, &command_binary_synchronizer.command_in_progress_mutex); @@ -85,8 +87,8 @@ sl_cpc_security_command_t security_wait_for_command(void) command = command_binary_synchronizer.command_type; - /* The event has been registered, kick the condition to let other sender thread(s) be able - * to send another request right away */ + // The event has been registered, kick the condition to let other sender thread(s) be able + // to send another request right away command_binary_synchronizer.command_type = SECURITY_COMMAND_NONE; pthread_cond_signal(&command_binary_synchronizer.command_in_process_condition); } diff --git a/security/private/thread/command_synchronizer.h b/security/private/thread/command_synchronizer.h index 7bfd90b..36bdced 100644 --- a/security/private/thread/command_synchronizer.h +++ b/security/private/thread/command_synchronizer.h @@ -20,10 +20,8 @@ #include "security/security.h" -void security_post_command(sl_cpc_security_command_t command); - sl_cpc_security_command_t security_wait_for_command(void); void security_flush_pending_commands(void); -#endif //SECURITY_COMMAND_SYNCHRONIZER_H +#endif // SECURITY_COMMAND_SYNCHRONIZER_H diff --git a/security/private/thread/security_thread.c b/security/private/thread/security_thread.c index c6a6589..a4d79cf 100644 --- a/security/private/thread/security_thread.c +++ b/security/private/thread/security_thread.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include @@ -30,7 +32,7 @@ #include "security/security.h" #include "sl_cpc.h" -/* Library handles */ +// Library handles static cpc_handle_t lib_handle; cpc_endpoint_t security_ep; @@ -52,13 +54,13 @@ void* security_thread_func(void* param) security_keys_init(); - /* The server can take time to be up; try to to load the key first - * to crash early if its bad. */ + // The server can take time to be up; try to to load the key first + // to crash early if its bad. if (config.operation_mode != MODE_BINDING_ECDH && config.operation_mode != MODE_BINDING_UNBIND) { security_load_binding_key_from_file(); } - /* Block until the server is up and running */ + // Block until the server is up and running server_ready_wait(); ret = cpc_init(&lib_handle, config.instance_name, false, NULL); @@ -74,7 +76,7 @@ void* security_thread_func(void* param) while (1) { sl_cpc_security_command_t command = security_wait_for_command(); - /* An event request is pending, act on it */ + // An event request is pending, act on it switch (command) { case SECURITY_COMMAND_NONE: WARN("SECURITY_EVENT_NONE has no effect"); diff --git a/security/private/thread/security_thread.h b/security/private/thread/security_thread.h index f2449e9..05523c1 100644 --- a/security/private/thread/security_thread.h +++ b/security/private/thread/security_thread.h @@ -28,4 +28,4 @@ extern bool security_initialized; void* security_thread_func(void* param); -#endif //SECURITY_THREAD_H +#endif // SECURITY_THREAD_H diff --git a/security/security.c b/security/security.c index 42213bd..576ef2a 100644 --- a/security/security.c +++ b/security/security.c @@ -15,7 +15,8 @@ * ******************************************************************************/ -#define _GNU_SOURCE +#include "config.h" + #include #include "cpcd/config.h" diff --git a/server_core/core/buffer.c b/server_core/core/buffer.c index 243b42b..e0b2fb0 100644 --- a/server_core/core/buffer.c +++ b/server_core/core/buffer.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -42,7 +44,7 @@ struct sl_cpc_transmit_queue_item { ******************************************************************************/ sl_cpc_buffer_handle_t* buffer_new(sl_cpc_endpoint_t *ep, const uint8_t ep_id, - const void *data, + const uint8_t *data, const size_t data_len, const uint8_t control) { @@ -58,16 +60,12 @@ sl_cpc_buffer_handle_t* buffer_new(sl_cpc_endpoint_t *ep, buffer->control = control; if ((data != NULL) && (data_len > 0)) { - uint16_t fcs; - FATAL_ON(data_len > UINT16_MAX); buffer->data = data; buffer->data_length = (uint16_t)data_len; - fcs = sli_cpc_get_crc_sw(buffer->data, buffer->data_length); - buffer->fcs[0] = (uint8_t)fcs; - buffer->fcs[1] = (uint8_t)(fcs >> 8); + buffer->fcs = sli_cpc_get_crc_sw(buffer->data, buffer->data_length); } // explicitely set ref_cnt to 0, even though diff --git a/server_core/core/buffer.h b/server_core/core/buffer.h index 136befa..d6e7895 100644 --- a/server_core/core/buffer.h +++ b/server_core/core/buffer.h @@ -25,10 +25,10 @@ #include "cpcd/sl_slist.h" typedef struct { - void *hdlc_header; - const void *data; + uint8_t *hdlc_header; + const uint8_t *data; uint16_t data_length; - uint8_t fcs[2]; + uint16_t fcs; uint8_t control; uint8_t address; uint8_t ref_cnt; @@ -45,7 +45,7 @@ typedef struct sl_cpc_transmit_queue_item sl_cpc_transmit_queue_item_t; sl_cpc_buffer_handle_t* buffer_new(sl_cpc_endpoint_t *ep, const uint8_t ep_id, - const void *data, + const uint8_t *data, const size_t data_len, const uint8_t control); diff --git a/server_core/core/core.c b/server_core/core/core.c index 804b227..0b454b6 100644 --- a/server_core/core/core.c +++ b/server_core/core/core.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -106,7 +108,7 @@ static void core_process_rx_i_frame(frame_t *rx_frame); static void core_process_rx_s_frame(frame_t *rx_frame); static void core_process_rx_u_frame(frame_t *rx_frame); -/* CPC core functions */ +// CPC core functions static bool core_process_tx_queue(void); static void process_ack(sl_cpc_endpoint_t *endpoint, uint8_t ack); static void transmit_ack(sl_cpc_endpoint_t *endpoint); @@ -116,11 +118,11 @@ static sl_cpc_endpoint_t* find_endpoint(uint8_t endpoint_number); static void transmit_reject(sl_cpc_endpoint_t *endpoint, uint8_t address, uint8_t ack, sl_cpc_reject_reason_t reason); static bool is_endpoint_connection_active(const sl_cpc_endpoint_t *ep); -/* Functions to operate on linux fd timers */ +// Functions to operate on linux fd timers static void stop_re_transmit_timer(sl_cpc_endpoint_t* endpoint); static void start_re_transmit_timer(sl_cpc_endpoint_t* endpoint, struct timespec offset); -/* Functions to communicate with the driver and server */ +// Functions to communicate with the driver and server static void core_push_frame_to_driver(const void *frame, size_t frame_len); static bool core_pull_frame_from_driver(frame_t** frame_buf, size_t* frame_buf_len); @@ -314,8 +316,8 @@ static void core_on_security_state_change(sl_cpc_security_state_t old, sl_cpc_se core_endpoints[i].frame_counter_tx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; core_endpoints[i].frame_counter_rx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; #if defined(UNIT_TESTING) - sli_cpc_drv_emul_set_frame_counter(i, SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE, true); - sli_cpc_drv_emul_set_frame_counter(i, SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE, false); + sli_cpc_drv_emul_set_frame_counter((uint8_t)i, SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE, true); + sli_cpc_drv_emul_set_frame_counter((uint8_t)i, SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE, false); #endif } } else if (new == SECURITY_STATE_INITIALIZING) { @@ -326,7 +328,7 @@ static void core_on_security_state_change(sl_cpc_security_state_t old, sl_cpc_se void core_init(int driver_fd, int driver_notify_fd) { - /* Init all endpoints */ + // Init all endpoints size_t i = 0; for (i = 0; i < SL_CPC_ENDPOINT_MAX_COUNT; i++) { core_endpoints[i].id = (uint8_t)i; @@ -352,9 +354,9 @@ void core_init(int driver_fd, int driver_notify_fd) security_register_state_change_callback(core_on_security_state_change); #endif - /* Setup epoll */ + // Setup epoll { - /* Setup the driver data socket */ + // Setup the driver data socket { driver_sock_private_data.callback = core_process_rx_driver; driver_sock_private_data.file_descriptor = driver_fd; @@ -363,17 +365,17 @@ void core_init(int driver_fd, int driver_notify_fd) epoll_register(&driver_sock_private_data); } - /* Setup the driver notification socket */ + // Setup the driver notification socket { driver_sock_notify_private_data.callback = core_process_rx_driver_notification; driver_sock_notify_private_data.file_descriptor = driver_notify_fd; - driver_sock_notify_private_data.endpoint_number = 0; /* Irrelevant here */ + driver_sock_notify_private_data.endpoint_number = 0; // Irrelevant here epoll_register(&driver_sock_notify_private_data); } } - /* Setup timer to fetch secondary debug counter */ + // Setup timer to fetch secondary debug counter if (config.stats_interval > 0) { stats_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); FATAL_SYSCALL_ON(stats_timer_fd < 0); @@ -388,7 +390,7 @@ void core_init(int driver_fd, int driver_notify_fd) FATAL_SYSCALL_ON(ret < 0); - /* Setup epoll */ + // Setup epoll { epoll_private_data_t* private_data = (epoll_private_data_t*) zalloc(sizeof(epoll_private_data_t)); FATAL_SYSCALL_ON(private_data == NULL); @@ -405,7 +407,7 @@ void core_init(int driver_fd, int driver_notify_fd) void core_process_transmit_queue(void) { - /* Flush the transmit queue */ + // Flush the transmit queue while (transmit_queue != NULL || pending_on_security_ready_queue != NULL) { if (!core_process_tx_queue()) { break; @@ -447,6 +449,7 @@ static void core_update_secondary_debug_counter(sli_cpc_property_id_t property_i void *user_data, sl_status_t status) { + const uint8_t *property_data; (void)user_data; if (status == SL_STATUS_TIMEOUT) { @@ -467,57 +470,58 @@ static void core_update_secondary_debug_counter(sli_cpc_property_id_t property_i FATAL_ON(property_id != PROP_CORE_DEBUG_COUNTERS); FATAL_ON(property_value == NULL || property_length > sizeof(core_debug_counters_t)); + property_data = (const uint8_t *)property_value; - secondary_core_debug_counters.endpoint_opened = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.endpoint_opened); + secondary_core_debug_counters.endpoint_opened = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.endpoint_opened); - secondary_core_debug_counters.endpoint_closed = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.endpoint_closed); + secondary_core_debug_counters.endpoint_closed = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.endpoint_closed); - secondary_core_debug_counters.rxd_frame = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.rxd_frame); + secondary_core_debug_counters.rxd_frame = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.rxd_frame); - secondary_core_debug_counters.rxd_valid_iframe = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.rxd_valid_iframe); + secondary_core_debug_counters.rxd_valid_iframe = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.rxd_valid_iframe); - secondary_core_debug_counters.rxd_valid_uframe = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.rxd_valid_uframe); + secondary_core_debug_counters.rxd_valid_uframe = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.rxd_valid_uframe); - secondary_core_debug_counters.rxd_valid_sframe = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.rxd_valid_sframe); + secondary_core_debug_counters.rxd_valid_sframe = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.rxd_valid_sframe); - secondary_core_debug_counters.rxd_data_frame_dropped = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.rxd_data_frame_dropped); + secondary_core_debug_counters.rxd_data_frame_dropped = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.rxd_data_frame_dropped); - secondary_core_debug_counters.txd_reject_destination_unreachable = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.txd_reject_destination_unreachable); + secondary_core_debug_counters.txd_reject_destination_unreachable = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.txd_reject_destination_unreachable); - secondary_core_debug_counters.txd_reject_error_fault = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.txd_reject_error_fault); + secondary_core_debug_counters.txd_reject_error_fault = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.txd_reject_error_fault); - secondary_core_debug_counters.txd_completed = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.txd_completed); + secondary_core_debug_counters.txd_completed = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.txd_completed); - secondary_core_debug_counters.retxd_data_frame = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.retxd_data_frame); + secondary_core_debug_counters.retxd_data_frame = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.retxd_data_frame); - secondary_core_debug_counters.driver_error = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.driver_error); + secondary_core_debug_counters.driver_error = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.driver_error); - secondary_core_debug_counters.driver_packet_dropped = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.driver_packet_dropped); + secondary_core_debug_counters.driver_packet_dropped = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.driver_packet_dropped); - secondary_core_debug_counters.invalid_header_checksum = u32_from_le((const uint8_t *)property_value); - property_value = property_value + sizeof(secondary_core_debug_counters.invalid_header_checksum); + secondary_core_debug_counters.invalid_header_checksum = u32_from_le(property_data); + property_data += sizeof(secondary_core_debug_counters.invalid_header_checksum); - secondary_core_debug_counters.invalid_payload_checksum = u32_from_le((const uint8_t *)property_value); + secondary_core_debug_counters.invalid_payload_checksum = u32_from_le(property_data); } static void core_fetch_secondary_debug_counters(epoll_private_data_t *event_private_data) { int fd_timer = event_private_data->file_descriptor; - /* Ack the timer */ + // Ack the timer { uint64_t expiration; ssize_t ret; @@ -547,7 +551,7 @@ static void core_process_rx_driver_notification(epoll_private_data_t *event_priv sizeof(tx_complete_timestamp), MSG_DONTWAIT); - /* Socket closed */ + // Socket closed if (ret == 0 || (ret < 0 && errno == ECONNRESET)) { TRACE_CORE("Driver closed the notification socket"); epoll_unregister(&driver_sock_notify_private_data); @@ -585,14 +589,14 @@ static void core_process_rx_driver(epoll_private_data_t *event_private_data) frame_t *rx_frame; size_t frame_size; - /* The driver unblocked, read the frame. Frames from the driver are complete */ + // The driver unblocked, read the frame. Frames from the driver are complete if (core_pull_frame_from_driver(&rx_frame, &frame_size) == false) { return; } TRACE_CORE_RXD_FRAME(rx_frame, frame_size); - /* Validate header checksum */ + // Validate header checksum { uint16_t hcs = hdlc_get_hcs(rx_frame->header); @@ -609,7 +613,7 @@ static void core_process_rx_driver(epoll_private_data_t *event_private_data) uint8_t type = hdlc_get_frame_type(control); uint8_t ack = hdlc_get_ack(control); - /* Make sure the length from the header matches the length reported by the driver*/ + // Make sure the length from the header matches the length reported by the driver BUG_ON(data_length != frame_size - SLI_CPC_HDLC_HEADER_RAW_SIZE); sl_cpc_endpoint_t* endpoint = find_endpoint(address); @@ -625,7 +629,7 @@ static void core_process_rx_driver(epoll_private_data_t *event_private_data) } } - /* If endpoint is closed , reject the frame and return unless the frame itself is a reject, if so ignore it */ + // If endpoint is closed , reject the frame and return unless the frame itself is a reject, if so ignore it if (!is_endpoint_connection_active(endpoint) || (endpoint->state == SLI_CPC_STATE_REMOTE_SHUTDOWN && type != SLI_CPC_HDLC_FRAME_TYPE_SUPERVISORY)) { @@ -636,7 +640,7 @@ static void core_process_rx_driver(epoll_private_data_t *event_private_data) return; } - /* For data and supervisory frames, process the ack right away */ + // For data and supervisory frames, process the ack right away if (type == SLI_CPC_HDLC_FRAME_TYPE_INFORMATION || type == SLI_CPC_HDLC_FRAME_TYPE_SUPERVISORY) { process_ack(endpoint, ack); } @@ -660,7 +664,7 @@ static void core_process_rx_driver(epoll_private_data_t *event_private_data) break; } - /* core_pull_frame_from_driver() malloced rx_frame */ + // core_pull_frame_from_driver() malloced rx_frame free(rx_frame); } @@ -669,6 +673,36 @@ bool core_ep_is_closing(uint8_t ep_id) return core_endpoints[ep_id].state == SLI_CPC_STATE_CLOSING; } +#if defined(ENABLE_ENCRYPTION) +static void on_set_security_counters_reply(sl_cpc_endpoint_t *ep, + sl_status_t status, + void *ctx) +{ + uint8_t tx_window_size = (uint8_t)((uintptr_t)ctx); + + if (status == SL_STATUS_NOT_SUPPORTED) { + ep->frame_counter_rx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; + ep->frame_counter_tx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; + + status = SL_STATUS_OK; + } + + if (status == SL_STATUS_OK) { + core_connect_endpoint(ep->id, 0, tx_window_size, true); + } else { + server_connect_endpoint(ep->id, true); + } +} + +static void core_set_remote_security_counters(sl_cpc_endpoint_t *ep, uint8_t tx_window_size) +{ + FATAL_ON(protocol == NULL); + protocol->set_security_counters(ep, + on_set_security_counters_reply, + (void*)((uintptr_t)tx_window_size)); +} +#endif + static void on_get_encryption_reply(sl_cpc_endpoint_t *ep, sl_status_t status, bool encrypted, void *ctx) { uint8_t tx_window_size = (uint8_t)((uintptr_t)ctx); @@ -676,7 +710,16 @@ static void on_get_encryption_reply(sl_cpc_endpoint_t *ep, sl_status_t status, b if (status != SL_STATUS_OK) { server_connect_endpoint(ep->id, true); } else { - core_connect_endpoint(ep->id, 0, tx_window_size, encrypted); + if (encrypted) { +#if defined(ENABLE_ENCRYPTION) + core_set_remote_security_counters(ep, tx_window_size); +#else + // we should never end up, but handle it for completeness + FATAL("CPCd built without encryption support"); +#endif + } else { + core_connect_endpoint(ep->id, 0, tx_window_size, encrypted); + } } } @@ -836,14 +879,14 @@ static void core_process_rx_i_frame(frame_t *rx_frame) return; } - /* Prevent -2 on a zero length */ + // Prevent -2 on a zero length BUG_ON(hdlc_get_length(rx_frame->header) < SLI_CPC_HDLC_FCS_SIZE); uint16_t rx_frame_payload_length = (uint16_t) (hdlc_get_length(rx_frame->header) - SLI_CPC_HDLC_FCS_SIZE); uint16_t fcs = hdlc_get_fcs(rx_frame->payload, rx_frame_payload_length); - /* Validate payload checksum. In case it is invalid, NAK the packet. */ + // Validate payload checksum. In case it is invalid, NAK the packet. if (!sli_cpc_validate_crc_sw(rx_frame->payload, rx_frame_payload_length, fcs)) { transmit_reject(endpoint, address, endpoint->ack, HDLC_REJECT_CHECKSUM_MISMATCH); TRACE_CORE_INVALID_PAYLOAD_CHECKSUM(); @@ -861,7 +904,7 @@ static void core_process_rx_i_frame(frame_t *rx_frame) uint8_t *output; sl_status_t status; - /* the payload buffer must be longer than the security tag */ + // the payload buffer must be longer than the security tag BUG_ON(rx_frame_payload_length < tag_len); rx_frame_payload_length = (uint16_t)(rx_frame_payload_length - tag_len); @@ -1144,16 +1187,16 @@ int core_write(uint8_t endpoint_number, const void* message, size_t message_len, endpoint = find_endpoint(endpoint_number); - /* Sanity checks */ + // Sanity checks { - /* Make sure the endpoint it opened */ + // Make sure the endpoint it opened if (endpoint->state != SLI_CPC_STATE_CONNECTED && endpoint->state != SLI_CPC_STATE_REMOTE_SHUTDOWN) { WARN("Tried to write on closed endpoint #%d", endpoint_number); return -1; } - /* if u-frame, make sure they are enabled */ + // if u-frame, make sure they are enabled if ((flags & SL_CPC_FLAG_UNNUMBERED_INFORMATION) || (flags & SL_CPC_FLAG_UNNUMBERED_RESET_COMMAND) || (flags & SL_CPC_FLAG_UNNUMBERED_POLL)) { FATAL_ON(!(endpoint->flags & SL_CPC_OPEN_ENDPOINT_FLAG_UFRAME_ENABLE)); @@ -1167,13 +1210,13 @@ int core_write(uint8_t endpoint_number, const void* message, size_t message_len, type = SLI_CPC_HDLC_CONTROL_UNNUMBERED_TYPE_POLL_FINAL; } } - /* if I-frame, make sure they are not disabled */ + // if I-frame, make sure they are not disabled else { FATAL_ON(endpoint->flags & SL_CPC_OPEN_ENDPOINT_FLAG_IFRAME_DISABLE); } } - /* Fill the buffer handle */ + // Fill the buffer handle { uint8_t control; @@ -1227,15 +1270,19 @@ int core_write(uint8_t endpoint_number, const void* message, size_t message_len, ******************************************************************************/ void core_connect_endpoint(uint8_t endpoint_number, uint8_t flags, uint8_t tx_window_size, bool encryption) { - sl_cpc_endpoint_t *ep; sli_cpc_endpoint_state_t previous_state; + sl_cpc_endpoint_t *ep; +#if defined(ENABLE_ENCRYPTION) + uint32_t rx_counter; + uint32_t tx_counter; +#endif FATAL_ON(tx_window_size < TRANSMIT_WINDOW_MIN_SIZE); FATAL_ON(tx_window_size > TRANSMIT_WINDOW_MAX_SIZE); ep = &core_endpoints[endpoint_number]; - /* Check if endpoint was already opened */ + // Check if endpoint was already opened if (ep->state != SLI_CPC_STATE_CLOSED) { BUG("Endpoint already opened, current state=%s, expected=%s", core_stringify_state(ep->state), @@ -1243,8 +1290,12 @@ void core_connect_endpoint(uint8_t endpoint_number, uint8_t flags, uint8_t tx_wi return; } - /* Keep the previous state to log the transition */ + // Keep the previous state to log the transition previous_state = ep->state; +#if defined(ENABLE_ENCRYPTION) + rx_counter = ep->frame_counter_rx; + tx_counter = ep->frame_counter_tx; +#endif memset(ep, 0x00, sizeof(sl_cpc_endpoint_t)); ep->state = previous_state; if (endpoint_number == SL_CPC_ENDPOINT_SYSTEM) { @@ -1260,8 +1311,15 @@ void core_connect_endpoint(uint8_t endpoint_number, uint8_t flags, uint8_t tx_wi ep->re_transmit_timeout_ms = SL_CPC_MAX_RE_TRANSMIT_TIMEOUT_MS; #if defined(ENABLE_ENCRYPTION) ep->encrypted = encryption; - ep->frame_counter_tx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; - ep->frame_counter_rx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; + + if (endpoint_number == SL_CPC_ENDPOINT_SYSTEM) { + // do not reset frame counters values, except for the system endpoint + ep->frame_counter_tx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; + ep->frame_counter_rx = SLI_CPC_SECURITY_NONCE_FRAME_COUNTER_RESET_VALUE; + } else { + ep->frame_counter_rx = rx_counter; + ep->frame_counter_tx = tx_counter; + } #else (void)encryption; #endif @@ -1269,7 +1327,7 @@ void core_connect_endpoint(uint8_t endpoint_number, uint8_t flags, uint8_t tx_wi int timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); FATAL_SYSCALL_ON(timer_fd < 0); - /* Setup epoll */ + // Setup epoll { epoll_private_data_t* private_data = (epoll_private_data_t*) zalloc(sizeof(epoll_private_data_t)); FATAL_SYSCALL_ON(private_data == NULL); @@ -1333,6 +1391,26 @@ sl_status_t core_close_endpoint(uint8_t endpoint_number, bool notify_secondary, BUG_ON(ep->state == SLI_CPC_STATE_CLOSED); + if (ep->state == SLI_CPC_STATE_REMOTE_SHUTDOWN + && notify_secondary && !force_close + && !ep->closed_by_server + && endpoint_number != SL_CPC_ENDPOINT_SECURITY + && (ep->re_transmit_queue != NULL || ep->holding_list != NULL)) { + // we end up here because a remote shutdown was received, the data socket + // was then shutdown() to prevent the user from sending more data. When the + // last packet is read from the socket, the next read returns EOF and the + // tear down sequence is called from the server, ultimately closing the + // core endpoint. But the last packet was just sent on the wire and not + // ack'd yet, so it might be missed by the remote device, meaning + // ep->re_transmit_queue still contain the un-ack'd packet. + + ep->closed_by_server = true; + + TRACE_CORE("Deferring close for endpoint #%d, still has unacknowledged packets", endpoint_number); + + return SL_STATUS_OK; + } + TRACE_CORE("Closing endpoint #%d", endpoint_number); stop_re_transmit_timer(ep); @@ -1536,6 +1614,13 @@ static void process_ack(sl_cpc_endpoint_t *endpoint, uint8_t ack) epoll_watch_back(endpoint->id); } + if (endpoint->state == SLI_CPC_STATE_REMOTE_SHUTDOWN + && endpoint->closed_by_server + && endpoint->re_transmit_queue == NULL + && endpoint->holding_list == NULL) { + core_close_endpoint(endpoint->id, true, false); + } + TRACE_ENDPOINT_RXD_ACK(endpoint, ack); } @@ -1719,10 +1804,10 @@ static bool core_process_tx_queue(void) #if defined(ENABLE_ENCRYPTION) uint16_t security_buffer_size = 0; if (encrypt) { - /* add up a few extra bytes to store security tag */ + // add up a few extra bytes to store security tag security_buffer_size = (uint16_t)security_encrypt_get_extra_buffer_size(); - /* bug if the sum is going to overflow */ + // bug if the sum is going to overflow BUG_ON(total_length > UINT16_MAX - security_buffer_size); total_length = (uint16_t)(total_length + security_buffer_size); } @@ -1730,8 +1815,8 @@ static bool core_process_tx_queue(void) BUG_ON(encrypt); #endif - /* create header after checking if the frame must be encrypted or not - * as it has an impact on the total size of the payload, and the fcs */ + // create header after checking if the frame must be encrypted or not + // as it has an impact on the total size of the payload, and the fcs hdlc_create_header(frame->hdlc_header, frame->address, total_length, frame->control, true); uint16_t encrypted_data_length = frame->data_length; @@ -1744,35 +1829,28 @@ static bool core_process_tx_queue(void) if (encrypt) { uint8_t *security_offset; - uint16_t fcs; sl_status_t encrypt_status; - /* - * encrypted_data_length is size of encrypted payload + size of security tag. - * This operation should be safe to cast to uint16_t as it was already checked - * earlier that the following sum doesn't overflow: - * total_length + security_buffer_size - * - * And total_length is frame->data_length + 2 bytes for the FCS. - * So if the first operation doesn't overflow, this one won't as it's - * two-byte shorter. - */ + // encrypted_data_length is size of encrypted payload + size of security tag. + // This operation should be safe to cast to uint16_t as it was already checked + // earlier that the following sum doesn't overflow: + // total_length + security_buffer_size + // + // And total_length is frame->data_length + 2 bytes for the FCS. + // So if the first operation doesn't overflow, this one won't as it's + // two-byte shorter. encrypted_data_length = (uint16_t)(frame->data_length + security_buffer_size); - /* allocate buffer and make sure it succeeded */ + // allocate buffer and make sure it succeeded encrypted_payload = (uint8_t*)zalloc(encrypted_data_length); FATAL_ON(encrypted_payload == NULL); - /* - * compute offset at which security tag must be stored. It should be right - * after the encrypted payload. - */ + // compute offset at which security tag must be stored. It should be right + // after the encrypted payload. security_offset = &encrypted_payload[frame->data_length]; - /* - * 'ack' in the control field of the header should be always set to 0 - * as it's not part of the authenticated data - */ + // 'ack' in the control field of the header should be always set to 0 + // as it's not part of the authenticated data uint8_t ack = hdlc_get_ack(hdlc_get_control(frame->hdlc_header)); hdlc_set_control_ack(&((uint8_t*)frame->hdlc_header)[SLI_CPC_HDLC_CONTROL_POS], 0); @@ -1782,9 +1860,7 @@ static bool core_process_tx_queue(void) encrypted_payload, security_offset, security_buffer_size); - /* - * restore 'ack' to its value - */ + // restore 'ack' to its value hdlc_set_control_ack(&((uint8_t*)frame->hdlc_header)[SLI_CPC_HDLC_CONTROL_POS], ack); if (encrypt_status != SL_STATUS_OK) { @@ -1799,15 +1875,13 @@ static bool core_process_tx_queue(void) security_session_last_packet_acked = false; } - fcs = sli_cpc_get_crc_sw(encrypted_payload, (uint16_t)encrypted_data_length); - frame->fcs[0] = (uint8_t)fcs; - frame->fcs[1] = (uint8_t)(fcs >> 8); + frame->fcs = sli_cpc_get_crc_sw(encrypted_payload, (uint16_t)encrypted_data_length); } #else BUG_ON(encrypt); #endif - /* Construct and send the frame to the driver */ + // Construct and send the frame to the driver { // total_length takes into account FCS and security tag size_t frame_length = SLI_CPC_HDLC_HEADER_RAW_SIZE + total_length; @@ -1815,21 +1889,21 @@ static bool core_process_tx_queue(void) frame_t* frame_buffer = (frame_t*) zalloc(frame_length); FATAL_ON(frame_buffer == NULL); - /* copy the header */ + // copy the header memcpy(frame_buffer->header, frame->hdlc_header, SLI_CPC_HDLC_HEADER_RAW_SIZE); if (encrypted_data_length > 0) { - /* copy the payload */ + // copy the payload memcpy(frame_buffer->payload, encrypted_payload, encrypted_data_length); - memcpy(&frame_buffer->payload[encrypted_data_length], frame->fcs, sizeof(frame->fcs)); + u16_to_le(frame->fcs, &frame_buffer->payload[encrypted_data_length]); } buffer_list_push_back_item(item, &pending_on_tx_complete); core_push_frame_to_driver(frame_buffer, frame_length); if (frame->data != encrypted_payload) { - /* in case a buffer was allocated for allocation, free it */ + // in case a buffer was allocated for allocation, free it free((void*)encrypted_payload); } @@ -1862,7 +1936,7 @@ static void re_transmit_timeout(sl_cpc_endpoint_t* endpoint) endpoint->re_transmit_timeout_ms = SL_CPC_MAX_RE_TRANSMIT_TIMEOUT_MS; } - TRACE_CORE("New RTO calculated on ep %d, after re_transmit timeout: %ldms", endpoint->id, endpoint->re_transmit_timeout_ms); + TRACE_CORE("New RTO calculated on ep %d, after re_transmit timeout: %dms", endpoint->id, endpoint->re_transmit_timeout_ms); re_transmit_frame(endpoint); } @@ -1907,15 +1981,13 @@ bool should_encrypt_frame(sl_cpc_buffer_handle_t *frame) #if defined(ENABLE_ENCRYPTION) static bool should_decrypt_frame(sl_cpc_endpoint_t *endpoint, uint16_t payload_len) { - /* - * In normal mode of operation, security_state is set to INITIALIZED and - * packets are decrypted below if they have a non-zero length. When the - * security session is reset (for instance because the daemon sent a packet - * that triggered an overflow), the secondary can still reply with encrypted - * packets before it detects on its side that the security session should be - * reset. So if packets are received while the state is RESETTING, we should - * try to decrypt them. - */ + // In normal mode of operation, security_state is set to INITIALIZED and + // packets are decrypted below if they have a non-zero length. When the + // security session is reset (for instance because the daemon sent a packet + // that triggered an overflow), the secondary can still reply with encrypted + // packets before it detects on its side that the security session should be + // reset. So if packets are received while the state is RESETTING, we should + // try to decrypt them. sl_cpc_security_state_t security_state = security_get_state(); if ((security_state != SECURITY_STATE_INITIALIZED @@ -1998,6 +2070,7 @@ void core_reset_endpoint(uint8_t endpoint_number) ep->current_tx_window_space = ep->configured_tx_window_size; } +#if defined(ENABLE_ENCRYPTION) uint32_t core_endpoint_get_frame_counter(uint8_t endpoint_number, bool tx) { sl_cpc_endpoint_t *ep = &core_endpoints[endpoint_number]; @@ -2021,6 +2094,8 @@ void core_endpoint_set_frame_counter(uint8_t endpoint_number, uint32_t new_value } #endif +#endif + /***************************************************************************//** * Stops the re-transmit timer for a given endpoint ******************************************************************************/ @@ -2029,7 +2104,7 @@ static void stop_re_transmit_timer(sl_cpc_endpoint_t* endpoint) int ret; epoll_private_data_t* fd_timer_private_data; - /* Passing itimerspec with it_value of 0 stops the timer. */ + // Passing itimerspec with it_value of 0 stops the timer. const struct itimerspec cancel_time = { .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, .it_value = { .tv_sec = 0, .tv_nsec = 0 } }; @@ -2080,7 +2155,7 @@ static void start_re_transmit_timer(sl_cpc_endpoint_t* endpoint, struct timespec // and an endpoint closed right after. } - /* Make sure the timer file descriptor is open*/ + // Make sure the timer file descriptor is open FATAL_ON(fd_timer_private_data == NULL); FATAL_ON(fd_timer_private_data->file_descriptor < 0); @@ -2104,7 +2179,7 @@ static void core_process_ep_timeout(epoll_private_data_t *event_private_data) int fd_timer = event_private_data->file_descriptor; uint8_t endpoint_number = event_private_data->endpoint_number; - /* Ack the timer */ + // Ack the timer { uint64_t expiration; ssize_t ret; @@ -2112,7 +2187,7 @@ static void core_process_ep_timeout(epoll_private_data_t *event_private_data) ret = read(fd_timer, &expiration, sizeof(expiration)); FATAL_ON(ret < 0); - /* we missed a timeout*/ + // we missed a timeout WARN_ON(expiration != 1); } @@ -2135,7 +2210,7 @@ static void core_push_frame_to_driver(const void *frame, size_t frame_len) ssize_t ret = send(driver_sock_private_data.file_descriptor, frame, frame_len, 0); - /* Socket closed */ + // Socket closed if (ret < 0 && (errno == ECONNRESET || errno == EPIPE)) { TRACE_CORE("Driver closed the data socket"); epoll_unregister(&driver_sock_private_data); @@ -2164,8 +2239,9 @@ static void core_push_frame_to_driver(const void *frame, size_t frame_len) static bool core_pull_frame_from_driver(frame_t** frame_buf, size_t* frame_buf_len) { size_t datagram_length; + int ret_close; - /* Poll the socket to get the next pending datagram size */ + // Poll the socket to get the next pending datagram size { if (driver_sock_private_data.file_descriptor < 1) { TRACE_CORE("Core already closed the data socket"); @@ -2174,45 +2250,56 @@ static bool core_pull_frame_from_driver(frame_t** frame_buf, size_t* frame_buf_l ssize_t retval = recv(driver_sock_private_data.file_descriptor, NULL, 0, MSG_PEEK | MSG_TRUNC | MSG_DONTWAIT); - /* Socket closed */ + // Detect if recv failed due to driver socket being closed if (retval == 0 || (retval < 0 && (errno == ECONNRESET || errno == EPIPE))) { - TRACE_CORE("Driver closed the data socket"); - epoll_unregister(&driver_sock_private_data); - int ret_close = close(driver_sock_private_data.file_descriptor); - FATAL_SYSCALL_ON(ret_close != 0); - driver_sock_private_data.file_descriptor = -1; - return false; + goto driver_socket_closed; } FATAL_SYSCALL_ON(retval < 0); - /* The socket had no data. This function is intended to be called - * when we know the socket has data. */ + // The socket had no data. This function is intended to be called + // when we know the socket has data. datagram_length = (size_t)retval; BUG_ON(datagram_length == 0); - /* The length of the frame should be at minimum a header length */ + // The length of the frame should be at minimum a header length BUG_ON(datagram_length < sizeof(frame_t)); } - /* Allocate a buffer of the right size */ + // Allocate a buffer of the right size { *frame_buf = (frame_t*) zalloc((size_t)datagram_length); FATAL_SYSCALL_ON(*frame_buf == NULL); } - /* Fetch the datagram from the driver socket */ + // Fetch the datagram from the driver socket { ssize_t ret = recv(driver_sock_private_data.file_descriptor, *frame_buf, (size_t)datagram_length, 0); + // Detect if recv failed due to driver socket being closed + if (ret == 0 || (ret < 0 && (errno == ECONNRESET || errno == EPIPE))) { + free(*frame_buf); + goto driver_socket_closed; + } + FATAL_SYSCALL_ON(ret < 0); - /* The next pending datagram size should be equal to what we just read */ + // The next pending datagram size should be equal to what we just read FATAL_ON((size_t)ret != (size_t)datagram_length); } *frame_buf_len = (size_t)datagram_length; return true; + + driver_socket_closed: + + TRACE_CORE("Driver closed the data socket"); + epoll_unregister(&driver_sock_private_data); + ret_close = close(driver_sock_private_data.file_descriptor); + FATAL_SYSCALL_ON(ret_close != 0); + driver_sock_private_data.file_descriptor = -1; + + return false; } /***************************************************************************//** diff --git a/server_core/core/core.h b/server_core/core/core.h index b900427..1f0d63c 100644 --- a/server_core/core/core.h +++ b/server_core/core/core.h @@ -59,9 +59,11 @@ void on_write_completed(uint8_t id, sl_status_t status); void cpc_unity_test_read_rx_callback(uint8_t endpoint_id); void core_reset_endpoint(uint8_t endpoint_number); +#if defined(ENABLE_ENCRYPTION) uint32_t core_endpoint_get_frame_counter(uint8_t endpoint_number, bool tx); void core_endpoint_set_frame_counter(uint8_t endpoint_number, uint32_t new_value, bool tx); #endif +#endif void core_reset_endpoint_sequence(uint8_t endpoint_number); @@ -108,17 +110,16 @@ void core_on_unsolicited_endpoint_state(const uint8_t endpoint_id, // ----------------------------------------------------------------------------- // Data Types -/* 1-byte aligned - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | header[7] | | - * +-+-+-+-+-+-+-+ : - * | payload | - * : : - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ +// 1-byte aligned +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | header[7] | | +// +-+-+-+-+-+-+-+ : +// | payload | +// : : +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ typedef struct { uint8_t header[SLI_CPC_HDLC_HEADER_RAW_SIZE]; uint8_t payload[]; // last two bytes are little endian 16bits diff --git a/server_core/core/crc.c b/server_core/core/crc.c index b1f88b1..2a47b3f 100644 --- a/server_core/core/crc.c +++ b/server_core/core/crc.c @@ -15,29 +15,68 @@ * ******************************************************************************/ +#include "config.h" + #include "crc.h" -static uint16_t sli_cpc_compute_crc16(uint8_t new_byte, uint16_t prev_result); +static const uint16_t crc16_xmodem_lut[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +static inline uint16_t sli_cpc_compute_crc16(uint16_t crc, const uint8_t data) +{ + return (uint16_t) (crc << 8) ^ crc16_xmodem_lut[((crc >> 8) ^ data) & 0xff]; +} /***************************************************************************//** - * Computes CRC-16 CCITT (XMODEM) on given buffer. Software implementation. + * Computes CRC-16 XMODEM on given buffer. Software implementation. ******************************************************************************/ -uint16_t sli_cpc_get_crc_sw(const void* buffer, uint16_t buffer_length) +inline uint16_t sli_cpc_get_crc_sw(const uint8_t* buffer, uint16_t buffer_length) { - uint16_t i; uint16_t crc = 0; - for (i = 0; i < buffer_length; i++) { - crc = sli_cpc_compute_crc16((uint8_t)((uint8_t *)buffer)[i], crc); + while (buffer_length--) { + crc = sli_cpc_compute_crc16(crc, *buffer++); } return crc; } /***************************************************************************//** - * Validates CRC-16 CCITT (XMODEM) on given buffer. Software implementation. + * Validates CRC-16 XMODEM on given buffer. Software implementation. ******************************************************************************/ -bool sli_cpc_validate_crc_sw(const void* buffer, uint16_t buffer_length, uint16_t expected_crc) +bool sli_cpc_validate_crc_sw(const uint8_t* buffer, uint16_t buffer_length, uint16_t expected_crc) { uint16_t computed_crc; @@ -45,15 +84,3 @@ bool sli_cpc_validate_crc_sw(const void* buffer, uint16_t buffer_length, uint16_ return (computed_crc == expected_crc); } - -static uint16_t sli_cpc_compute_crc16(uint8_t new_byte, uint16_t prev_result) -{ - prev_result = ((uint16_t) (prev_result >> 8)) | ((uint16_t) (prev_result << 8)); - prev_result = (uint16_t)(prev_result ^ new_byte); - prev_result = (uint16_t) (prev_result ^ (prev_result & 0xff) >> 4); - prev_result ^= (uint16_t) (((uint16_t) (prev_result << 8)) << 4); - prev_result = (uint16_t) (prev_result ^ ( ((uint8_t) (((uint8_t) (prev_result & 0xff)) << 5)) - | ((uint16_t) ((uint16_t) ((uint8_t) (((uint8_t) (prev_result & 0xff)) >> 3)) << 8)))); - - return prev_result; -} diff --git a/server_core/core/crc.h b/server_core/core/crc.h index cd086ce..3f450dd 100644 --- a/server_core/core/crc.h +++ b/server_core/core/crc.h @@ -22,17 +22,17 @@ #include /***************************************************************************//** - * Computes CRC-16 CCITT on given buffer. Software implementation. + * Computes CRC-16 XMODEM on given buffer. Software implementation. * * @param buffer Pointer to the buffer on which the CRC must be computed. * @param buffer_length Length of the buffer, in bytes. * * @return CRC value. ******************************************************************************/ -uint16_t sli_cpc_get_crc_sw(const void* buffer, uint16_t buffer_length); +uint16_t sli_cpc_get_crc_sw(const uint8_t* buffer, uint16_t buffer_length); /***************************************************************************//** - * Validates CRC-16 CCITT on given buffer. Software implementation. + * Validates CRC-16 XMODEM on given buffer. Software implementation. * * @param buffer Pointer to the buffer on which the CRC must be computed. * @param buffer_length Length of the buffer, in bytes. @@ -40,6 +40,6 @@ uint16_t sli_cpc_get_crc_sw(const void* buffer, uint16_t buffer_length); * * @return true if CRC matches. False otherwise. ******************************************************************************/ -bool sli_cpc_validate_crc_sw(const void* buffer, uint16_t buffer_length, uint16_t expected_crc); +bool sli_cpc_validate_crc_sw(const uint8_t* buffer, uint16_t buffer_length, uint16_t expected_crc); -#endif //CRC_H +#endif // CRC_H diff --git a/server_core/core/hdlc.c b/server_core/core/hdlc.c index 77e3c44..32620ac 100644 --- a/server_core/core/hdlc.c +++ b/server_core/core/hdlc.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include "hdlc.h" #include "crc.h" diff --git a/server_core/core/hdlc.h b/server_core/core/hdlc.h index b7d4fe9..dcea45e 100644 --- a/server_core/core/hdlc.h +++ b/server_core/core/hdlc.h @@ -288,7 +288,7 @@ static inline uint8_t hdlc_create_control_unumbered(uint8_t type) { uint8_t control = SLI_CPC_HDLC_FRAME_TYPE_UNNUMBERED << SLI_CPC_HDLC_CONTROL_FRAME_TYPE_SHIFT; - control |= type << SLI_CPC_HDLC_CONTROL_UNNUMBERED_TYPE_SHIFT; + control |= (uint8_t)(type << SLI_CPC_HDLC_CONTROL_UNNUMBERED_TYPE_SHIFT); return control; } diff --git a/server_core/core/protocol.c b/server_core/core/protocol.c index 0b6f8f3..ce3bb3d 100644 --- a/server_core/core/protocol.c +++ b/server_core/core/protocol.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include "cpcd/logging.h" #include "cpcd/utils.h" @@ -40,6 +42,9 @@ static struct protocol_ops protocol_v5_ops = { .connect = connect_endpoint_v5, .disconnect = disconnect_endpoint_v5, .terminate = terminate_endpoint_v5, +#if defined(ENABLE_ENCRYPTION) + .set_security_counters = set_security_counters_v5, +#endif }; /***************************************************************************//** diff --git a/server_core/core/protocol.h b/server_core/core/protocol.h index 03fb844..9a177b5 100644 --- a/server_core/core/protocol.h +++ b/server_core/core/protocol.h @@ -37,6 +37,11 @@ typedef void (*on_disconnect_completion_t)(sl_cpc_endpoint_t *ep, sl_status_t st /// Called when a termine operation completes typedef void (*on_terminate_completion_t)(sl_cpc_endpoint_t *ep, sl_status_t status); +/// Called when setting the security counters completes +typedef void (*on_set_security_counters_completion_t)(sl_cpc_endpoint_t *ep, + sl_status_t status, + void *ctx); + /// @brief Struct for storing protocol operation structure struct protocol_ops { /// protocol version supported @@ -67,6 +72,12 @@ struct protocol_ops { /// terminate/close an endpoint void (*terminate)(sl_cpc_endpoint_t *ep, on_terminate_completion_t); + +#if defined(ENABLE_ENCRYPTION) + void (*set_security_counters)(sl_cpc_endpoint_t *ep, + on_set_security_counters_completion_t, + void *ctx); +#endif }; /***************************************************************************//** diff --git a/server_core/core/protocol_internal.h b/server_core/core/protocol_internal.h index 7162d4c..9f6b159 100644 --- a/server_core/core/protocol_internal.h +++ b/server_core/core/protocol_internal.h @@ -86,5 +86,10 @@ void disconnect_endpoint_v5(sl_cpc_endpoint_t *ep, on_disconnect_completion_t callback); void terminate_endpoint_v5(sl_cpc_endpoint_t *ep, on_terminate_completion_t callback); +#if defined(ENABLE_ENCRYPTION) +void set_security_counters_v5(sl_cpc_endpoint_t *ep, + on_set_security_counters_completion_t callback, + void *cb_data); +#endif #endif // CORE_PROTOCOL_INTERNAL_H diff --git a/server_core/core/protocol_v4.c b/server_core/core/protocol_v4.c index 88c593f..6fa7261 100644 --- a/server_core/core/protocol_v4.c +++ b/server_core/core/protocol_v4.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include "errno.h" #include "cpcd/logging.h" @@ -82,10 +84,10 @@ static void is_endpoint_opened_reply_v4(sli_cpc_property_id_t property_id, endpoint_id = PROPERTY_ID_TO_EP_ID(property_id); - /* Sanity checks */ + // Sanity checks { - /* This function's signature is for all properties get/set. Make sure we - * are dealing with PROP_ENDPOINT_STATE and with the correct property_length*/ + // This function's signature is for all properties get/set. Make sure we + // are dealing with PROP_ENDPOINT_STATE and with the correct property_length BUG_ON(property_id < PROP_ENDPOINT_STATE_1 || property_id > PROP_ENDPOINT_STATE_255); BUG_ON(endpoint_id != ctx->ep->id); @@ -228,8 +230,8 @@ static void on_connect_reply_v4(sli_cpc_property_id_t property_id, case SL_STATUS_IN_PROGRESS: case SL_STATUS_OK: if (property_length != 0) { - TRACE_CORE("Connection confirmation for ep#%d has invalid length (expected %d, got %d)", - ep_id, 0, property_length); + TRACE_CORE("Connection confirmation for ep#%d has invalid length (expected %d, got %zd)", + (int)ep_id, 0, property_length); callback(ctx->ep, SL_STATUS_INVALID_TYPE); break; } @@ -401,8 +403,8 @@ void connect_endpoint_v4(sl_cpc_endpoint_t *ep, &open_state, sizeof(open_state), ctx, - 0, /* unlimited retries */ - 100000, /* 100ms between retries*/ + 0, // unlimited retries + 100000, // 100ms between retries SYSTEM_EP_IFRAME); } @@ -427,7 +429,7 @@ void terminate_endpoint_v4(sl_cpc_endpoint_t *ep, &close_state, sizeof(close_state), ctx, - 1, /* 1 retry */ - 100000, /* 100ms between retries*/ + 1, // 1 retry + 100000, // 100ms between retries SYSTEM_EP_IFRAME); } diff --git a/server_core/core/protocol_v5.c b/server_core/core/protocol_v5.c index a20833e..c9efada 100644 --- a/server_core/core/protocol_v5.c +++ b/server_core/core/protocol_v5.c @@ -15,10 +15,14 @@ * ******************************************************************************/ +#include "config.h" + #include +#include "cpcd/endianness.h" #include "cpcd/logging.h" +#include "cpcd/sl_status.h" #include "server_core/system_endpoint/system.h" #include "protocol.h" @@ -100,10 +104,10 @@ static void is_endpoint_opened_reply_v5(sli_cpc_property_id_t property_id, endpoint_id = PROPERTY_ID_TO_EP_ID(property_id); - /* Sanity checks */ + // Sanity checks { - /* This function's signature is for all properties get/set. Make sure we - * are dealing with PROP_ENDPOINT_STATE and with the correct property_length*/ + // This function's signature is for all properties get/set. Make sure we + // are dealing with PROP_ENDPOINT_STATE and with the correct property_length BUG_ON(property_id < PROP_ENDPOINT_STATE_1 || property_id > PROP_ENDPOINT_STATE_255); BUG_ON(endpoint_id != ctx->ep->id); @@ -180,8 +184,8 @@ static void on_connect_reply_v5(sli_cpc_property_id_t property_id, case SL_STATUS_IN_PROGRESS: case SL_STATUS_OK: if (property_length != sizeof(sli_cpc_endpoint_state_v5_t)) { - TRACE_CORE("Connection confirmation for ep#%d has invalid length (expected %d, got %d)", - ep_id, sizeof(sli_cpc_endpoint_state_v5_t), property_length); + TRACE_CORE("Connection confirmation for ep#%d has invalid length (expected %zd, got %zd)", + (int)ep_id, sizeof(sli_cpc_endpoint_state_v5_t), property_length); callback(ctx->ep, SL_STATUS_INVALID_TYPE); break; } @@ -273,6 +277,7 @@ static void on_disconnect_reply_v5(sli_cpc_property_id_t property_id, protocol_free_callback_context(ctx); } + /***************************************************************************//** * Callback called when the response to a `terminate` is received. ******************************************************************************/ @@ -323,6 +328,79 @@ static void on_terminate_reply_v5(sli_cpc_property_id_t property_id, protocol_free_callback_context(ctx); } +#if defined(ENABLE_ENCRYPTION) +/***************************************************************************//** + * Callback called when the response to setting security counters is received. + ******************************************************************************/ +static void on_set_security_counters_reply_v5(sli_cpc_property_id_t property_id, + void *property_value, + size_t property_length, + void *user_arg, + sl_status_t status) +{ + struct protocol_callback_context *ctx = (struct protocol_callback_context*)user_arg; + on_set_security_counters_completion_t callback; + + FATAL_ON(ctx == NULL); + callback = (on_set_security_counters_completion_t)ctx->callback; + + switch (status) { + case SL_STATUS_IN_PROGRESS: + case SL_STATUS_OK: + if (property_id == PROP_LAST_STATUS) { + // case where the remote doesn't support updating the counters + sl_cpc_system_status_t system_status; + + // first of all, check the length + if (property_length != sizeof(sl_cpc_system_status_t)) { + status = SL_STATUS_INVALID_TYPE; + } else { + system_status = (sl_cpc_system_status_t) u32_from_le((uint8_t*)property_value); + + // this is the only case we're really interested in, if the + // remote doesn't support this command. In that case it should + // be handled in a special manner. Every other situation is an + // critical error. + if (system_status == STATUS_PROP_NOT_FOUND) { + status = SL_STATUS_NOT_SUPPORTED; + } else { + status = SL_STATUS_FAIL; + } + } + } else if (property_id >= PROP_ENDPOINT_ENCRYPTION + && property_id <= PROP_ENDPOINT_ENCRYPTION + 255) { + // case where remote supports the command + uint8_t ep_id = PROPERTY_ID_TO_EP_ID(property_id); + size_t expected_length; + + TRACE_CORE("Updated security counters for ep#%d", ep_id); + expected_length = 2 * sizeof(uint32_t); + + if (property_length == expected_length) { + status = SL_STATUS_OK; + } else { + status = SL_STATUS_INVALID_TYPE; + } + } else { + status = SL_STATUS_FAIL; + } + + break; + + case SL_STATUS_TIMEOUT: + case SL_STATUS_ABORT: + status = SL_STATUS_FAIL; + break; + default: + break; + } + + callback(ctx->ep, status, ctx->callback_data); + + protocol_free_callback_context(ctx); +} +#endif + /***************************************************************************//** * Convert bytestream to internal core state. ******************************************************************************/ @@ -412,8 +490,8 @@ void connect_endpoint_v5(sl_cpc_endpoint_t *ep, &connected_state, sizeof(connected_state), ctx, - 0, /* unlimited retries */ - 100000, /* 100ms between retries*/ + 0, // unlimited retries + 100000, // 100ms between retries SYSTEM_EP_IFRAME); } @@ -438,8 +516,8 @@ void disconnect_endpoint_v5(sl_cpc_endpoint_t *ep, &disconnected_state, sizeof(disconnected_state), ctx, - 0, /* unlimited retries */ - 100000, /* 100ms between retries*/ + 0, // unlimited retries + 100000, // 100ms between retries SYSTEM_EP_IFRAME); } @@ -464,7 +542,36 @@ void terminate_endpoint_v5(sl_cpc_endpoint_t *ep, &close_state, sizeof(close_state), ctx, - 1, /* 1 retry */ - 100000, /* 100ms between retries*/ + 1, // 1 retry + 250000, // 250ms to receive reply + SYSTEM_EP_IFRAME); +} + +#if defined(ENABLE_ENCRYPTION) +void set_security_counters_v5(sl_cpc_endpoint_t *ep, + on_set_security_counters_completion_t callback, + void *cb_data) +{ + struct protocol_callback_context *ctx; + uint8_t counters[2 * sizeof(uint32_t)]; + + ctx = protocol_new_callback_context(); + FATAL_ON(ctx == NULL); + + ctx->ep = ep; + ctx->callback = callback; + ctx->callback_data = cb_data; + + u32_to_le(ep->frame_counter_rx, &counters[0]); + u32_to_le(ep->frame_counter_tx, &counters[sizeof(uint32_t)]); + + sl_cpc_system_cmd_property_set(on_set_security_counters_reply_v5, + EP_ID_TO_PROPERTY_ENCRYPTION(ep->id), + counters, + sizeof(counters), + ctx, + 1, + 100000, SYSTEM_EP_IFRAME); } +#endif diff --git a/server_core/epoll/epoll.c b/server_core/epoll/epoll.c index 75932d5..42a174e 100644 --- a/server_core/epoll/epoll.c +++ b/server_core/epoll/epoll.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -32,14 +34,14 @@ typedef struct { struct epoll_private_data* unregistered_epoll_private_data; }unwatched_endpoint_list_item_t; -/* List to keep track of every connected library instance over the control socket */ +// List to keep track of every connected library instance over the control socket static sl_slist_node_t *unwatched_endpoint_list; static int fd_epoll; void epoll_init(void) { - /* Create the epoll set */ + // Create the epoll set { fd_epoll = epoll_create1(EPOLL_CLOEXEC); FATAL_SYSCALL_ON(fd_epoll < 0); @@ -57,7 +59,7 @@ void epoll_register(epoll_private_data_t *private_data) FATAL_ON(private_data->callback == NULL); FATAL_ON(private_data->file_descriptor < 1); - event.events = EPOLLIN; /* Level-triggered read() availability */ + event.events = EPOLLIN; // Level-triggered read() availability event.data.ptr = private_data; ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, private_data->file_descriptor, &event); @@ -73,9 +75,9 @@ void epoll_unregister(epoll_private_data_t *private_data) FATAL_ON(private_data->callback == NULL); FATAL_ON(private_data->file_descriptor < 1); - /* Before unregistering, check if this private data if for an endpoint - * that was previously unwatched. If so, delete it from the unwatch list - * but don't call epoll_ctl::EPOLL_CTL_DEL on it since it was already deleted */ + // Before unregistering, check if this private data if for an endpoint + // that was previously unwatched. If so, delete it from the unwatch list + // but don't call epoll_ctl::EPOLL_CTL_DEL on it since it was already deleted SL_SLIST_FOR_EACH_ENTRY(unwatched_endpoint_list, item, unwatched_endpoint_list_item_t, @@ -108,8 +110,8 @@ void epoll_watch_back(uint8_t endpoint_number) { unwatched_endpoint_list_item_t* item; - /* More than one library connection can exist for one endpoint. When watching back for an - * endpoint, we want to go through all the connections and watch them back */ + // More than one library connection can exist for one endpoint. When watching back for an + // endpoint, we want to go through all the connections and watch them back sl_slist_node_t *item_node = unwatched_endpoint_list; while (1) { @@ -138,7 +140,7 @@ size_t epoll_wait_for_event(struct epoll_event events[], size_t max_event_number FATAL_SYSCALL_ON(event_count < 0); - /* Timeouts should not occur */ + // Timeouts should not occur FATAL_ON(event_count == 0); return (size_t)event_count; diff --git a/server_core/epoll/epoll.h b/server_core/epoll/epoll.h index 8de0f85..ef6a6d1 100644 --- a/server_core/epoll/epoll.h +++ b/server_core/epoll/epoll.h @@ -21,7 +21,7 @@ #include "stdint.h" #include -//forward declaration for interdependency +// forward declaration for interdependency struct epoll_private_data; typedef struct epoll_private_data epoll_private_data_t; @@ -46,4 +46,4 @@ void epoll_watch_back(uint8_t endpoint_number); size_t epoll_wait_for_event(struct epoll_event events[], size_t max_event_number); -#endif //EPOLL_H +#endif // EPOLL_H diff --git a/server_core/server/server.c b/server_core/server/server.c index e12daac..81cd8b5 100644 --- a/server_core/server/server.c +++ b/server_core/server/server.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -42,7 +44,6 @@ #include "server_core/epoll/epoll.h" #include "server_core/core/core.h" #include "sl_cpc.h" -#include "version.h" /******************************************************************************* *************************** LOCAL DECLARATIONS ***************************** @@ -98,13 +99,13 @@ typedef struct { endpoint_control_block_t endpoints[256]; -/* List to keep track of libraries that are blocking on the cpc_open call */ +// List to keep track of libraries that are blocking on the cpc_open call static sl_slist_node_t *pending_connections; -/* List to keep track of every connected library instance over the control socket */ +// List to keep track of every connected library instance over the control socket static sl_slist_node_t *ctrl_connections; -/* List to keep track of every connected library instance over the reset socket */ +// List to keep track of every connected library instance over the reset socket static sl_slist_node_t *reset_connections; /******************************************************************************* @@ -158,29 +159,29 @@ void server_init(void) int ret; - /* Create the control socket /tmp/cpcd/{instance_name}/ctrl.cpcd.sock and start listening for connections */ + // Create the control socket /tmp/cpcd/{instance_name}/ctrl.cpcd.sock and start listening for connections { - /* Create datagram socket for control */ + // Create datagram socket for control fd_socket_ctrl = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); FATAL_SYSCALL_ON(fd_socket_ctrl < 0); - /* Bind socket to socket name. */ + // Bind socket to socket name. { struct sockaddr_un name; - /* Clear struct for portability */ + // Clear struct for portability memset(&name, 0, sizeof(name)); name.sun_family = AF_UNIX; - /* Create the control socket path */ + // Create the control socket path { int nchars; const size_t size = sizeof(name.sun_path) - 1; nchars = snprintf(name.sun_path, size, "%s/cpcd/%s/ctrl.cpcd.sock", config.socket_folder, config.instance_name); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer FATAL_ON(nchars < 0 || (size_t) nchars >= size); } @@ -188,44 +189,42 @@ void server_init(void) FATAL_SYSCALL_ON(ret < 0); } - /* - * Prepare for accepting connections. The backlog size is set - * to 5. So while one request is being processed other requests - * can be waiting. - */ + // Prepare for accepting connections. The backlog size is set + // to 5. So while one request is being processed other requests + // can be waiting. ret = listen(fd_socket_ctrl, 5); FATAL_SYSCALL_ON(ret < 0); - /* Init the linked list of connected instances of the library to /run/cpc/ctrl.cpcd.sock (to empty) */ + // Init the linked list of connected instances of the library to /run/cpc/ctrl.cpcd.sock (to empty) sl_slist_init(&ctrl_connections); - /* Init the linked list of pending client connections */ + // Init the linked list of pending client connections sl_slist_init(&pending_connections); } - /* Create the reset socket /tmp/cpcd/{instance_name}/reset.cpcd.sock and start listening for connections */ + // Create the reset socket /tmp/cpcd/{instance_name}/reset.cpcd.sock and start listening for connections { - /* Create datagram socket for reset */ + // Create datagram socket for reset fd_socket_reset = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); FATAL_SYSCALL_ON(fd_socket_reset < 0); - /* Bind socket to socket name. */ + // Bind socket to socket name. { struct sockaddr_un name; - /* Clear struct for portability */ + // Clear struct for portability memset(&name, 0, sizeof(name)); name.sun_family = AF_UNIX; - /* Create the reset socket path */ + // Create the reset socket path { int nchars; const size_t size = sizeof(name.sun_path) - 1; nchars = snprintf(name.sun_path, size, "%s/cpcd/%s/reset.cpcd.sock", config.socket_folder, config.instance_name); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer FATAL_ON(nchars < 0 || (size_t) nchars >= size); } @@ -233,23 +232,21 @@ void server_init(void) FATAL_SYSCALL_ON(ret < 0); } - /* - * Prepare for accepting connections. The backlog size is set - * to 5. So while one request is being processed other requests - * can be waiting. - */ + // Prepare for accepting connections. The backlog size is set + // to 5. So while one request is being processed other requests + // can be waiting. ret = listen(fd_socket_reset, 5); FATAL_SYSCALL_ON(ret < 0); - /* Init the linked list of connected instances of the library to /run/cpc/reset.cpcd.sock (to empty) */ + // Init the linked list of connected instances of the library to /run/cpc/reset.cpcd.sock (to empty) sl_slist_init(&reset_connections); } - /* Initialize every endpoint control block */ + // Initialize every endpoint control block { size_t i; - for (i = 1; i != 256; i++) { /* dont care for ep#0 */ + for (i = 1; i != 256; i++) { // dont care for ep#0 endpoints[i].open_data_connections = 0; endpoints[i].open_event_connections = 0; endpoints[i].pending_close = 0; @@ -264,13 +261,13 @@ void server_init(void) } } - /* Setup no-op timer. Trig in 1 sec, and every 1 sec after that */ + // Setup no-op timer. Trig in 1 sec, and every 1 sec after that if (config.use_noop_keep_alive) { #if !defined(UNIT_TESTING) const struct itimerspec timeout = { .it_interval = { .tv_sec = 5, .tv_nsec = 0 }, .it_value = { .tv_sec = 5, .tv_nsec = 0 } }; - /* Periodic no-op timer */ + // Periodic no-op timer { fd_timer_noop = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); FATAL_SYSCALL_ON(fd_timer_noop < 0); @@ -282,33 +279,33 @@ void server_init(void) FATAL_SYSCALL_ON(ret < 0); } - /* Setup the timerfd for noop polling */ + // Setup the timerfd for noop polling { static epoll_private_data_t private_data; private_data.callback = server_process_epoll_fd_timeout_noop; private_data.file_descriptor = fd_timer_noop; - private_data.endpoint_number = 0; /* Irrelevant here */ + private_data.endpoint_number = 0; // Irrelevant here epoll_register(&private_data); } #endif } - /* Setup epoll */ + // Setup epoll { - /* Setup the control socket */ + // Setup the control socket { static epoll_private_data_t private_data; private_data.callback = server_process_epoll_fd_ctrl_connection_socket; private_data.file_descriptor = fd_socket_ctrl; - private_data.endpoint_number = 0; /* Irrelevant here */ + private_data.endpoint_number = 0; // Irrelevant here epoll_register(&private_data); } - /* Setup the reset socket */ + // Setup the reset socket { static epoll_private_data_t private_data; @@ -319,14 +316,14 @@ void server_init(void) epoll_register(&private_data); } - /* per-endpoint connection sockets are dynamically created [and added to epoll set] when endpoints are opened */ + // per-endpoint connection sockets are dynamically created [and added to epoll set] when endpoints are opened - /* per-endpoint event sockets are dynamically created [and added to epoll set] when endpoints are opened */ + // per-endpoint event sockets are dynamically created [and added to epoll set] when endpoints are opened - /* per-endpoint data sockets are dynamically created [and added to epoll set] when instances of library are connecting to an endpoint */ + // per-endpoint data sockets are dynamically created [and added to epoll set] when instances of library are connecting to an endpoint } - /* The server up and running, unblock possible threads waiting for it. */ + // The server up and running, unblock possible threads waiting for it. server_ready_post(); } @@ -336,20 +333,20 @@ static void server_process_epoll_fd_event_connection_socket(epoll_private_data_t int fd_connection_socket = private_data->file_descriptor; uint8_t endpoint_number = private_data->endpoint_number; - /* Sanity checks */ + // Sanity checks { - /* We don't deal with system endpoint here*/ + // We don't deal with system endpoint here BUG_ON(endpoint_number == 0); - /* Make sure the connection socket exists */ + // Make sure the connection socket exists BUG_ON(endpoints[endpoint_number].event_connection_socket_epoll_private_data.file_descriptor == -1); } - /* Accept the new connection for that endpoint */ + // Accept the new connection for that endpoint new_data_socket = accept(fd_connection_socket, NULL, NULL); FATAL_SYSCALL_ON(new_data_socket < 0); - /* Set socket as non-blocking */ + // Set socket as non-blocking flags = fcntl(new_data_socket, F_GETFL, NULL); if (flags < 0) { @@ -362,11 +359,11 @@ static void server_process_epoll_fd_event_connection_socket(epoll_private_data_t FATAL("fcntl F_SETFL failed.%s", strerror(errno)); } - /* Add the new data socket in the list of data sockets for that endpoint */ + // Add the new data socket in the list of data sockets for that endpoint { event_socket_private_data_list_item_t* new_item; - /* Allocate resources for this new connection */ + // Allocate resources for this new connection { new_item = (event_socket_private_data_list_item_t*) zalloc(sizeof(event_socket_private_data_list_item_t)); FATAL_ON(new_item == NULL); @@ -374,15 +371,15 @@ static void server_process_epoll_fd_event_connection_socket(epoll_private_data_t sl_slist_push(&endpoints[endpoint_number].event_data_socket_epoll_private_data, &new_item->node); } - /* Register this new connection's socket to epoll set */ + // Register this new connection's socket to epoll set { - epoll_private_data_t* private_data = &new_item->event_socket_epoll_private_data; + epoll_private_data_t* event_socket_private_data = &new_item->event_socket_epoll_private_data; - private_data->callback = server_process_epoll_fd_event_data_socket; - private_data->endpoint_number = endpoint_number; - private_data->file_descriptor = new_data_socket; + event_socket_private_data->callback = server_process_epoll_fd_event_data_socket; + event_socket_private_data->endpoint_number = endpoint_number; + event_socket_private_data->file_descriptor = new_data_socket; - epoll_register(private_data); + epoll_register(event_socket_private_data); } } @@ -397,36 +394,36 @@ static void server_process_epoll_fd_ctrl_connection_socket(epoll_private_data_t int flags; int ret; - /* Accept the new ctrl connection for that client */ + // Accept the new ctrl connection for that client new_data_socket = accept(fd_socket_ctrl, NULL, NULL); FATAL_SYSCALL_ON(new_data_socket < 0); - /* Set socket as non-blocking */ + // Set socket as non-blocking flags = fcntl(new_data_socket, F_GETFL, NULL); FATAL_SYSCALL_ON(flags < 0); ret = fcntl(new_data_socket, F_SETFL, flags | O_NONBLOCK); FATAL_SYSCALL_ON(ret < 0); - /* Add the new data socket in the list of data sockets for ctrl */ + // Add the new data socket in the list of data sockets for ctrl { ctrl_socket_private_data_list_item_t* new_item; - /* Allocate resources for this new connection */ + // Allocate resources for this new connection new_item = zalloc(sizeof(*new_item)); new_item->pid = -1; - /* Register this new data socket to epoll set */ + // Register this new data socket to epoll set { - epoll_private_data_t* private_data = &new_item->data_socket_epoll_private_data; + epoll_private_data_t* data_socket_private_data = &new_item->data_socket_epoll_private_data; - private_data->callback = server_process_epoll_fd_ctrl_data_socket; - private_data->endpoint_number = 0; /* Irrelevent information in the case of ctrl data sockets */ - private_data->file_descriptor = new_data_socket; + data_socket_private_data->callback = server_process_epoll_fd_ctrl_data_socket; + data_socket_private_data->endpoint_number = 0; // Irrelevant information in the case of ctrl data sockets + data_socket_private_data->file_descriptor = new_data_socket; - epoll_register(private_data); + epoll_register(data_socket_private_data); } - /* Finally, add this new socket item to the list */ + // Finally, add this new socket item to the list sl_slist_push(&ctrl_connections, &new_item->node); } } @@ -438,35 +435,35 @@ static void server_process_epoll_fd_reset_connection_socket(epoll_private_data_t int flags; int ret; - /* Accept the new reset connection for that client */ + // Accept the new reset connection for that client reset_data_socket = accept(fd_socket_reset, NULL, NULL); FATAL_SYSCALL_ON(reset_data_socket < 0); - /* Set socket as non-blocking */ + // Set socket as non-blocking flags = fcntl(reset_data_socket, F_GETFL, NULL); FATAL_SYSCALL_ON(flags < 0); ret = fcntl(reset_data_socket, F_SETFL, flags | O_NONBLOCK); FATAL_SYSCALL_ON(ret < 0); - /* Add the new client socket in the list of reset sockets */ + // Add the new client socket in the list of reset sockets { reset_socket_private_data_list_item_t* new_item; - /* Allocate resources for this new connection */ + // Allocate resources for this new connection new_item = zalloc(sizeof(*new_item)); - /* Register this new reset data socket to epoll set */ + // Register this new reset data socket to epoll set { - epoll_private_data_t* private_data = &new_item->reset_socket_epoll_private_data; + epoll_private_data_t* reset_socket_private_data = &new_item->reset_socket_epoll_private_data; - private_data->callback = server_process_epoll_fd_reset_data_socket; - private_data->endpoint_number = 0; /* Irrelevent information in the case of reset data sockets */ - private_data->file_descriptor = reset_data_socket; + reset_socket_private_data->callback = server_process_epoll_fd_reset_data_socket; + reset_socket_private_data->endpoint_number = 0; // Irrelevant information in the case of reset data sockets + reset_socket_private_data->file_descriptor = reset_data_socket; - epoll_register(private_data); + epoll_register(reset_socket_private_data); } - /* Finally, add this new socket item to the list */ + // Finally, add this new socket item to the list sl_slist_push(&reset_connections, &new_item->node); } } @@ -480,16 +477,16 @@ static void server_process_epoll_fd_event_data_socket(epoll_private_data_t *priv int ret; uint8_t endpoint_number = private_data->endpoint_number; - /* Sanity checks */ + // Sanity checks { - /* We don't deal with system endpoint here*/ + // We don't deal with system endpoint here BUG_ON(endpoint_number == 0); - /* Make sure the connection socket exists */ + // Make sure the connection socket exists BUG_ON(endpoints[endpoint_number].event_connection_socket_epoll_private_data.file_descriptor == -1); } - /* Check if the event is about the client closing the connection */ + // Check if the event is about the client closing the connection { int length; @@ -502,7 +499,7 @@ static void server_process_epoll_fd_event_data_socket(epoll_private_data_t *priv } } - /* Retrieve the payload from the endpoint data connection */ + // Retrieve the payload from the endpoint data connection ret = server_pull_data_from_data_socket(fd_event_data_socket, &buffer, &buffer_len); FATAL_ON(ret != 0); @@ -541,6 +538,7 @@ static cpc_endpoint_state_t server_convert_endpoint_state_internal_to_public(sli return SL_CPC_STATE_ERROR_FAULT; default: BUG("Unhandled internal state %d", internal_ep_state); + return SL_CPC_STATE_ERROR_FAULT; } } @@ -550,13 +548,12 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva uint8_t* buffer; size_t buffer_len; cpcd_exchange_buffer_t *interface_buffer; - int ret; - /* Check if the event is about the client closing the connection */ + // Check if the event is about the client closing the connection { int length; - ret = ioctl(fd_ctrl_data_socket, FIONREAD, &length); + int ret = ioctl(fd_ctrl_data_socket, FIONREAD, &length); FATAL_SYSCALL_ON(ret < 0); if (length == 0) { @@ -565,16 +562,18 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva } } - /* Retrieve the payload from the endpoint data connection */ - ret = server_pull_data_from_data_socket(fd_ctrl_data_socket, &buffer, &buffer_len); - FATAL_ON(ret != 0); + // Retrieve the payload from the endpoint data connection + { + int ret = server_pull_data_from_data_socket(fd_ctrl_data_socket, &buffer, &buffer_len); + FATAL_ON(ret != 0); + } FATAL_ON(buffer_len < sizeof(cpcd_exchange_buffer_t)); interface_buffer = (cpcd_exchange_buffer_t *)buffer; switch (interface_buffer->type) { case EXCHANGE_ENDPOINT_STATUS_QUERY: - /* Client requested an endpoint status */ + // Client requested an endpoint status { sli_cpc_endpoint_state_t internal_ep_state; cpc_endpoint_state_t public_ep_state; @@ -588,19 +587,19 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva memcpy(interface_buffer->payload, &public_ep_state, sizeof(cpc_endpoint_state_t)); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != sizeof(cpcd_exchange_buffer_t) + sizeof(cpc_endpoint_state_t)); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != sizeof(cpcd_exchange_buffer_t) + sizeof(cpc_endpoint_state_t)); } } break; case EXCHANGE_MAX_WRITE_SIZE_QUERY: - /* Client requested maximum write size */ + // Client requested maximum write size { uint32_t rx_capability; @@ -612,19 +611,19 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva memcpy(interface_buffer->payload, &rx_capability, sizeof(uint32_t)); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != sizeof(cpcd_exchange_buffer_t) + sizeof(uint32_t)); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != sizeof(cpcd_exchange_buffer_t) + sizeof(uint32_t)); } } break; case EXCHANGE_VERSION_QUERY: - /* Client requested the version of the daemon*/ + // Client requested the version of the daemon { char* version = (char*)interface_buffer->payload; bool do_close_client = false; @@ -648,22 +647,22 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva PRINT_INFO("New client connection using library v%s", version); } - //Reuse the receive buffer to send back the response + // Reuse the receive buffer to send back the response strncpy(version, PROJECT_VER, PROJECT_MAX_VERSION_SIZE); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if ((ret < 0 && errno == EPIPE) || do_close_client) { + if ((sret < 0 && errno == EPIPE) || do_close_client) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != sizeof(cpcd_exchange_buffer_t) + sizeof(char) * PROJECT_MAX_VERSION_SIZE); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != sizeof(cpcd_exchange_buffer_t) + sizeof(char) * PROJECT_MAX_VERSION_SIZE); } } break; case EXCHANGE_SECONDARY_APP_VERSION_SIZE_QUERY: - /* Client requested the size of the application version string */ + // Client requested the size of the application version string { TRACE_SERVER("Received a secondary app version size query"); @@ -672,19 +671,19 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva uint16_t app_version_size = (uint16_t)strlen(server_core_get_secondary_app_version()); memcpy(interface_buffer->payload, &app_version_size, sizeof(app_version_size)); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != buffer_len); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != buffer_len); } } break; case EXCHANGE_SECONDARY_APP_VERSION_STRING_QUERY: - /* Client requested the version string of the secondary application version */ + // Client requested the version string of the secondary application version { size_t app_version_size = strlen(server_core_get_secondary_app_version()); @@ -694,25 +693,25 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva memcpy(interface_buffer->payload, server_core_get_secondary_app_version(), app_version_size); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != buffer_len); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != buffer_len); } } break; case EXCHANGE_OPEN_ENDPOINT_QUERY: - /* Client requested to open an endpoint socket*/ + // Client requested to open an endpoint socket { BUG_ON(buffer_len != sizeof(cpcd_exchange_buffer_t) + sizeof(uint8_t) + sizeof(bool)); TRACE_SERVER("Received an open query for endpoint #%d", interface_buffer->endpoint_number); - //Be careful when asked about opening the security endpoint... + // Be careful when asked about opening the security endpoint... if (interface_buffer->endpoint_number == SL_CPC_ENDPOINT_SECURITY) { if (endpoints[SL_CPC_ENDPOINT_SECURITY].data_connections != NULL // Make sure only 1 client is connected (ie, the daemon' security thread) || config.use_encryption == false) { // Make sure security is enabled @@ -720,13 +719,13 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva bool reply = false; memcpy(&(interface_buffer->payload[1]), &reply, sizeof(bool)); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != buffer_len); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != buffer_len); } break; } @@ -738,8 +737,8 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva SL_SLIST_FOR_EACH_ENTRY(pending_connections, entry, pending_connection_list_item_t, node) { if (entry->endpoint_id == interface_buffer->endpoint_number && entry->fd_ctrl_data_socket == fd_ctrl_data_socket) { - TRACE_SERVER("Found an existing open endpoint query, skipping this one", - interface_buffer->endpoint_number); + TRACE_SERVER("Found an existing open endpoint #%d query, skipping this one", + (int)interface_buffer->endpoint_number); found = true; break; } @@ -764,7 +763,7 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva case EXCHANGE_CLOSE_ENDPOINT_QUERY: { TRACE_SERVER("Received a endpoint close query"); - /* Endpoint was closed by secondary */ + // Endpoint was closed by secondary if (endpoints[interface_buffer->endpoint_number].pending_close > 0) { endpoints[interface_buffer->endpoint_number].pending_close--; @@ -775,23 +774,23 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva } // Ack the close query - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); // And notify the caller - ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); } } } else { - /* Endpoint is about to be closed by a client */ + // Endpoint is about to be closed by a client int fd_data_socket; bool conn_closed; @@ -803,23 +802,23 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva conn_closed = server_ep_remove_closed_connection(interface_buffer->endpoint_number, fd_data_socket); - /* Endpoint was already closed by a client (same ctrl data socket, multiple instances of the same endpoint) */ + // Endpoint was already closed by a client (same ctrl data socket, multiple instances of the same endpoint) if (core_get_endpoint_state(interface_buffer->endpoint_number) == SLI_CPC_STATE_CLOSED || conn_closed) { // Ack the close query - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); // And notify the caller - ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); } } } else { @@ -833,12 +832,12 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva fd_ctrl_data_socket); // Ack the close query - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != (sizeof(cpcd_exchange_buffer_t) + sizeof(int))); } } } @@ -874,13 +873,13 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva memcpy(interface_buffer->payload, &normal_operational_mode, sizeof(bool)); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != sizeof(cpcd_exchange_buffer_t) + sizeof(bool)); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != sizeof(cpcd_exchange_buffer_t) + sizeof(bool)); } } break; @@ -896,13 +895,13 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva memcpy(interface_buffer->payload, &ep_encryption, sizeof(bool)); - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != sizeof(cpcd_exchange_buffer_t) + sizeof(bool)); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != sizeof(cpcd_exchange_buffer_t) + sizeof(bool)); } } break; @@ -912,12 +911,12 @@ static void server_process_epoll_fd_ctrl_data_socket(epoll_private_data_t *priva server_open_endpoint_event_socket(interface_buffer->endpoint_number); // Ack the query - ssize_t ret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); - if (ret < 0 && errno == EPIPE) { + ssize_t sret = send(fd_ctrl_data_socket, interface_buffer, buffer_len, 0); + if (sret < 0 && errno == EPIPE) { server_handle_client_closed_ctrl_connection(fd_ctrl_data_socket); } else { - FATAL_SYSCALL_ON(ret < 0 && errno != EPIPE); - FATAL_ON((size_t)ret != sizeof(cpcd_exchange_buffer_t)); + FATAL_SYSCALL_ON(sret < 0 && errno != EPIPE); + FATAL_ON((size_t)sret != sizeof(cpcd_exchange_buffer_t)); } } break; @@ -934,7 +933,7 @@ static void server_process_epoll_fd_reset_data_socket(epoll_private_data_t *priv int fd_reset_data_socket = private_data->file_descriptor; int ret; - /* Check if the event is about the client closing the connection */ + // Check if the event is about the client closing the connection { int length; @@ -1108,7 +1107,7 @@ static void server_process_epoll_fd_timeout_noop(epoll_private_data_t *private_d { int fd_timer_noop = private_data->file_descriptor; - /* Ack the timer */ + // Ack the timer { uint64_t expiration; ssize_t retval; @@ -1119,7 +1118,7 @@ static void server_process_epoll_fd_timeout_noop(epoll_private_data_t *private_d FATAL_ON(retval != sizeof(expiration)); - WARN_ON(expiration != 1); /* we missed a timeout*/ + WARN_ON(expiration != 1); // we missed a timeout } TRACE_SERVER("NOOP keep alive"); @@ -1144,23 +1143,23 @@ static void server_process_epoll_fd_ep_connection_socket(epoll_private_data_t *p int fd_connection_socket = private_data->file_descriptor; uint8_t endpoint_number = private_data->endpoint_number; - /* Sanity checks */ + // Sanity checks { - /* We don't deal with system endpoint here*/ + // We don't deal with system endpoint here BUG_ON(endpoint_number == 0); - /* Make sure the connection socket exists */ + // Make sure the connection socket exists BUG_ON(endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor == -1); - /* The server should not be currently connecting to the secondary */ + // The server should not be currently connecting to the secondary BUG_ON(endpoints[endpoint_number].connecting_data_socket_fd != -1); } - /* Accept the new connection for that endpoint */ + // Accept the new connection for that endpoint new_data_socket = accept(fd_connection_socket, NULL, NULL); FATAL_SYSCALL_ON(new_data_socket < 0); - /* Set socket as non-blocking */ + // Set socket as non-blocking flags = fcntl(new_data_socket, F_GETFL, NULL); if (flags < 0) { @@ -1173,18 +1172,16 @@ static void server_process_epoll_fd_ep_connection_socket(epoll_private_data_t *p FATAL("fcntl F_SETFL failed.%s", strerror(errno)); } - /* - * store the newly created file descriptor as it will - * be used when the secondary acks the connection - */ + // store the newly created file descriptor as it will + // be used when the secondary acks the connection endpoints[endpoint_number].connecting_data_socket_fd = new_data_socket; - /* unregister this entry to process only one connection request at a time */ + // unregister this entry to process only one connection request at a time epoll_unregister(private_data); uint8_t tx_window_size = endpoints[endpoint_number].tx_window_size; - /* Tell the core that a client has connected to this endpoint */ + // Tell the core that a client has connected to this endpoint if (endpoints[endpoint_number].open_data_connections == 0) { TRACE_SERVER("Told core to connect to ep#%u", endpoint_number); core_open_endpoint(endpoint_number, tx_window_size); @@ -1202,13 +1199,13 @@ static void server_process_epoll_fd_ep_data_socket(epoll_private_data_t *private int ret; if (core_ep_is_busy(endpoint_number)) { - /* Prevent epoll from unblocking right away on this [still marked as ready-read] file descriptor the next time - * epoll_wait is called (and thus leading to 100% CPU usage) */ + // Prevent epoll from unblocking right away on this [still marked as ready-read] file descriptor the next time + // epoll_wait is called (and thus leading to 100% CPU usage) epoll_unwatch(private_data); return; } - /* Check if the event is about the client closing the connection */ + // Check if the event is about the client closing the connection { int length; @@ -1221,16 +1218,16 @@ static void server_process_epoll_fd_ep_data_socket(epoll_private_data_t *private } } - /* The event is about rx data */ + // The event is about rx data - /* Retrieve the payload from the endpoint data connection */ + // Retrieve the payload from the endpoint data connection ret = server_pull_data_from_data_socket(fd_data_socket, &buffer, &buffer_len); if (ret != 0) { server_handle_client_closed_ep_connection(fd_data_socket, endpoint_number); return; } - /* Send the data to the core */ + // Send the data to the core ret = core_write(endpoint_number, buffer, buffer_len, 0); if (ret != 0) { WARN("User tried to push on endpoint %d but it failed", @@ -1266,8 +1263,8 @@ static void server_handle_client_closed_ep_connection(int fd_data_socket, uint8_ sl_slist_node_t *it = endpoints[endpoint_number].data_connections; data_connection_t* item; - /* The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow - * for free()ing items during iteration */ + // The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow + // for free()ing items during iteration if (it == NULL) { FATAL("data connection not found in the linked list of the endpoint"); @@ -1278,38 +1275,36 @@ static void server_handle_client_closed_ep_connection(int fd_data_socket, uint8_ data_connection_t, node); - /* Get next item */ + // Get next item it = it->node; - /* We are iterating through the linked list of opened connections, - * check if this iteration is the good one*/ + // We are iterating through the linked list of opened connections, + // check if this iteration is the good one if (item->conn_data_fd == fd_data_socket) { int ret; - /* Unregister the data socket file descriptor from epoll watch list */ + // Unregister the data socket file descriptor from epoll watch list epoll_unregister(&item->data_socket_epoll_private_data); - /* Remove the item from the list*/ + // Remove the item from the list sl_slist_remove(&endpoints[endpoint_number].data_connections, &item->node); - /* - * Notify the client. The client may or may not have initiated a close - * request. If a close request was initiated, it means it's a clean close - * notify the client and free the resource. If close request was not - * initiated but we end up here, it means that the client probably - * crashed. So just close and free regardless of the return value of the - * function. - */ + // Notify the client. The client may or may not have initiated a close + // request. If a close request was initiated, it means it's a clean close + // notify the client and free the resource. If close request was not + // initiated but we end up here, it means that the client probably + // crashed. So just close and free regardless of the return value of the + // function. server_handle_client_closed_ep_notify_close(endpoint_number, item); - /* Properly close this socket on our side (it is on the client's side)*/ + // Properly close this socket on our side (it is on the client's side) ret = close(item->conn_data_fd); FATAL_SYSCALL_ON(ret < 0); - /* data connections items are malloced */ + // data connections items are malloced free(item); - /* Inform server and core that the endpoint lost a listener */ + // Inform server and core that the endpoint lost a listener server_handle_client_disconnected(endpoint_number); } } @@ -1343,22 +1338,20 @@ static bool server_ep_remove_closed_connection(uint8_t endpoint_number, int conn sl_slist_remove(head, &conn->node); - /* - * Close the file descriptor. It's done only now to make sure the file - * descriptor is not reused while there is a closed connection with the same - * file descriptor. Otherwise we could end up with: - * - Client A - * - open endpoint X, get conn_data_fd=42 - * - crash - * - daemon detects that socket is closed and put the connection in the - * closed connections list. - * - Client B - * - open endpoint X, get conn_data_fd=42 (reused) - * - close endpoint, the daemon detects that the data socket with fd=42 - * has already been closed and returns immediately to the client, but - * it's actually confusing the current connection with the one of - * client A - */ + // Close the file descriptor. It's done only now to make sure the file + // descriptor is not reused while there is a closed connection with the same + // file descriptor. Otherwise we could end up with: + // - Client A + // - open endpoint X, get conn_data_fd=42 + // - crash + // - daemon detects that socket is closed and put the connection in the + // closed connections list. + // - Client B + // - open endpoint X, get conn_data_fd=42 (reused) + // - close endpoint, the daemon detects that the data socket with fd=42 + // has already been closed and returns immediately to the client, but + // it's actually confusing the current connection with the one of + // client A close(conn->conn_data_fd); free(conn); @@ -1393,7 +1386,7 @@ static bool server_handle_client_closed_ep_notify_close(uint8_t endpoint_number, ret = send(conn->conn_ctrl_fd, query_close, query_close_len, 0); if (ret == (ssize_t)query_close_len) { } else { - if (errno != EPIPE || errno != ECONNRESET || errno != ECONNREFUSED) { + if (errno != EPIPE && errno != ECONNRESET && errno != ECONNREFUSED) { WARN("Endpoint close notification could not be sent, errno = %d", errno); } } @@ -1409,8 +1402,8 @@ static void server_handle_client_closed_ctrl_connection(int fd_data_socket) ctrl_socket_private_data_list_item_t* item; sl_slist_node_t *it = ctrl_connections; - /* The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow - * for free()ing items during iteration */ + // The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow + // for free()ing items during iteration if (it == NULL) { FATAL("ctrl data connection not found in the linked list of the ctrl socket"); @@ -1421,25 +1414,25 @@ static void server_handle_client_closed_ctrl_connection(int fd_data_socket) ctrl_socket_private_data_list_item_t, node); - /* Get the next item */ + // Get the next item it = it->node; - /* We are iterating through the linked list of opened connections, - * check if this iteration is the good one*/ + // We are iterating through the linked list of opened connections, + // check if this iteration is the good one if (item->data_socket_epoll_private_data.file_descriptor == fd_data_socket) { - /* Unregister the data socket file descriptor from epoll watch list */ + // Unregister the data socket file descriptor from epoll watch list epoll_unregister(&item->data_socket_epoll_private_data); - /* Remove the item from the list*/ + // Remove the item from the list sl_slist_remove(&ctrl_connections, &item->node); - /* Properly close this socket on our side (it is on the client's side)*/ + // Properly close this socket on our side (it is on the client's side) int ret = close(fd_data_socket); FATAL_SYSCALL_ON(ret < 0); PRINT_INFO("Client disconnected"); - /* data connections items are malloced */ + // data connections items are malloced free(item); } } @@ -1450,8 +1443,8 @@ static void server_handle_client_closed_reset_connection(int fd_reset_data_socke reset_socket_private_data_list_item_t* item; sl_slist_node_t *it = reset_connections; - /* The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow - * for free()ing items during iteration */ + // The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow + // for free()ing items during iteration if (it == NULL) { FATAL("reset data connection not found in the linked list of the reset socket"); @@ -1462,23 +1455,23 @@ static void server_handle_client_closed_reset_connection(int fd_reset_data_socke reset_socket_private_data_list_item_t, node); - /* Get the next item */ + // Get the next item it = it->node; - /* We are iterating through the linked list of opened connections, - * check if this iteration is the good one*/ + // We are iterating through the linked list of opened connections, + // check if this iteration is the good one if (item->reset_socket_epoll_private_data.file_descriptor == fd_reset_data_socket) { - /* Unregister the reset data socket file descriptor from epoll watch list */ + // Unregister the reset data socket file descriptor from epoll watch list epoll_unregister(&item->reset_socket_epoll_private_data); - /* Remove the item from the list*/ + // Remove the item from the list sl_slist_remove(&reset_connections, &item->node); - /* Properly close this socket on our side (it is on the client's side)*/ + // Properly close this socket on our side (it is on the client's side) int ret = close(fd_reset_data_socket); FATAL_SYSCALL_ON(ret < 0); - /* data connections items are malloced */ + // data connections items are malloced free(item); } } @@ -1491,8 +1484,8 @@ static void server_handle_client_closed_event_connection(int fd_data_socket, uin BUG_ON(endpoints[endpoint_number].open_event_connections == 0); - /* The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow - * for free()ing items during iteration */ + // The while loop that follows is the macro SL_SLIST_FOR_EACH_ENTRY exploded to allow + // for free()ing items during iteration if (it == NULL) { FATAL("event data connection not found in the linked list of the event socket"); @@ -1503,23 +1496,23 @@ static void server_handle_client_closed_event_connection(int fd_data_socket, uin event_socket_private_data_list_item_t, node); - /* Get the next item */ + // Get the next item it = it->node; - /* We are iterating through the linked list of opened connections, - * check if this iteration is the good one*/ + // We are iterating through the linked list of opened connections, + // check if this iteration is the good one if (item->event_socket_epoll_private_data.file_descriptor == fd_data_socket) { - /* Unregister the data socket file descriptor from epoll watch list */ + // Unregister the data socket file descriptor from epoll watch list epoll_unregister(&item->event_socket_epoll_private_data); - /* Remove the item from the list*/ + // Remove the item from the list sl_slist_remove(&endpoints[endpoint_number].event_data_socket_epoll_private_data, &item->node); - /* Properly close this socket on our side (it is on the client's side)*/ + // Properly close this socket on our side (it is on the client's side) int ret = close(fd_data_socket); FATAL_SYSCALL_ON(ret < 0); - /* data connections items are malloced */ + // data connections items are malloced free(item); } } @@ -1539,47 +1532,45 @@ static void server_open_endpoint_event_socket(uint8_t endpoint_number) int fd_connection_sock; int ret; - /* Sanity checks */ + // Sanity checks { if (endpoints[endpoint_number].event_connection_socket_epoll_private_data.file_descriptor != -1) { return; // Nothing to do, endpoint socket is already opened } - /* System endpoint (#0) is not like the others, if we create a socket for it, there's a bug */ + // System endpoint (#0) is not like the others, if we create a socket for it, there's a bug BUG_ON(endpoint_number == 0); - /* Its a bug if we try to open an already opened endpoint */ + // Its a bug if we try to open an already opened endpoint BUG_ON(endpoints[endpoint_number].event_connection_socket_epoll_private_data.file_descriptor != -1); - /* Make sure the list of data sockets is empty (no leftovers from previous open/close */ + // Make sure the list of data sockets is empty (no leftovers from previous open/close BUG_ON(endpoints[endpoint_number].event_data_socket_epoll_private_data != NULL); } - /* Create the connection socket and start listening new connections on /run/cpc/epX.cpcd.sock */ + // Create the connection socket and start listening new connections on /run/cpc/epX.cpcd.sock { - /* Create the connection socket.*/ + // Create the connection socket. fd_connection_sock = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); FATAL_SYSCALL_ON(fd_connection_sock < 0); - /* Bind this socket to a name. */ + // Bind this socket to a name. { - /* - * For portability clear the whole structure, since some - * implementations have additional (nonstandard) fields in - * the structure. - */ + // For portability clear the whole structure, since some + // implementations have additional (nonstandard) fields in + // the structure. memset(&name, 0, sizeof(name)); name.sun_family = AF_UNIX; - /* Create the endpoint socket path */ + // Create the endpoint socket path { int nchars; const size_t size = sizeof(name.sun_path) - 1; nchars = snprintf(name.sun_path, size, "%s/cpcd/%s/ep%d.event.cpcd.sock", config.socket_folder, config.instance_name, endpoint_number); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer FATAL_ON(nchars < 0 || (size_t) nchars >= size); } @@ -1587,16 +1578,14 @@ static void server_open_endpoint_event_socket(uint8_t endpoint_number) FATAL_SYSCALL_ON(ret < 0); } - /* - * Prepare for accepting connections. The backlog size is set - * to 5. So while one request is being processed other requests - * can be waiting. - */ + // Prepare for accepting connections. The backlog size is set + // to 5. So while one request is being processed other requests + // can be waiting. ret = listen(fd_connection_sock, 5); FATAL_SYSCALL_ON(ret < 0); } - /* Start monitoring this connection socket in epoll */ + // Start monitoring this connection socket in epoll { epoll_private_data_t* private_data = &endpoints[endpoint_number].event_connection_socket_epoll_private_data; @@ -1621,47 +1610,45 @@ static void server_open_endpoint(uint8_t endpoint_number) int fd_connection_sock; int ret; - /* Sanity checks */ + // Sanity checks { if (endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor != -1) { return; // Nothing to do, endpoint socket is already opened } - /* System endpoint (#0) is not like the others, if we create a socket for it, there's a bug */ + // System endpoint (#0) is not like the others, if we create a socket for it, there's a bug BUG_ON(endpoint_number == 0); - /* Its a bug if we try to open an already opened endpoint */ + // Its a bug if we try to open an already opened endpoint BUG_ON(endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor != -1); - /* Make sure the list of data sockets is empty (no leftovers from previous open/close */ + // Make sure the list of data sockets is empty (no leftovers from previous open/close BUG_ON(endpoints[endpoint_number].data_connections != NULL); } - /* Create the connection socket and start listening new connections on /run/cpc/epX.cpcd.sock */ + // Create the connection socket and start listening new connections on /run/cpc/epX.cpcd.sock { - /* Create the connection socket.*/ + // Create the connection socket. fd_connection_sock = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); FATAL_SYSCALL_ON(fd_connection_sock < 0); - /* Bind this socket to a name. */ + // Bind this socket to a name. { - /* - * For portability clear the whole structure, since some - * implementations have additional (nonstandard) fields in - * the structure. - */ + // For portability clear the whole structure, since some + // implementations have additional (nonstandard) fields in + // the structure. memset(&name, 0, sizeof(name)); name.sun_family = AF_UNIX; - /* Create the endpoint socket path */ + // Create the endpoint socket path { int nchars; const size_t size = sizeof(name.sun_path) - 1; nchars = snprintf(name.sun_path, size, "%s/cpcd/%s/ep%d.cpcd.sock", config.socket_folder, config.instance_name, endpoint_number); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer FATAL_ON(nchars < 0 || (size_t) nchars >= size); } @@ -1669,21 +1656,19 @@ static void server_open_endpoint(uint8_t endpoint_number) FATAL_SYSCALL_ON(ret < 0); } - /* - * Prepare for accepting connections. The backlog size is set - * to 5. So while one request is being processed other requests - * can be waiting. - */ + // Prepare for accepting connections. The backlog size is set + // to 5. So while one request is being processed other requests + // can be waiting. ret = listen(fd_connection_sock, 5); FATAL_SYSCALL_ON(ret < 0); } - /* Start monitoring this connection socket in epoll */ + // Start monitoring this connection socket in epoll { epoll_private_data_t* private_data = &endpoints[endpoint_number].connection_socket_epoll_private_data; private_data->callback = server_process_epoll_fd_ep_connection_socket; - private_data->endpoint_number = endpoint_number; /* server_process_epoll_fd_ep_connection_socket() callback WILL use the endpoint number and the file descriptor */ + private_data->endpoint_number = endpoint_number; // server_process_epoll_fd_ep_connection_socket() callback WILL use the endpoint number and the file descriptor private_data->file_descriptor = fd_connection_sock; epoll_register(private_data); @@ -1716,10 +1701,8 @@ void server_connect_endpoint(uint8_t endpoint_number, bool error) BUG_ON(data_socket_fd == -1); if (!error) { - /* - * If no error occurred, the secondary accepted the connection request, - * start watching on the data socket created for the user - */ + // If no error occurred, the secondary accepted the connection request, + // start watching on the data socket created for the user data_connection_t* new_item; epoll_private_data_t* private_data; @@ -1734,10 +1717,10 @@ void server_connect_endpoint(uint8_t endpoint_number, bool error) private_data->endpoint_number = endpoint_number; private_data->file_descriptor = data_socket_fd; - /* Add the new data socket in the list of data sockets for that endpoint */ + // Add the new data socket in the list of data sockets for that endpoint sl_slist_push(&endpoints[endpoint_number].data_connections, &new_item->node); - /* Register this new connection's socket to epoll set */ + // Register this new connection's socket to epoll set epoll_register(private_data); endpoints[endpoint_number].open_data_connections++; @@ -1750,14 +1733,12 @@ void server_connect_endpoint(uint8_t endpoint_number, bool error) buffer->endpoint_number = endpoint_number; buffer->type = EXCHANGE_OPEN_ENDPOINT_QUERY; - /* - * Share the server endpoint data socket to the user. This allows us to - * create a ctrl data/data socket pair when it's time to close the socket, - * which ultimately allows us to send a synchronized notification to the user. - * For the library, this variable is just a token that the user must pass - * back to the daemon in order to identify the connection. The library uses - * that value as session_id. - */ + // Share the server endpoint data socket to the user. This allows us to + // create a ctrl data/data socket pair when it's time to close the socket, + // which ultimately allows us to send a synchronized notification to the user. + // For the library, this variable is just a token that the user must pass + // back to the daemon in order to identify the connection. The library uses + // that value as session_id. memcpy(buffer->payload, &data_socket_fd, sizeof(data_socket_fd)); memcpy(&buffer->payload[sizeof(int)], &can_open, sizeof(bool)); @@ -1771,10 +1752,10 @@ void server_connect_endpoint(uint8_t endpoint_number, bool error) } } - /* for sanity, reset this value to -1 to catch potential mistakes */ + // for sanity, reset this value to -1 to catch potential mistakes endpoints[endpoint_number].connecting_data_socket_fd = -1; - /* watch back the connection socket for other clients wishing to connect */ + // watch back the connection socket for other clients wishing to connect epoll_register(&endpoints[endpoint_number].connection_socket_epoll_private_data); } @@ -1788,9 +1769,9 @@ void server_close_endpoint(uint8_t endpoint_number, bool error) size_t data_sock_i = 0; int ret; - /* Sanity check */ + // Sanity check { - /* System endpoint is not like the others, if we create a socket for it, there's a bug */ + // System endpoint is not like the others, if we create a socket for it, there's a bug BUG_ON(endpoint_number == 0); if (endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor == -1) { @@ -1798,48 +1779,46 @@ void server_close_endpoint(uint8_t endpoint_number, bool error) } } - /* Close every open connection on that endpoint (data socket) */ + // Close every open connection on that endpoint (data socket) while (endpoints[endpoint_number].data_connections != NULL) { data_connection_t* item; bool client_notified; data_sock_i++; - /* Pop the first element of the list */ + // Pop the first element of the list { sl_slist_node_t* node = sl_slist_pop(&endpoints[endpoint_number].data_connections); item = SL_SLIST_ENTRY(node, data_connection_t, node); } - /* Unregister the data socket file descriptor from epoll watch list */ + // Unregister the data socket file descriptor from epoll watch list { epoll_unregister(&item->data_socket_epoll_private_data); } - /* Notify the client */ + // Notify the client { client_notified = server_handle_client_closed_ep_notify_close(endpoint_number, item); - /* - * If the client was notified, it means a close request was pending, now - * that we're done dealing with it, we can get rid of it. Otherwise, just - * shutdown the connection to prevent client from using it. Eventually, we - * expect them to close the endpoint via the control endpoint. If the - * error flag is set, all connection resources should be released. - */ + // If the client was notified, it means a close request was pending, now + // that we're done dealing with it, we can get rid of it. Otherwise, just + // shutdown the connection to prevent client from using it. Eventually, we + // expect them to close the endpoint via the control endpoint. If the + // error flag is set, all connection resources should be released. if (client_notified || error) { - /* Close the socket */ + // Close the socket ret = close(item->conn_data_fd); FATAL_SYSCALL_ON(ret < 0); - /* Unlike connection sockets, which is one per endpoint (and we know there are 255 of them) - * and statically allocated in the fixed 255 size array at the top of this file, data sockets - * are dynamically allocated because an arbitrary number of application can decide to connect - * to an opened endpoint */ - /* Linked list items are malloc'ed, free them */ + // Unlike connection sockets, which is one per endpoint (and we know there are 255 of them) + // and statically allocated in the fixed 255 size array at the top of this file, data sockets + // are dynamically allocated because an arbitrary number of application can decide to connect + // to an opened endpoint + // Linked list items are malloc'ed, free them free(item); } else { - /* shutdown the socket to prevent further transmissions */ + // shutdown the socket to prevent further transmissions ret = shutdown(item->conn_data_fd, SHUT_RDWR); FATAL_SYSCALL_ON(ret < 0); @@ -1847,40 +1826,40 @@ void server_close_endpoint(uint8_t endpoint_number, bool error) &item->node); } - TRACE_SERVER("Closed data socket #%u on ep#%u%s", + TRACE_SERVER("Closed data socket #%zd on ep#%d%s", data_sock_i, - endpoint_number, + (int)endpoint_number, client_notified ? "" : " delayed"); } } - /* Close the connection socket */ + // Close the connection socket { int fd_connection_socket = endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor; if (fd_connection_socket > 0) { - /* Unregister the connection socket file descriptor from epoll watch list */ + // Unregister the connection socket file descriptor from epoll watch list epoll_unregister(&endpoints[endpoint_number].connection_socket_epoll_private_data); - /* Close the connection socket */ + // Close the connection socket ret = close(fd_connection_socket); FATAL_SYSCALL_ON(ret < 0); } - /* Clean its lingering file system socket file */ + // Clean its lingering file system socket file { - /* The connection socket was named and bound to a file system name. Shutting() it down - * and closing() it doesn't 'delete' its file, it has to be manually unlinked */ + // The connection socket was named and bound to a file system name. Shutting() it down + // and closing() it doesn't 'delete' its file, it has to be manually unlinked char endpoint_path[sizeof_member(struct sockaddr_un, sun_path)]; - /* Create the endpoint path */ + // Create the endpoint path { int nchars; const size_t size = sizeof(endpoint_path); nchars = snprintf(endpoint_path, size, "%s/cpcd/%s/ep%d.cpcd.sock", config.socket_folder, config.instance_name, endpoint_number); - /* Make sure the path fitted entirely in the struct's static buffer */ + // Make sure the path fitted entirely in the struct's static buffer FATAL_ON(nchars < 0 || (size_t) nchars >= size); } @@ -1888,10 +1867,10 @@ void server_close_endpoint(uint8_t endpoint_number, bool error) FATAL_SYSCALL_ON(ret < 0 && errno != ENOENT); } - /* Set the connection socket file descriptor to -1 to signify that the endpoint is closed */ + // Set the connection socket file descriptor to -1 to signify that the endpoint is closed endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor = -1; - /* At this point the endpoint socket is closed.. there can't be any listeners */ + // At this point the endpoint socket is closed.. there can't be any listeners if (error) { // We expect all open connections to call cpc_close to clear the error via the control socket endpoints[endpoint_number].pending_close = endpoints[endpoint_number].open_data_connections; @@ -1910,21 +1889,21 @@ sl_status_t server_push_data_to_endpoint(uint8_t endpoint_number, const uint8_t* sl_slist_node_t *it = endpoints[endpoint_number].data_connections; int nb_clients = 0; - /* Sanity checks */ + // Sanity checks { - /* If we receive data for an endpoint from the core and try to push it to an - * endpoint socket that is closed (that is, doesn't have its connection socket - * up), its a bug. Server and core should be coherent */ + // If we receive data for an endpoint from the core and try to push it to an + // endpoint socket that is closed (that is, doesn't have its connection socket + // up), its a bug. Server and core should be coherent BUG_ON(endpoints[endpoint_number].connection_socket_epoll_private_data.file_descriptor == -1); - /* Give a warning if we want to push data but no apps are connected to the - * endpoint. That is, the list of data sockets is empty */ + // Give a warning if we want to push data but no apps are connected to the + // endpoint. That is, the list of data sockets is empty WARN_ON(endpoints[endpoint_number].data_connections == NULL); } - /* Iterate through all data sockets for that endpoint */ + // Iterate through all data sockets for that endpoint while (it != NULL) { - /* Push the buffer's payload to each connected app */ + // Push the buffer's payload to each connected app data_connection_t *item = SL_SLIST_ENTRY(it, data_connection_t, node); ssize_t wc; @@ -1938,36 +1917,39 @@ sl_status_t server_push_data_to_endpoint(uint8_t endpoint_number, const uint8_t* TRACE_SERVER("send() failed with %s", strerror(errno)); } - /* keep track of number of clients the data have been sent to */ + // keep track of number of clients the data have been sent to nb_clients++; - /* Close unresponsive sockets */ + // Close unresponsive sockets if (wc < 0 && (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EWOULDBLOCK)) { WARN("Unresponsive data socket on ep#%d, closing", endpoint_number); - /* - * nb_clients helps to keep track of the number of clients the data have - * been sent to. The use case here is to return an error *only* if there - * was only one client connected. If there were two clients and for some - * reasons sending to both of them fail, we want to close the two connections. - */ + // nb_clients helps to keep track of the number of clients the data have + // been sent to. The use case here is to return an error *only* if there + // was only one client connected. If there were two clients and for some + // reasons sending to both of them fail, we want to close the two connections. if (endpoints[endpoint_number].open_data_connections == 1 && nb_clients == 1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + // Checking EAGAIN and EWOULDBLOCK in the same condition triggers + // -Wlogical-op because they may be the same on POSIX. + if (errno == EAGAIN) { + return SL_STATUS_WOULD_BLOCK; + } + if (errno == EWOULDBLOCK) { return SL_STATUS_WOULD_BLOCK; } } - /* Unregister the data socket file descriptor from epoll watch list */ + // Unregister the data socket file descriptor from epoll watch list epoll_unregister(&item->data_socket_epoll_private_data); - /* shutdown the socket, preventing further transmissions */ + // shutdown the socket, preventing further transmissions int ret = shutdown(item->conn_data_fd, SHUT_RDWR); FATAL_SYSCALL_ON(ret < 0); - /* Remove the item from the list*/ + // Remove the item from the list sl_slist_remove(&endpoints[endpoint_number].data_connections, &item->node); - /* Push item to list of closed data endpoints */ + // Push item to list of closed data endpoints sl_slist_push_back(&endpoints[endpoint_number].closed_data_connections, &item->node); FATAL_ON(endpoints[endpoint_number].open_data_connections == 0); @@ -1982,7 +1964,7 @@ sl_status_t server_push_data_to_endpoint(uint8_t endpoint_number, const uint8_t* return SL_STATUS_FAIL; } } else { - /* The data should have been be completely written to the socket */ + // The data should have been be completely written to the socket FATAL_SYSCALL_ON(wc < 0); FATAL_ON((size_t)wc != data_len); } @@ -1998,18 +1980,18 @@ static int server_pull_data_from_data_socket(int fd_data_socket, uint8_t** buffe ssize_t rc; int ret; - /* Poll the socket to get the next pending datagram size */ + // Poll the socket to get the next pending datagram size { ret = ioctl(fd_data_socket, FIONREAD, &datagram_length); FATAL_SYSCALL_ON(ret < 0); - /* The socket had no data. This function is intended to be called - * when we know the socket has data. */ + // The socket had no data. This function is intended to be called + // when we know the socket has data. BUG_ON(datagram_length == 0); } - /* Allocate a buffer of the right size */ + // Allocate a buffer of the right size { // Allocate a buffer and pad it to 8 bytes because memcpy reads in chunks of 8. // If we don't pad, Valgrind will complain. @@ -2017,7 +1999,7 @@ static int server_pull_data_from_data_socket(int fd_data_socket, uint8_t** buffe FATAL_ON(buffer == NULL); } - /* Fetch the data from the data socket */ + // Fetch the data from the data socket { rc = recv(fd_data_socket, buffer, (size_t)datagram_length, 0); if (rc < 0) { @@ -2073,7 +2055,7 @@ void server_notify_connected_libs_of_secondary_reset(void) reset_socket_private_data_list_item_t, node){ ssize_t ret = send(item->reset_socket_epoll_private_data.file_descriptor, NULL, 0, MSG_DONTWAIT); - if (ret < 0 && (errno != EPIPE || errno != ECONNRESET || errno != ECONNREFUSED)) { + if ( (ret < 0) && (errno != EPIPE && errno != ECONNRESET && errno != ECONNREFUSED)) { WARN("Reset callback notification could not be sent, errno = %d", errno); } } @@ -2135,6 +2117,7 @@ static cpc_event_type_t server_get_event_type_from_state(sli_cpc_endpoint_state_ return SL_CPC_EVENT_ENDPOINT_UNKNOWN; default: BUG("A new state (%d) has been added that has no equivalent event type .", state); + return SL_CPC_EVENT_ENDPOINT_UNKNOWN; } } diff --git a/server_core/server/server_internal.h b/server_core/server/server_internal.h index 042f84d..a17b03e 100644 --- a/server_core/server/server_internal.h +++ b/server_core/server/server_internal.h @@ -24,4 +24,4 @@ void server_push_data_to_core(uint8_t endpoint_number, const void *data, size_t void server_tell_core_to_open_endpoint(uint8_t endpoint_number); -#endif //SERVER_INTERNAL_H +#endif // SERVER_INTERNAL_H diff --git a/server_core/server/server_ready_sync.c b/server_core/server/server_ready_sync.c index 1dcb0f6..f512812 100644 --- a/server_core/server/server_ready_sync.c +++ b/server_core/server/server_ready_sync.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include @@ -58,7 +60,7 @@ void server_ready_wait(void) FATAL_ON(ret != 0); } - /* Nothing to do with the predicate. */ + // Nothing to do with the predicate. } pthread_mutex_unlock(&server_ready_synchronizer.is_ready_mutex); } diff --git a/server_core/server_core.c b/server_core/server_core.c index 8c718b9..67a92d4 100644 --- a/server_core/server_core.c +++ b/server_core/server_core.c @@ -14,7 +14,8 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ -#define _GNU_SOURCE + +#include "config.h" #include @@ -41,7 +42,6 @@ #include "server_core/server/server.h" #include "server_core/core/core.h" #include "server_core/system_endpoint/system.h" -#include "version.h" #include "driver/driver_kill.h" #define MAX_EPOLL_EVENTS 1 @@ -50,28 +50,33 @@ char *server_core_secondary_app_version = NULL; uint8_t server_core_secondary_protocol_version; sl_cpc_bootloader_t server_core_secondary_bootloader_type = SL_CPC_BOOTLOADER_UNKNOWN; +#if !defined(UNIT_TESTING) static const sli_cpc_system_primary_version_t primary_version = { .major = PROJECT_VER_MAJOR, .minor = PROJECT_VER_MINOR, .patch = PROJECT_VER_PATCH, .tweak = PROJECT_VER_TWEAK }; +#endif static pthread_t server_core_thread; static bool server_core_thread_started = false; -static bool set_reset_mode_ack = false; static bool reset_ack = false; +static bool secondary_bus_max_bitrate_received = false; + +#if !defined(UNIT_TESTING) +static bool set_reset_mode_ack = false; static bool secondary_cpc_version_received = false; static bool set_primary_version_reply_received = false; static bool secondary_app_version_received_or_not_available = false; static bool bootloader_info_received_or_not_available = false; static bool secondary_bus_bitrate_received = false; static bool failed_to_receive_secondary_bus_bitrate = false; -static bool secondary_bus_max_bitrate_received = false; static bool failed_to_receive_secondary_bus_max_bitrate = false; static bool capabilities_received = false; static bool rx_capability_received = false; static bool protocol_version_received = false; +#endif #if defined(UNIT_TESTING) static bool reset_reason_received = true; @@ -81,7 +86,9 @@ static bool reset_reason_received = false; static server_core_mode_t server_core_mode = SERVER_CORE_MODE_NORMAL; +#if !defined(UNIT_TESTING) static sl_cpc_system_reboot_mode_t pending_reboot_mode; +#endif static int kill_eventfd = -1; static int security_ready_eventfd = -1; @@ -103,11 +110,13 @@ static enum { RESET_SEQUENCE_DONE } reset_sequence_state = SET_NORMAL_REBOOT_MODE; +#if !defined(UNIT_TESTING) static enum { SET_BOOTLOADER_REBOOT_MODE, WAIT_BOOTLOADER_REBOOT_MODE_ACK, WAIT_BOOTLOADER_RESET_ACK } reboot_into_bootloader_state = SET_BOOTLOADER_REBOOT_MODE; +#endif bool ignore_reset_reason = true; @@ -117,9 +126,13 @@ static uint32_t rx_capability = 1024; static uint32_t rx_capability = 0; #endif +#if !defined(UNIT_TESTING) static uint32_t capabilities = 0; +#endif +#if !defined(UNIT_TESTING) static void on_unsolicited_status(sl_cpc_system_status_t status); +#endif static void* server_core_thread_func(void* param); @@ -139,13 +152,17 @@ static void security_property_get_state_callback(sli_cpc_property_id_t property_ static void security_fetch_remote_security_state(epoll_private_data_t *private_data); +#if !defined(UNIT_TESTING) static void property_set_reset_mode_callback(sli_cpc_property_id_t property_id, void *property_value, size_t property_length, void *user_data, sl_status_t status); +#endif +#if !defined(UNIT_TESTING) static void process_reboot_enter_bootloader(void); +#endif void reset_callback(sl_status_t status, sl_cpc_system_status_t reset_status); @@ -183,7 +200,7 @@ uint32_t server_core_get_secondary_rx_capability(void) void server_core_kill(void) { ssize_t ret; - const uint64_t event_value = 1; //doesn't matter what it is + const uint64_t event_value = 1; // Doesn't matter what it is if (kill_eventfd == -1) { return; @@ -231,7 +248,7 @@ void server_core_init(int fd_socket_driver_core, int fd_socket_driver_core_notif sl_cpc_system_register_unsolicited_prop_last_status_callback(on_unsolicited_status); #endif - /* Create the string {socket_folder}/cpcd/{instance_name} */ + // Create the string {socket_folder}/cpcd/{instance_name} { const size_t socket_folder_string_size = strlen(config.socket_folder) + strlen("/cpcd/") + strlen(config.instance_name) + sizeof(char); socket_folder = (char *)zalloc(socket_folder_string_size); @@ -241,7 +258,7 @@ void server_core_init(int fd_socket_driver_core, int fd_socket_driver_core_notif FATAL_ON(ret < 0 || (size_t) ret >= socket_folder_string_size); } - /* Check if the socket folder exists */ + // Check if the socket folder exists if (stat(socket_folder, &sb) == 0 && S_ISDIR(sb.st_mode)) { TRACE_SERVER("Cleaning up socket folder %s", socket_folder); cleanup_socket_folder(socket_folder); @@ -254,11 +271,11 @@ void server_core_init(int fd_socket_driver_core, int fd_socket_driver_core_notif free(socket_folder); - /* The server is not initialized immediately because we want to perform a successful reset sequence - * of the secondary before. That is, unless we explicitly disable the reset sequence in the config file */ + // The server is not initialized immediately because we want to perform a successful reset sequence + // of the secondary before. That is, unless we explicitly disable the reset sequence in the config file if (config.reset_sequence == false) { - /* FIXME : If we don't perform a reset sequence, the rx_capability won't be fetched. Lets put a very conservative - * value in place to be able to work . */ + // FIXME : If we don't perform a reset sequence, the rx_capability won't be fetched. Lets put a very conservative + // value in place to be able to work. rx_capability = 256; ret = core_set_protocol_version(PROTOCOL_VERSION); @@ -279,22 +296,22 @@ void server_core_init(int fd_socket_driver_core, int fd_socket_driver_core_notif server_init(); #endif - /* Setup the kill eventfd */ + // Setup the kill eventfd { - kill_eventfd = eventfd(0, //Start with 0 value + kill_eventfd = eventfd(0, // Start with 0 value EFD_CLOEXEC); FATAL_ON(kill_eventfd == -1); static epoll_private_data_t private_data; private_data.callback = server_core_cleanup; - private_data.file_descriptor = kill_eventfd; /* Irrelevant here */ - private_data.endpoint_number = 0; /* Irrelevant here */ + private_data.file_descriptor = kill_eventfd; // Irrelevant here + private_data.endpoint_number = 0; // Irrelevant here epoll_register(&private_data); } - /* Setup event to be called when security has been initialized */ + // Setup event to be called when security has been initialized { security_ready_eventfd = eventfd(0, EFD_CLOEXEC); FATAL_ON(security_ready_eventfd == -1); @@ -302,14 +319,14 @@ void server_core_init(int fd_socket_driver_core, int fd_socket_driver_core_notif static epoll_private_data_t security_ready_data; security_ready_data.callback = security_fetch_remote_security_state; - /* These fields are initialized but values are not relevant */ + // These fields are initialized but values are not relevant security_ready_data.file_descriptor = security_ready_eventfd; security_ready_data.endpoint_number = 0; epoll_register(&security_ready_data); } - /* create server_core thread */ + // create server_core thread server_core_mode = mode; ret = pthread_create(&server_core_thread, NULL, server_core_thread_func, NULL); FATAL_ON(ret != 0); @@ -353,7 +370,7 @@ static void* server_core_thread_func(void* param) event_count = epoll_wait_for_event(events, MAX_EPOLL_EVENTS); - /* Process each ready file descriptor*/ + // Process each ready file descriptor size_t event_i; for (event_i = 0; event_i != (size_t)event_count; event_i++) { epoll_private_data_t* private_data = (epoll_private_data_t*) events[event_i].data.ptr; @@ -366,6 +383,7 @@ static void* server_core_thread_func(void* param) return NULL; } +#if !defined(UNIT_TESTING) static void property_set_reset_mode_callback(sli_cpc_property_id_t property_id, void *property_value, size_t property_length, @@ -417,6 +435,7 @@ static void property_set_reset_mode_callback(sli_cpc_property_id_t property_id, break; } } +#endif void reset_callback(sl_status_t status, sl_cpc_system_status_t reset_status) @@ -444,6 +463,7 @@ void reset_callback(sl_status_t status, } } +#if !defined(UNIT_TESTING) static void on_unsolicited_status(sl_cpc_system_status_t status) { if (uart_validation_reset_requested(status)) { @@ -465,19 +485,19 @@ static void on_unsolicited_status(sl_cpc_system_status_t status) } else { PRINT_INFO("Secondary has reset, reset the daemon."); - /* Stop driver immediately */ + // Stop driver immediately driver_kill(); - /* Notify lib connected */ + // Notify lib connected server_notify_connected_libs_of_secondary_reset(); - /* Close every single endpoint data connections */ + // Close every single endpoint data connections for (uint8_t i = 1; i < 255; ++i) { server_close_endpoint(i, false); } - /* Restart the daemon with the same arguments as this process */ - /* All file descriptors except stdout, stdin and stderr are supposed to be closed automatically with O_CLOEXEC */ + // Restart the daemon with the same arguments as this process + // All file descriptors except stdout, stdin and stderr are supposed to be closed automatically with O_CLOEXEC { extern char **argv_g; config_restart_cpcd(argv_g); @@ -485,6 +505,7 @@ static void on_unsolicited_status(sl_cpc_system_status_t status) } } } +#endif char* server_core_get_secondary_app_version(void) { @@ -803,7 +824,7 @@ static void process_reset_sequence(bool firmware_reset_mode) case SET_NORMAL_REBOOT_MODE: PRINT_INFO("Connecting to Secondary..."); - /* Send a request to the secondary to set the reboot mode to 'application' */ + // Send a request to the secondary to set the reboot mode to 'application' { const sl_cpc_system_reboot_mode_t reboot_mode = REBOOT_APPLICATION; @@ -815,8 +836,8 @@ static void process_reset_sequence(bool firmware_reset_mode) &reboot_mode, sizeof(reboot_mode), NULL, - 1, /* retry once */ - 2000000, /* 2s between retries*/ + 1, // retry once + 2000000, // 2s between retries SYSTEM_EP_UFRAME); reset_sequence_state = WAIT_NORMAL_REBOOT_MODE_ACK; @@ -828,14 +849,14 @@ static void process_reset_sequence(bool firmware_reset_mode) case WAIT_NORMAL_REBOOT_MODE_ACK: if (set_reset_mode_ack == true) { - /* Now, request a reset */ + // Now, request a reset sl_cpc_system_cmd_reboot(reset_callback, - 5, /* 5 retries */ - 100000 /* 100ms between retries*/); + 5, // 5 retries + 100000); // 100ms between retries reset_sequence_state = WAIT_NORMAL_RESET_ACK; - /* Set it back to false because it will be used for the bootloader reboot sequence */ + // Set it back to false because it will be used for the bootloader reboot sequence set_reset_mode_ack = false; TRACE_RESET("Reboot mode reply received, reset request sent"); @@ -847,7 +868,7 @@ static void process_reset_sequence(bool firmware_reset_mode) if (reset_ack == true) { reset_sequence_state = WAIT_RESET_REASON; - /* Set it back to false because it will be used for the bootloader reboot sequence */ + // Set it back to false because it will be used for the bootloader reboot sequence reset_ack = false; TRACE_RESET("Reset request acknowledged, waiting for device to reset"); @@ -862,8 +883,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_rx_capability_callback, PROP_RX_CAPABILITY, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -876,8 +897,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_protocol_version_callback, PROP_PROTOCOL_VERSION, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -892,8 +913,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_capabilities_callback, PROP_CAPABILITIES, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -908,8 +929,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_secondary_cpc_version_callback, PROP_SECONDARY_CPC_VERSION, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } else { // Fetch bootloader information only if in firmware reset mode @@ -917,8 +938,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_secondary_bootloader_info_callback, PROP_BOOTLOADER_INFO, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } } @@ -932,8 +953,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_secondary_cpc_version_callback, PROP_SECONDARY_CPC_VERSION, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } @@ -949,8 +970,8 @@ static void process_reset_sequence(bool firmware_reset_mode) &primary_version, sizeof(primary_version), NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -963,8 +984,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_secondary_bus_bitrate_callback, PROP_BUS_BITRATE_VALUE, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -976,8 +997,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_secondary_bus_max_bitrate_callback, PROP_BUS_MAX_BITRATE_VALUE, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -989,8 +1010,8 @@ static void process_reset_sequence(bool firmware_reset_mode) sl_cpc_system_cmd_property_get(property_get_secondary_app_version_callback, PROP_SECONDARY_APP_VERSION, NULL, - 5, /* 5 retries */ - 100000, /* 100ms between retries*/ + 5, // 5 retries + 100000, // 100ms between retries SYSTEM_EP_UFRAME); } break; @@ -1033,7 +1054,7 @@ static void process_reboot_enter_bootloader(void) { switch (reboot_into_bootloader_state) { case SET_BOOTLOADER_REBOOT_MODE: - /* Send a request to the secondary to set the reboot mode to 'application' */ + // Send a request to the secondary to set the reboot mode to 'application' { const sl_cpc_system_reboot_mode_t reboot_mode = REBOOT_BOOTLOADER; @@ -1045,8 +1066,8 @@ static void process_reboot_enter_bootloader(void) &reboot_mode, sizeof(reboot_mode), NULL, - 1, /* retry once */ - 2000000, /* 2s between retries*/ + 1, // retry once + 2000000, // 2s between retries SYSTEM_EP_UFRAME); reboot_into_bootloader_state = WAIT_BOOTLOADER_REBOOT_MODE_ACK; @@ -1057,10 +1078,10 @@ static void process_reboot_enter_bootloader(void) case WAIT_BOOTLOADER_REBOOT_MODE_ACK: if (set_reset_mode_ack == true) { - /* Now, request a reset */ + // Now, request a reset sl_cpc_system_cmd_reboot(reset_callback, - 5, /* 5 retries */ - 100000 /* 100ms between retries*/); + 5, // 5 retries + 100000); // 100ms between retries reboot_into_bootloader_state = WAIT_BOOTLOADER_RESET_ACK; diff --git a/server_core/system_endpoint/system.c b/server_core/system_endpoint/system.c index 51cc0d8..b68eaaf 100644 --- a/server_core/system_endpoint/system.c +++ b/server_core/system_endpoint/system.c @@ -15,6 +15,8 @@ * ******************************************************************************/ +#include "config.h" + #include #include #include @@ -75,7 +77,7 @@ typedef struct { sl_status_t error_status; uint8_t command_seq; bool acked; - epoll_private_data_t re_transmit_timer_private_data; //for epoll for timerfd + epoll_private_data_t re_transmit_timer_private_data; // for epoll for timerfd } sl_cpc_system_command_handle_t; typedef struct { @@ -88,8 +90,6 @@ typedef struct { ******************************************************************************/ static sl_slist_node_t *pending_commands; static sl_slist_node_t *commands; -static sl_slist_node_t *retries; -static sl_slist_node_t *commands_in_error; static bool received_remote_sequence_numbers_reset_ack = true; @@ -122,6 +122,10 @@ static void sl_cpc_system_open_endpoint(void) on_iframe_unsolicited); } +/***************************************************************************//** + * Helper function to simplify initializing a command handle. + * Sets the command sequence number and increments it. + ******************************************************************************/ static void sl_cpc_system_init_command_handle(sl_cpc_system_command_handle_t *command_handle, void *on_final_callback, void *on_final_arg, @@ -154,7 +158,7 @@ const char* sl_cpc_system_bootloader_type_to_str(sl_cpc_bootloader_t bootloader) case SL_CPC_BOOTLOADER_EMBER_STANDALONE: return "Ember Standalone"; case SL_CPC_BOOTLOADER_GECKO: - return "Gecko SDK"; + return "Simplicity SDK"; case SL_CPC_BOOTLOADER_UNKNOWN: return "Unknown"; default: @@ -165,9 +169,7 @@ const char* sl_cpc_system_bootloader_type_to_str(sl_cpc_bootloader_t bootloader) void sl_cpc_system_init(void) { sl_slist_init(&commands); - sl_slist_init(&retries); sl_slist_init(&pending_commands); - sl_slist_init(&commands_in_error); sl_slist_init(&prop_last_status_callbacks); sl_cpc_system_open_endpoint(); @@ -197,7 +199,7 @@ static void sl_cpc_system_cmd_abort(sl_cpc_system_command_handle_t *command_hand command_handle->re_transmit_timer_private_data.file_descriptor = 0; } - command_handle->error_status = error; //This will be propagated when calling the callbacks + command_handle->error_status = error; // This will be propagated when calling the callbacks switch (command_handle->command->command_id) { case CMD_SYSTEM_NOOP: @@ -221,7 +223,7 @@ static void sl_cpc_system_cmd_abort(sl_cpc_system_command_handle_t *command_hand } break; - case CMD_SYSTEM_PROP_VALUE_IS: //fall through + case CMD_SYSTEM_PROP_VALUE_IS: // fall through default: BUG("Invalid command_id"); break; @@ -243,7 +245,7 @@ static void sl_cpc_system_cmd_timed_out(const void *frame_data) timed_out_command = (sli_cpc_system_cmd_t *)frame_data; - /* Go through the list of pending requests to find the one for which this reply applies */ + // Go through the list of pending requests to find the one for which this reply applies SL_SLIST_FOR_EACH_ENTRY(commands, command_handle, sl_cpc_system_command_handle_t, node_commands) { if (command_handle->command_seq == timed_out_command->command_seq) { break; @@ -261,7 +263,7 @@ static void sl_cpc_system_cmd_timed_out(const void *frame_data) sl_cpc_system_cmd_abort(command_handle, SL_STATUS_TIMEOUT); - /* Free the command handle and its buffer */ + // Free the command handle and its buffer free(command_handle->command); free(command_handle); @@ -284,7 +286,7 @@ void sl_cpc_system_cmd_poll_acknowledged(const void *frame_data) const struct itimerspec timeout = { .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, .it_value = { .tv_sec = (long int)command_handle->retry_timeout_us / 1000000, .tv_nsec = ((long int)command_handle->retry_timeout_us * 1000) % 1000000000 } }; - /* Setup timeout timer.*/ + // Setup timeout timer. if (command_handle->error_status == SL_STATUS_OK) { timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); @@ -293,8 +295,8 @@ void sl_cpc_system_cmd_poll_acknowledged(const void *frame_data) ret = timerfd_settime(timer_fd, 0, &timeout, NULL); FATAL_SYSCALL_ON(ret < 0); - /* Setup the timer in the server_core epoll set */ - command_handle->re_transmit_timer_private_data.endpoint_number = SL_CPC_ENDPOINT_SYSTEM; //Irrelevant in this scenario + // Setup the timer in the server_core epoll set + command_handle->re_transmit_timer_private_data.endpoint_number = SL_CPC_ENDPOINT_SYSTEM; // Irrelevant in this scenario command_handle->re_transmit_timer_private_data.file_descriptor = timer_fd; command_handle->re_transmit_timer_private_data.callback = on_timer_expired; @@ -325,12 +327,12 @@ void sl_cpc_system_cmd_noop(sl_cpc_system_noop_cmd_callback_t on_noop_reply, { sl_cpc_system_command_handle_t *command_handle; - /* Malloc the command handle and the command buffer */ + // Malloc the command handle and the command buffer { command_handle = zalloc(sizeof(sl_cpc_system_command_handle_t)); FATAL_ON(command_handle == NULL); - command_handle->command = zalloc(sizeof(sli_cpc_system_cmd_t)); //noop has nothing in the 'payload field' + command_handle->command = zalloc(sizeof(sli_cpc_system_cmd_t)); // noop has nothing in the 'payload field' FATAL_ON(command_handle->command == NULL); } @@ -341,7 +343,7 @@ void sl_cpc_system_cmd_noop(sl_cpc_system_noop_cmd_callback_t on_noop_reply, retry_timeout_us, SYSTEM_EP_IFRAME); - /* Fill the system endpoint command buffer */ + // Fill the system endpoint command buffer { sli_cpc_system_cmd_t *tx_command = command_handle->command; @@ -368,7 +370,7 @@ void sl_cpc_system_cmd_reboot(sl_cpc_system_reset_cmd_callback_t on_reset_reply, { sl_cpc_system_command_handle_t *command_handle; - /* Malloc the command handle and the command buffer */ + // Malloc the command handle and the command buffer { command_handle = zalloc(sizeof(sl_cpc_system_command_handle_t)); FATAL_ON(command_handle == NULL); @@ -384,7 +386,7 @@ void sl_cpc_system_cmd_reboot(sl_cpc_system_reset_cmd_callback_t on_reset_reply, retry_timeout_us, SYSTEM_EP_UFRAME); - /* Fill the system endpoint command buffer */ + // Fill the system endpoint command buffer { sli_cpc_system_cmd_t *tx_command = command_handle->command; @@ -415,18 +417,15 @@ bool sl_cpc_system_received_unnumbered_acknowledgement(void) ******************************************************************************/ void sl_cpc_system_on_unnumbered_acknowledgement(void) { - sl_slist_node_t *item; sl_cpc_system_command_handle_t *command_handle; TRACE_SYSTEM("Received sequence numbers reset acknowledgement"); received_remote_sequence_numbers_reset_ack = true; // Send any pending commands - item = sl_slist_pop(&pending_commands); - while (item != NULL) { - command_handle = SL_SLIST_ENTRY(item, sl_cpc_system_command_handle_t, node_commands); + while (!sl_slist_is_empty(pending_commands)) { + command_handle = SL_SLIST_ENTRY(sl_slist_pop(&pending_commands), sl_cpc_system_command_handle_t, node_commands); write_command(command_handle); - item = sl_slist_pop(&pending_commands); } } @@ -436,7 +435,6 @@ void sl_cpc_system_on_unnumbered_acknowledgement(void) static void on_unnumbered_acknowledgement_timeout(epoll_private_data_t *private_data) { int ret; - sl_slist_node_t *item; int timer_fd = private_data->file_descriptor; sl_cpc_system_command_handle_t *command_handle = container_of(private_data, sl_cpc_system_command_handle_t, @@ -454,7 +452,7 @@ static void on_unnumbered_acknowledgement_timeout(epoll_private_data_t *private_ TRACE_SYSTEM("Remote is unresponsive, retrying..."); - /* Ack the timer */ + // Ack the timer { uint64_t expiration; ssize_t retval; @@ -465,20 +463,18 @@ static void on_unnumbered_acknowledgement_timeout(epoll_private_data_t *private_ FATAL_ON(retval != sizeof(expiration)); - WARN_ON(expiration != 1); /* we missed a timeout*/ + WARN_ON(expiration != 1); // we missed a timeout } - /* Drop any pending commands to prevent accumulation*/ - item = sl_slist_pop(&pending_commands); - while (item != NULL) { - command_handle = SL_SLIST_ENTRY(item, sl_cpc_system_command_handle_t, node_commands); + // Drop any pending commands to prevent accumulation + while (!sl_slist_is_empty(pending_commands)) { + command_handle = SL_SLIST_ENTRY(sl_slist_pop(&pending_commands), sl_cpc_system_command_handle_t, node_commands); if (command_handle->command->command_id != CMD_SYSTEM_INVALID) { sl_cpc_system_cmd_abort(command_handle, SL_STATUS_ABORT); } free(command_handle->command); free(command_handle); - item = sl_slist_pop(&pending_commands); } ret = core_write(SL_CPC_ENDPOINT_SYSTEM, NULL, 0, SL_CPC_FLAG_UNNUMBERED_RESET_COMMAND); @@ -516,7 +512,7 @@ void sl_cpc_system_request_sequence_reset(void) command_handle = zalloc(sizeof(sl_cpc_system_command_handle_t)); FATAL_ON(command_handle == NULL); - /* Setup the timer in the server_core epoll set */ + // Setup the timer in the server_core epoll set command_handle->re_transmit_timer_private_data.file_descriptor = timer_fd; command_handle->re_transmit_timer_private_data.callback = on_unnumbered_acknowledgement_timeout; @@ -533,13 +529,11 @@ void sl_cpc_system_request_sequence_reset(void) ******************************************************************************/ void sl_cpc_system_reset_system_endpoint(void) { - sl_slist_node_t *item; sl_cpc_system_command_handle_t *command_handle; // Abort any pending commands - item = sl_slist_pop(&commands); - while (item != NULL) { - command_handle = SL_SLIST_ENTRY(item, sl_cpc_system_command_handle_t, node_commands); + while (!sl_slist_is_empty(commands)) { + command_handle = SL_SLIST_ENTRY(sl_slist_pop(&commands), sl_cpc_system_command_handle_t, node_commands); if (command_handle->command->command_id != CMD_SYSTEM_INVALID) { WARN("Dropping system command id #%d seq#%d", command_handle->command->command_id, command_handle->command_seq); @@ -549,7 +543,6 @@ void sl_cpc_system_reset_system_endpoint(void) // Command payload will be freed once we close the endpoint free(command_handle->command); free(command_handle); - item = sl_slist_pop(&commands); } // Close the system endpoint @@ -571,7 +564,7 @@ void sl_cpc_system_cmd_property_get(sl_cpc_system_property_get_set_cmd_callback_ { sl_cpc_system_command_handle_t *command_handle; - /* Malloc the command handle and the command buffer */ + // Malloc the command handle and the command buffer { const size_t property_get_buffer_size = sizeof(sli_cpc_system_cmd_t) + sizeof(sli_cpc_property_id_t); @@ -580,7 +573,7 @@ void sl_cpc_system_cmd_property_get(sl_cpc_system_property_get_set_cmd_callback_ // Allocate a buffer and pad it to 8 bytes because memcpy reads in chunks of 8. // If we don't pad, Valgrind will complain. - command_handle->command = zalloc(PAD_TO_8_BYTES(property_get_buffer_size)); //property-get has the property id as payload + command_handle->command = zalloc(PAD_TO_8_BYTES(property_get_buffer_size)); // property-get has the property id as payload FATAL_ON(command_handle->command == NULL); } @@ -591,7 +584,7 @@ void sl_cpc_system_cmd_property_get(sl_cpc_system_property_get_set_cmd_callback_ retry_timeout_us, frame_type); - /* Fill the system endpoint command buffer */ + // Fill the system endpoint command buffer { sli_cpc_system_cmd_t *tx_command = command_handle->command; sli_cpc_system_property_cmd_t *tx_property_command = (sli_cpc_system_property_cmd_t *) tx_command->payload; @@ -636,7 +629,7 @@ void sl_cpc_system_cmd_property_set(sl_cpc_system_property_get_set_cmd_callback_ // Allocate a buffer and pad it to 8 bytes because memcpy reads in chunks of 8. // If we don't pad, Valgrind will complain. - command_handle->command = zalloc(PAD_TO_8_BYTES(property_get_buffer_size)); //property-get has the property id as payload + command_handle->command = zalloc(PAD_TO_8_BYTES(property_get_buffer_size)); // property-get has the property id as payload FATAL_ON(command_handle->command == NULL); } @@ -647,7 +640,7 @@ void sl_cpc_system_cmd_property_set(sl_cpc_system_property_get_set_cmd_callback_ retry_timeout_us, frame_type); - /* Fill the system endpoint command buffer */ + // Fill the system endpoint command buffer { sli_cpc_system_cmd_t *tx_command = command_handle->command; sli_cpc_system_property_cmd_t *tx_property_command = (sli_cpc_system_property_cmd_t *) tx_command->payload; @@ -770,7 +763,7 @@ static void on_final_property_is(sl_cpc_system_command_handle_t * command_handle size_t value_length = system_cmd->length - sizeof(sli_cpc_system_property_cmd_t); callback(system_property_cmd.property_id, - (uint8_t *)system_property_cmd_payload, /* discard const qualifier */ + (uint8_t *)system_property_cmd_payload, // discard const qualifier value_length, command_handle->on_final_arg, command_handle->error_status); @@ -802,12 +795,12 @@ static void on_reply(uint8_t endpoint_id, system_cmd_payload_length = answer_length - sizeof(system_cmd); FATAL_ON(system_cmd.length != system_cmd_payload_length); - /* Go through the list of pending requests to find the one for which this reply applies */ + // Go through the list of pending requests to find the one for which this reply applies SL_SLIST_FOR_EACH_ENTRY(commands, command_handle, sl_cpc_system_command_handle_t, node_commands) { if (command_handle->command_seq == system_cmd.command_seq) { - TRACE_SYSTEM("Processing command seq#%d of type %d", system_cmd.command_seq, frame_type); + TRACE_SYSTEM("Processing command seq#%d of type %zd", (int)system_cmd.command_seq, frame_type); - /* Stop and close the retransmit timer */ + // Stop and close the retransmit timer if (frame_type == SLI_CPC_HDLC_FRAME_TYPE_UNNUMBERED || (frame_type == SLI_CPC_HDLC_FRAME_TYPE_INFORMATION && command_handle->acked == true)) { BUG_ON(command_handle->re_transmit_timer_private_data.file_descriptor <= 0); @@ -816,7 +809,7 @@ static void on_reply(uint8_t endpoint_id, command_handle->re_transmit_timer_private_data.file_descriptor = 0; } - /* Call the appropriate callback */ + // Call the appropriate callback if (frame_type == SLI_CPC_HDLC_FRAME_TYPE_UNNUMBERED) { BUG_ON(command_handle->frame_type == SYSTEM_EP_IFRAME); switch (system_cmd.command_id) { @@ -854,7 +847,7 @@ static void on_reply(uint8_t endpoint_id, FATAL("Invalid frame_type"); } - /* Cleanup this command now that it's been serviced */ + // Cleanup this command now that it's been serviced sl_slist_remove(&commands, &command_handle->node_commands); free(command_handle->command); free(command_handle); @@ -972,9 +965,9 @@ static void on_iframe_unsolicited(uint8_t endpoint_id, const void* data, size_t data_len -= 4; if (system_property_cmd.property_id >= PROP_ENDPOINT_STATE_0 && system_property_cmd.property_id <= PROP_ENDPOINT_STATE_255) { - uint8_t endpoint_id = PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id); + uint8_t ep_id = PROPERTY_ID_TO_EP_ID(system_property_cmd.property_id); - core_on_unsolicited_endpoint_state(endpoint_id, u8_data, data_len); + core_on_unsolicited_endpoint_state(ep_id, u8_data, data_len); } } } @@ -991,7 +984,7 @@ static void on_timer_expired(epoll_private_data_t *private_data) TRACE_SYSTEM("Command ID #%u SEQ #%u timer expired", command_handle->command->command_id, command_handle->command->command_seq); - /* Ack the timer */ + // Ack the timer { uint64_t expiration; ssize_t retval; @@ -1002,7 +995,7 @@ static void on_timer_expired(epoll_private_data_t *private_data) FATAL_ON(retval != sizeof(expiration)); - WARN_ON(expiration != 1); /* we missed a timeout*/ + WARN_ON(expiration != 1); // we missed a timeout } if (!command_handle->retry_forever) { @@ -1012,7 +1005,7 @@ static void on_timer_expired(epoll_private_data_t *private_data) if (command_handle->retry_count > 0 || command_handle->retry_forever) { sl_slist_remove(&commands, &command_handle->node_commands); - command_handle->error_status = SL_STATUS_IN_PROGRESS; //at least one timer retry occurred + command_handle->error_status = SL_STATUS_IN_PROGRESS; // at least one timer retry occurred write_command(command_handle); @@ -1068,7 +1061,7 @@ static void write_command(sl_cpc_system_command_handle_t *command_handle) TRACE_SYSTEM("Submitted command_id #%d command_seq #%d", command_handle->command->command_id, command_handle->command_seq); if (command_handle->frame_type == SYSTEM_EP_UFRAME) { - /* Setup timeout timer.*/ + // Setup timeout timer. { const struct itimerspec timeout = { .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, .it_value = { .tv_sec = (long int)command_handle->retry_timeout_us / 1000000, .tv_nsec = ((long int)command_handle->retry_timeout_us * 1000) % 1000000000 } }; @@ -1077,15 +1070,15 @@ static void write_command(sl_cpc_system_command_handle_t *command_handle) FATAL_SYSCALL_ON(timer_fd < 0); - int ret = timerfd_settime(timer_fd, - 0, - &timeout, - NULL); + ret = timerfd_settime(timer_fd, + 0, + &timeout, + NULL); FATAL_SYSCALL_ON(ret < 0); } - /* Setup the timer in the server_core epoll set */ + // Setup the timer in the server_core epoll set { command_handle->re_transmit_timer_private_data.endpoint_number = SL_CPC_ENDPOINT_SYSTEM; command_handle->re_transmit_timer_private_data.file_descriptor = timer_fd; @@ -1098,16 +1091,13 @@ static void write_command(sl_cpc_system_command_handle_t *command_handle) void sl_cpc_system_cleanup(void) { - sl_slist_node_t *item; prop_last_status_callback_list_item_t *callback_list_item; TRACE_RESET("Server core cleanup"); - item = sl_slist_pop(&prop_last_status_callbacks); - while (item != NULL) { - callback_list_item = SL_SLIST_ENTRY(item, prop_last_status_callback_list_item_t, node); + while (!sl_slist_is_empty(prop_last_status_callbacks)) { + callback_list_item = SL_SLIST_ENTRY(sl_slist_pop(&prop_last_status_callbacks), prop_last_status_callback_list_item_t, node); free(callback_list_item); - item = sl_slist_pop(&pending_commands); } // Close the system endpoint diff --git a/server_core/system_endpoint/system.h b/server_core/system_endpoint/system.h index 11876d4..d48ef2e 100644 --- a/server_core/system_endpoint/system.h +++ b/server_core/system_endpoint/system.h @@ -438,7 +438,7 @@ SL_ENUM_GENERIC(sl_cpc_bootloader_t, uint32_t) SL_CPC_BOOTLOADER_NONE = 0, ///< No bootloader SL_CPC_BOOTLOADER_EMBER_APPLICATION = 1, ///< Ember bootloader in application mode SL_CPC_BOOTLOADER_EMBER_STANDALONE = 2, ///< Ember bootloader in standalone mode - SL_CPC_BOOTLOADER_GECKO = 3, ///< Gecko SDK bootloader + SL_CPC_BOOTLOADER_GECKO = 3, ///< Simplicity SDK bootloader SL_CPC_BOOTLOADER_UNKNOWN = 4, ///< Unknown, third party bootloader? };