diff --git a/.github/workflows/build-check.yaml b/.github/workflows/build-check.yaml index 144431572..be3e52d7e 100644 --- a/.github/workflows/build-check.yaml +++ b/.github/workflows/build-check.yaml @@ -34,13 +34,15 @@ jobs: check_format: name: Check codebase format with clang-format - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout code uses: actions/checkout@v4 - name: Run clang-format dry-run - run: find include/ src/ tests/ examples/ -iname "*.ino" -o -iname "*.h" -o -iname "*.c" | xargs clang-format -n -Werror + run: | + clang-format --version + find include/ src/ tests/ examples/ -iname "*.ino" -o -iname "*.h" -o -iname "*.c" | xargs clang-format -n -Werror c99_build: name: Check c99 compilation diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 01fb354b2..e72186dbd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,6 +59,7 @@ jobs: - name: Bump and tag project run: bash ci/scripts/bump-and-tag.bash env: + LIVE_RUN: ${{ inputs.live-run || false }} VERSION: ${{ steps.create-release-branch.outputs.version }} GIT_USER_NAME: eclipse-zenoh-bot GIT_USER_EMAIL: eclipse-zenoh-bot@users.noreply.github.com @@ -150,6 +151,19 @@ jobs: name: ${{ steps.build-linux.outputs.archive-deb }} path: ${{ steps.build-linux.outputs.archive-deb }} + debian: + name: Publish Debian packages + needs: [tag, build-linux] + uses: eclipse-zenoh/ci/.github/workflows/release-crates-debian.yml@main + with: + no-build: true + live-run: ${{ inputs.live-run || false }} + version: ${{ needs.tag.outputs.version }} + repo: ${{ github.repository }} + branch: ${{ needs.tag.outputs.branch }} + installation-test: false + secrets: inherit + eclipse: needs: [tag, build-macos, build-linux] runs-on: ubuntu-latest @@ -160,8 +174,8 @@ jobs: version: ${{ needs.tag.outputs.version }} ssh-host: genie.zenoh@projects-storage.eclipse.org ssh-host-path: /home/data/httpd/download.eclipse.org/zenoh/zenoh-pico - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - ssh-passphrase: ${{ secrets.SSH_PASSPHRASE }} + ssh-private-key: ${{ secrets.ORG_GPG_PRIVATE_KEY }} + ssh-passphrase: ${{ secrets.ORG_GPG_PASSPHRASE }} archive-patterns: '.*\.zip' github: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f5d01971..8f2df3631 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,17 +39,6 @@ configure_file( @ONLY ) -set(project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") -if(NOT DEFINED PROJECT_VERSION_TWEAK) - set(project_version "${project_version}") -elseif(PROJECT_VERSION_TWEAK EQUAL 0) - set(project_version "${project_version}-dev") -elseif(PROJECT_VERSION_TWEAK GREATER 1) - set(project_version "${project_version}-pre.${PROJECT_VERSION_TWEAK}") -endif() -status_print(project_version) - - include(CMakePackageConfigHelpers) include(GNUInstallDirs) @@ -69,6 +58,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") endif() elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") if(WITH_ZEPHYR) + set(PACKAGING OFF) # no packaging support for zephyr set(BUILD_SHARED_LIBS "OFF") endif() endif() @@ -115,44 +105,83 @@ else() endif() endif() +if (PACKAGING) + set(PICO_STATIC ON) + set(PICO_SHARED ON) +endif() +if(BUILD_SHARED_LIBS) + set(PICO_SHARED ON) +else() + set(PICO_STATIC ON) +endif() + set(Libname "zenohpico") -add_library(${Libname}) -add_library(zenohpico::lib ALIAS ${Libname}) +if(PICO_STATIC) + add_library(${Libname}_static STATIC) + set_target_properties(${Libname}_static PROPERTIES OUTPUT_NAME ${Libname}) + add_library(zenohpico::static ALIAS ${Libname}_static) +endif() +if(PICO_SHARED) + add_library(${Libname}_shared SHARED) + set_target_properties(${Libname}_shared PROPERTIES OUTPUT_NAME ${Libname}) + add_library(zenohpico::shared ALIAS ${Libname}_shared) +endif() +if(BUILD_SHARED_LIBS) + add_library(zenohpico::lib ALIAS ${Libname}_shared) +else() + add_library(zenohpico::lib ALIAS ${Libname}_static) +endif() -function(add_definition value) +function(pico_add_compile_definition value) add_definitions(-D${value}) - target_compile_definitions(${Libname} PUBLIC ${value}) + if(PICO_STATIC) + target_compile_definitions(zenohpico_static PUBLIC ${value}) + endif() + if(PICO_SHARED) + target_compile_definitions(zenohpico_shared PUBLIC ${value}) + endif() endfunction() -add_definition(ZENOH_C_STANDARD=${CMAKE_C_STANDARD}) +function(pico_target_link_library value) + if(PICO_STATIC) + target_link_libraries(zenohpico_static ${value}) + endif() + if(PICO_SHARED) + target_link_libraries(zenohpico_shared ${value}) + endif() +endfunction() -# while in development, use timestamp for patch version: -string(TIMESTAMP PROJECT_VERSION_PATCH "%Y%m%ddev") -set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +pico_add_compile_definition(ZENOH_C_STANDARD=${CMAKE_C_STANDARD}) + +if (NOT CMAKE_BUILD_TYPE MATCHES "RELEASE" OR "Release") + # while in development, use timestamp for patch version: + string(TIMESTAMP PROJECT_VERSION_PATCH "%Y%m%ddev") + set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +endif() set(CHECK_THREADS "ON") # System definition if(CMAKE_SYSTEM_NAME MATCHES "Linux") - add_definition(ZENOH_LINUX) + pico_add_compile_definition(ZENOH_LINUX) elseif(POSIX_COMPATIBLE) - add_definition(ZENOH_LINUX) + pico_add_compile_definition(ZENOH_LINUX) set(CHECK_THREADS "OFF") elseif(CMAKE_SYSTEM_NAME MATCHES "BSD") - add_definition(ZENOH_BSD) + pico_add_compile_definition(ZENOH_BSD) elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_definition(ZENOH_MACOS) + pico_add_compile_definition(ZENOH_MACOS) set(MACOSX_RPATH "ON") elseif(CMAKE_SYSTEM_NAME MATCHES "Emscripten") - add_definition(ZENOH_EMSCRIPTEN) + pico_add_compile_definition(ZENOH_EMSCRIPTEN) elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") - add_definition(ZENOH_WINDOWS) - add_definition(_CRT_SECURE_NO_WARNINGS) + pico_add_compile_definition(ZENOH_WINDOWS) + pico_add_compile_definition(_CRT_SECURE_NO_WARNINGS) elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") if(WITH_ZEPHYR) - add_definition(ZENOH_ZEPHYR) + pico_add_compile_definition(ZENOH_ZEPHYR) elseif(WITH_FREERTOS_PLUS_TCP) - add_definition(ZENOH_FREERTOS_PLUS_TCP) + pico_add_compile_definition(ZENOH_FREERTOS_PLUS_TCP) endif() else() message(FATAL_ERROR "zenoh-pico is not yet available on ${CMAKE_SYSTEM_NAME} platform") @@ -162,18 +191,18 @@ endif() # Compiler definition message("Compilers in use: ${CMAKE_C_COMPILER_ID}, ${CMAKE_CXX_COMPILER_ID}") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - add_definition(ZENOH_COMPILER_CLANG) + pico_add_compile_definition(ZENOH_COMPILER_CLANG) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "GNU") - add_definition(ZENOH_COMPILER_GCC) + pico_add_compile_definition(ZENOH_COMPILER_GCC) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" OR CMAKE_C_COMPILER_ID STREQUAL "Intel") - add_definition(ZENOH_COMPILER_INTEL) + pico_add_compile_definition(ZENOH_COMPILER_INTEL) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL "MSVC") - add_definition(ZENOH_COMPILER_MSVC) + pico_add_compile_definition(ZENOH_COMPILER_MSVC) else() - add_definition(ZENOH_COMPILER_OTHER) + pico_add_compile_definition(ZENOH_COMPILER_OTHER) endif() -add_definition(ZENOH_DEBUG=${ZENOH_DEBUG}) +pico_add_compile_definition(ZENOH_DEBUG=${ZENOH_DEBUG}) # Zenoh pico feature configuration options @@ -204,6 +233,10 @@ set(Z_FEATURE_MULTICAST_TRANSPORT 1 CACHE STRING "Toggle multicast transport") set(Z_FEATURE_UNICAST_TRANSPORT 1 CACHE STRING "Toggle unicast transport") set(Z_FEATURE_RAWETH_TRANSPORT 0 CACHE STRING "Toggle raw ethernet transport") set(Z_FEATURE_TCP_NODELAY 1 CACHE STRING "Toggle TCP_NODELAY") +set(Z_FEATURE_LOCAL_SUBSCRIBER 0 CACHE STRING "Toggle local subscriptions") +set(Z_FEATURE_PUBLISHER_SESSION_CHECK 1 CACHE STRING "Toggle publisher session check") +set(Z_FEATURE_BATCHING 1 CACHE STRING "Toggle batching") +set(Z_FEATURE_RX_CACHE 0 CACHE STRING "Toggle RX_CACHE") add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ @@ -266,10 +299,19 @@ file(GLOB_RECURSE PublicHeaders "include/zenoh-pico/utils/*.h" "include/zenoh-pico/config.h" ) -target_include_directories(${Libname} - PUBLIC - $ - $) +if(PICO_STATIC) + target_include_directories(${Libname}_static + PUBLIC + $ + $) +endif() +if(PICO_SHARED) + target_include_directories(${Libname}_shared + PUBLIC + $ + $) +endif() + file(GLOB_RECURSE Sources "src/api/*.c" @@ -303,18 +345,24 @@ endif() set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) link_directories(${LIBRARY_OUTPUT_PATH}) -target_sources(${Libname} PRIVATE ${Sources}) +if(PICO_STATIC) + target_sources(zenohpico_static PRIVATE ${Sources}) +endif() +if(PICO_SHARED) + target_sources(zenohpico_shared PRIVATE ${Sources}) +endif() if(CHECK_THREADS) - target_link_libraries(${Libname} Threads::Threads) + pico_target_link_library(Threads::Threads) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux") - target_link_libraries(${Libname} rt) + pico_target_link_library(rt) endif() if(CMAKE_SYSTEM_NAME MATCHES "Windows") - target_link_libraries(${Libname} Ws2_32 Iphlpapi) + pico_target_link_library(Ws2_32) + pico_target_link_library(Iphlpapi) endif() # @@ -334,12 +382,22 @@ message(STATUS "Build tools: ${BUILD_TOOLS}") message(STATUS "Build tests: ${BUILD_TESTING}") message(STATUS "Build integration: ${BUILD_INTEGRATION}") -install(TARGETS ${Libname} +set(PICO_LIBS "") +if(PICO_STATIC) + list(APPEND PICO_LIBS zenohpico_static) +endif() +if(PICO_SHARED) + list(APPEND PICO_LIBS zenohpico_shared) +endif() + +install(TARGETS ${PICO_LIBS} EXPORT zenohpicoTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin - COMPONENT Library + LIBRARY COMPONENT Runtime + ARCHIVE COMPONENT Dev + RUNTIME COMPONENT Runtime ) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h DESTINATION include @@ -373,17 +431,18 @@ install( "${CMAKE_CURRENT_BINARY_DIR}/zenohpicoConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" CONFIGURATIONS ${configurations} - COMPONENT dev) + COMPONENT Dev) # Generate Targets.cmake install( EXPORT zenohpicoTargets NAMESPACE zenohpico:: - DESTINATION "${CMAKE_INSTALL_CMAKEDIR}") + DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" + COMPONENT Dev) if(UNIX) configure_file("${CMAKE_SOURCE_DIR}/zenohpico.pc.in" "${CMAKE_SOURCE_DIR}/zenohpico.pc" @ONLY) - install(FILES "${CMAKE_SOURCE_DIR}/zenohpico.pc" CONFIGURATIONS Release RelWithDebInfo DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + install(FILES "${CMAKE_SOURCE_DIR}/zenohpico.pc" CONFIGURATIONS Release RelWithDebInfo DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT Dev) endif() if(BUILD_EXAMPLES) @@ -394,7 +453,7 @@ if(UNIX OR MSVC) if(BUILD_TOOLS) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tools) add_executable(z_keyexpr_canonizer ${PROJECT_SOURCE_DIR}/tools/z_keyexpr_canonizer.c) - target_link_libraries(z_keyexpr_canonizer ${Libname}) + target_link_libraries(z_keyexpr_canonizer zenohpico::lib) endif() if(BUILD_TESTING AND CMAKE_C_STANDARD MATCHES "11") @@ -418,23 +477,23 @@ if(UNIX OR MSVC) add_executable(z_api_encoding_test ${PROJECT_SOURCE_DIR}/tests/z_api_encoding_test.c) add_executable(z_refcount_test ${PROJECT_SOURCE_DIR}/tests/z_refcount_test.c) - target_link_libraries(z_data_struct_test ${Libname}) - target_link_libraries(z_channels_test ${Libname}) - target_link_libraries(z_collections_test ${Libname}) - target_link_libraries(z_endpoint_test ${Libname}) - target_link_libraries(z_iobuf_test ${Libname}) - target_link_libraries(z_msgcodec_test ${Libname}) - target_link_libraries(z_keyexpr_test ${Libname}) - target_link_libraries(z_api_null_drop_test ${Libname}) - target_link_libraries(z_api_double_drop_test ${Libname}) - target_link_libraries(z_test_fragment_tx ${Libname}) - target_link_libraries(z_test_fragment_rx ${Libname}) - target_link_libraries(z_perf_tx ${Libname}) - target_link_libraries(z_perf_rx ${Libname}) - target_link_libraries(z_bytes_test ${Libname}) - target_link_libraries(z_api_bytes_test ${Libname}) - target_link_libraries(z_api_encoding_test ${Libname}) - target_link_libraries(z_refcount_test ${Libname}) + target_link_libraries(z_data_struct_test zenohpico::lib) + target_link_libraries(z_channels_test zenohpico::lib) + target_link_libraries(z_collections_test zenohpico::lib) + target_link_libraries(z_endpoint_test zenohpico::lib) + target_link_libraries(z_iobuf_test zenohpico::lib) + target_link_libraries(z_msgcodec_test zenohpico::lib) + target_link_libraries(z_keyexpr_test zenohpico::lib) + target_link_libraries(z_api_null_drop_test zenohpico::lib) + target_link_libraries(z_api_double_drop_test zenohpico::lib) + target_link_libraries(z_test_fragment_tx zenohpico::lib) + target_link_libraries(z_test_fragment_rx zenohpico::lib) + target_link_libraries(z_perf_tx zenohpico::lib) + target_link_libraries(z_perf_rx zenohpico::lib) + target_link_libraries(z_bytes_test zenohpico::lib) + target_link_libraries(z_api_bytes_test zenohpico::lib) + target_link_libraries(z_api_encoding_test zenohpico::lib) + target_link_libraries(z_refcount_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/modularity.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/modularity.py COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/raweth.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/raweth.py COPYONLY) @@ -465,7 +524,7 @@ if(UNIX OR MSVC) if(CMAKE_C_STANDARD MATCHES "11") add_executable(z_peer_multicast_test ${PROJECT_SOURCE_DIR}/tests/z_peer_multicast_test.c) - target_link_libraries(z_peer_multicast_test ${Libname}) + target_link_libraries(z_peer_multicast_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/multicast.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/multicast.sh COPYONLY) @@ -482,9 +541,9 @@ if(UNIX OR MSVC) add_executable(z_api_alignment_test ${PROJECT_SOURCE_DIR}/tests/z_api_alignment_test.c) add_executable(z_session_test ${PROJECT_SOURCE_DIR}/tests/z_session_test.c) - target_link_libraries(z_client_test ${Libname}) - target_link_libraries(z_api_alignment_test ${Libname}) - target_link_libraries(z_session_test ${Libname}) + target_link_libraries(z_client_test zenohpico::lib) + target_link_libraries(z_api_alignment_test zenohpico::lib) + target_link_libraries(z_session_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/routed.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/routed.sh COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/api.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/api.sh COPYONLY) @@ -499,37 +558,44 @@ endif() # For packaging if(PACKAGING) + set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/packages") - set(CPACK_COMPONENTS_ALL Library Headers) - set(CPACK_COMPONENT_LIBRARY_GROUP "lib") + set(CPACK_COMPONENTS_ALL Runtime Headers Dev) + + set(CPACK_COMPONENT_RUNTIME_GROUP "lib") set(CPACK_COMPONENT_HEADERS_GROUP "dev") - set(CPACK_COMPONENT_HEADERS_DEPENDS Library) + set(CPACK_COMPONENT_DEV_GROUP "dev") + set(CPACK_COMPONENT_HEADERS_DEPENDS Runtime) + set(CPACK_COMPONENT_DEV_DEPENDS Runtime) set(CPACK_PACKAGE_CHECKSUM MD5) set(CPACK_PACKAGE_VENDOR "The Eclipse Foundation") - set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) - set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) - set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) - set(CPACK_COMPONENT_LIB_DESCRIPTION "The C client library for Eclipse zenoh targeting pico devices") - set(CPACK_COMPONENT_DEV_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION} - devel files") + if(NOT CPACK_PACKAGE_VERSION) + set(SEM_VER "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + if(PROJECT_VERSION_TWEAK STREQUAL "") + set(CPACK_PACKAGE_VERSION ${SEM_VER}) + elseif(PROJECT_VERSION_TWEAK EQUAL 0) + set(CPACK_PACKAGE_VERSION "${SEM_VER}~dev-1") + elseif(PROJECT_VERSION_TWEAK GREATER 0) + set(CPACK_PACKAGE_VERSION "${SEM_VER}~pre.${PROJECT_VERSION_TWEAK}-1") + endif() + endif() + set(CPACK_COMPONENT_RUNTIME_DESCRIPTION "The C client library for Eclipse zenoh targeting pico devices") + set(CPACK_COMPONENT_HEADERS_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION} - headers") + set(CPACK_COMPONENT_DEV_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION} - config files") # Sources package set(CPACK_SOURCE_GENERATOR "TGZ") - set(CPACK_SOURCE_IGNORE_FILES "/.git/;/.github/;/build/;/crossbuilds/") - set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-src-${PROJECT_VERSION}") + set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-src-${project_version}") + + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") if(PACKAGING MATCHES "DEB") if(NOT DEBARCH) - execute_process( - COMMAND dpkg --print-architecture - OUTPUT_VARIABLE DEBARCH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + set(DEBARCH ${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}) endif() - message(STATUS "Configure DEB packaging for Linux ${DEBARCH}") - if(CPACK_GENERATOR) set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB") else() @@ -541,9 +607,10 @@ if(PACKAGING) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEBARCH}) set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) - set(CPACK_DEBIAN_LIB_PACKAGE_NAME ${PROJECT_NAME}) # avoid "-lib" suffix for "lib" package + set(CPACK_DEBIAN_LIB_PACKAGE_NAME "lib${CPACK_PACKAGE_NAME}") set(CPACK_DEBIAN_LIB_PACKAGE_DEPENDS "libc6 (>=2.12)") - set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIB_PACKAGE_NAME} (=${PROJECT_VERSION})") + set(CPACK_DEBIAN_DEV_PACKAGE_NAME "lib${CPACK_PACKAGE_NAME}-dev") + set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIB_PACKAGE_NAME} (=${CPACK_PACKAGE_VERSION})") endif() if(PACKAGING MATCHES "RPM") @@ -551,8 +618,6 @@ if(PACKAGING) set(RPMARCH ${CMAKE_SYSTEM_PROCESSOR}) endif() - message(STATUS "Configure RPM packaging for Linux ${RPMARCH}") - if(CPACK_GENERATOR) set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM") else() @@ -563,8 +628,8 @@ if(PACKAGING) set(CPACK_RPM_PACKAGE_ARCHITECTURE ${RPMARCH}) set(CPACK_RPM_COMPONENT_INSTALL ON) set(CPACK_RPM_FILE_NAME RPM-DEFAULT) - set(CPACK_RPM_LIB_PACKAGE_NAME ${PROJECT_NAME}) # avoid "-lib" suffix for "lib" package - set(CPACK_RPM_DEV_PACKAGE_REQUIRES "${CPACK_RPM_LIB_PACKAGE_NAME} = ${PROJECT_VERSION}") + set(CPACK_RPM_LIB_PACKAGE_NAME ${CPACK_PACKAGE_NAME}) # avoid "-lib" suffix for "lib" package + set(CPACK_RPM_DEV_PACKAGE_REQUIRES "${CPACK_RPM_LIB_PACKAGE_NAME} = ${CPACK_PACKAGE_VERSION}") endif() include(CPack) diff --git a/GNUmakefile b/GNUmakefile index fcbbbb4d8..1ed16502e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -63,7 +63,7 @@ Z_FEATURE_RAWETH_TRANSPORT?=0 # Buffer sizes FRAG_MAX_SIZE?=300000 BATCH_UNICAST_SIZE?=65535 -BATCH_MULTICAST_SIZE?=8096 +BATCH_MULTICAST_SIZE?=8192 # zenoh-pico/ directory ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) @@ -115,33 +115,33 @@ endif crossbuild: check-docker @echo "FROM dockcross/$(CROSSIMG)\nRUN apt-get update && apt-get -y install rpm" | docker build -t $(CROSSIMG_PREFIX)$(CROSSIMG) - docker run --rm -v $(ROOT_DIR):/workdir -w /workdir $(CROSSIMG_PREFIX)$(CROSSIMG) bash -c "\ - cmake $(CMAKE_OPT) -DPACKAGING=DEB,RPM -DDEBARCH=$(DEBARCH) -DRPMARCH=$(RPMARCH) -B$(CROSSBUILD_DIR)/$(CROSSIMG) && \ + cmake $(CMAKE_OPT) -DCPACK_PACKAGE_NAME=$(PACKAGE_NAME) -DPACKAGING=DEB,RPM -DDEBARCH=$(DEBARCH) -DRPMARCH=$(RPMARCH) -B$(CROSSBUILD_DIR)/$(CROSSIMG) && \ make VERBOSE=1 -C$(CROSSBUILD_DIR)/$(CROSSIMG) all package" docker rmi $(CROSSIMG_PREFIX)$(CROSSIMG) linux-armv5: - CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild linux-armv6: - CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild + PACKAGE_NAME="zenohpico-armv6" CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild linux-armv7: - CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild linux-armv7a: - CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild + PACKAGE_NAME="zenohpico-armv7a" CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild linux-arm64: - CROSSIMG=$@ DEBARCH=arm64 RPMARCH=aarch64 make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=arm64 RPMARCH=aarch64 make crossbuild linux-mips: - CROSSIMG=$@ DEBARCH=mips RPMARCH=mips make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=mips RPMARCH=mips make crossbuild linux-x86: - CROSSIMG=$@ DEBARCH=i386 RPMARCH=x86 make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=i386 RPMARCH=x86 make crossbuild linux-x64: - CROSSIMG=$@ DEBARCH=amd64 RPMARCH=x86_64 make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=amd64 RPMARCH=x86_64 make crossbuild clean: rm -fr $(BUILD_DIR) diff --git a/PackageConfig.cmake.in b/PackageConfig.cmake.in index 94e4777a4..55339d35e 100644 --- a/PackageConfig.cmake.in +++ b/PackageConfig.cmake.in @@ -15,4 +15,15 @@ endif() include("${CMAKE_CURRENT_LIST_DIR}/zenohpicoTargets.cmake") -add_library(zenohpico::lib ALIAS zenohpico::zenohpico) +if(@PICO_SHARED@) + add_library(zenohpico::shared ALIAS zenohpico::zenohpico_shared) +endif() +if(@PICO_STATIC@) + add_library(zenohpico::static ALIAS zenohpico::zenohpico_static) +endif() + +if(@BUILD_SHARED_LIBS@) + add_library(zenohpico::lib ALIAS zenohpico::zenohpico_shared) +else() + add_library(zenohpico::lib ALIAS zenohpico::zenohpico_static) +endif() diff --git a/README.md b/README.md index 452643087..fed957104 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ ![Build](https://github.com/eclipse-zenoh/zenoh-pico/workflows/build/badge.svg) -![Crossbuild](https://github.com/eclipse-zenoh/zenoh-pico/workflows/crossbuild/badge.svg) ![integration](https://github.com/eclipse-zenoh/zenoh-pico/workflows/integration/badge.svg) [![Documentation Status](https://readthedocs.org/projects/zenoh-pico/badge/?version=latest)](https://zenoh-pico.readthedocs.io/en/latest/?badge=latest) [![Discussion](https://img.shields.io/badge/discussion-on%20github-blue)](https://github.com/eclipse-zenoh/roadmap/discussions) @@ -12,14 +11,14 @@ # Eclipse Zenoh The Eclipse Zenoh: Zero Overhead Pub/sub, Store/Query and Compute. -Zenoh (pronounce _/zeno/_) unifies data in motion, data at rest and computations. It carefully blends traditional pub/sub with geo-distributed storages, queries and computations, while retaining a level of time and space efficiency that is well beyond any of the mainstream stacks. +Zenoh (pronounce _/zeno/_) unifies data in motion, data at rest, and computations. It carefully blends traditional pub/sub with geo-distributed storages, queries and computations, while retaining a level of time and space efficiency that is well beyond any of the mainstream stacks. Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.com/eclipse-zenoh/roadmap) for more detailed information. ------------------------------- # Zenoh-Pico: native C library for constrained devices -zenoh-pico is the [Eclipse zenoh](http://zenoh.io) implementation that targets constrained devices and offers a native C API. +zenoh-pico is the [Eclipse zenoh](http://zenoh.io) implementation that targets constrained devices, offering a native C API. It is fully compatible with its main [Rust Zenoh implementation](https://github.com/eclipse-zenoh/zenoh), providing a lightweight implementation of most functionalities. Currently, zenoh-pico provides support for the following (RT)OSs and protocols: @@ -42,11 +41,11 @@ Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.c ## 1. How to install it The Eclipse zenoh-pico library is available as **Debian**, **RPM**, and **tgz** packages in the [Eclipse zenoh-pico download area](https://download.eclipse.org/zenoh/zenoh-pico/). -Those packages are built using manylinux2010 x86-32 and x86-64 to be compatible with most of the Linux platforms. -There are 2 kind of packages: +Those packages are built using manylinux2010 x86-32 and x86-64 for compatibility with most Linux platforms. +There are two kind of packages: - **libzenohpico**: only contains the library file (.so) -- **libzenohpico-dev**: contains the zenoh-pico header files for development. Depends on *libzenohpico* package +- **libzenohpico-dev**: contains the zenoh-pico header files for development and depends on the *libzenohpico* package For other platforms - like RTOS for embedded systems / microcontrollers -, you will need to clone and build the sources. Check [below](#how-to-build-for-microcontrollers) for more details. diff --git a/ci/scripts/build-linux.bash b/ci/scripts/build-linux.bash index 3d3a33ca4..3ac09ccdc 100644 --- a/ci/scripts/build-linux.bash +++ b/ci/scripts/build-linux.bash @@ -9,13 +9,13 @@ readonly version=${VERSION:?input VERSION is required} # Build target readonly target=${TARGET:?input TARGET is required} -BUILD_TYPE=RELEASE make "$target" +BUILD_SHARED_LIBS=ON BUILD_TYPE=RELEASE make "$target" readonly out=$GITHUB_WORKSPACE readonly repo_name=${repo#*/} -readonly archive_lib=$out/$repo_name-$version-$target.zip -readonly archive_deb=$out/$repo_name-$version-$target-deb-pkgs.zip -readonly archive_rpm=$out/$repo_name-$version-$target-rpm-pkgs.zip +readonly archive_lib=$out/$repo_name-$version-$target-standalone.zip +readonly archive_deb=$out/$repo_name-$version-$target-debian.zip +readonly archive_rpm=$out/$repo_name-$version-$target-rpm.zip readonly archive_examples=$out/$repo_name-$version-$target-examples.zip cd crossbuilds/"$target" @@ -24,8 +24,8 @@ cd - zip -r "$archive_lib" include cd crossbuilds/"$target"/packages -zip "$archive_deb" ./*.deb -zip "$archive_rpm" ./*.rpm +zip -9 -j "$archive_deb" ./*.deb +zip -9 -j "$archive_rpm" ./*.rpm cd - cd crossbuilds/"$target"/examples diff --git a/ci/scripts/bump-and-tag.bash b/ci/scripts/bump-and-tag.bash index 58883d627..f54d8953e 100644 --- a/ci/scripts/bump-and-tag.bash +++ b/ci/scripts/bump-and-tag.bash @@ -2,6 +2,7 @@ set -xeo pipefail +readonly live_run=${LIVE_RUN:-false} # Release number readonly version=${VERSION:-input VERSION is required} # Git actor name @@ -18,7 +19,9 @@ export GIT_COMMITTER_EMAIL=$git_user_email printf '%s' "$version" > version.txt git commit version.txt -m "chore: Bump version to $version" -git tag --force "$version" -m "v$version" +if [[ ${live_run} ]]; then + git tag --force "$version" -m "v$version" +fi git log -10 git show-ref --tags git push --force origin diff --git a/docs/api.rst b/docs/api.rst index b2ff6cf4a..b76f7a040 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -462,7 +462,16 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_sample_t .. c:type:: z_loaned_closure_sample_t .. c:type:: z_moved_closure_sample_t - + +.. c:type:: void (* z_closure_sample_callback_t)(z_loaned_sample_t * sample, void * arg); + + Function pointer type for handling samples. + Represents a callback function that is invoked when a sample is available for processing. + + Parameters: + - **sample** - Pointer to a :c:type:`z_loaned_sample_t` representing the sample to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the sample. + Functions ^^^^^^^^^ .. autocfunction:: primitives.h::z_closure_sample @@ -486,7 +495,16 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_query_t .. c:type:: z_loaned_closure_query_t .. c:type:: z_moved_closure_query_t - + +.. c:type:: void (* z_closure_query_callback_t)(z_loaned_query_t * query, void * arg); + + Function pointer type for handling queries. + Represents a callback function that is invoked when a query is available for processing. + + Parameters: + - **query** - Pointer to a :c:type:`z_loaned_query_t` representing the query to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the query. + Functions ^^^^^^^^^ .. autocfunction:: primitives.h::z_closure_query @@ -511,7 +529,16 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_reply_t .. c:type:: z_loaned_closure_reply_t .. c:type:: z_moved_closure_reply_t - + +.. c:type:: void (* z_closure_reply_callback_t)(z_loaned_reply_t * reply, void * arg); + + Function pointer type for handling replies. + Represents a callback function that is invoked when a reply is available for processing. + + Parameters: + - **reply** - Pointer to a :c:type:`z_loaned_reply_t` representing the reply to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the reply. + Functions ^^^^^^^^^ .. autocfunction:: primitives.h::z_closure_reply @@ -536,6 +563,15 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_hello_t .. c:type:: z_loaned_closure_hello_t .. c:type:: z_moved_closure_hello_t + +.. c:type:: void (* z_closure_hello_callback_t)(z_loaned_hello_t * hello, void * arg); + + Function pointer type for handling scouting response. + Represents a callback function that is invoked when a hello is available for processing. + + Parameters: + - **hello** - Pointer to a :c:type:`z_loaned_hello_t` representing the hello to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the hello. Functions ^^^^^^^^^ @@ -561,6 +597,15 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_zid_t .. c:type:: z_loaned_closure_zid_t .. c:type:: z_moved_closure_zid_t + +.. c:type:: void (* z_closure_zid_callback_t)(z_loaned_zid_t * zid, void * arg); + + Function pointer type for handling Zenoh ID routers response. + Represents a callback function that is invoked when a zid is available for processing. + + Parameters: + - **zid** - Pointer to a :c:type:`z_loaned_zid_t` representing the zid to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the zid. Functions ^^^^^^^^^ @@ -1192,6 +1237,7 @@ Functions .. autocfunction:: serialization.h::ze_serializer_serialize_buf .. autocfunction:: serialization.h::ze_serializer_serialize_string .. autocfunction:: serialization.h::ze_serializer_serialize_str +.. autocfunction:: serialization.h::ze_serializer_serialize_substr .. autocfunction:: serialization.h::ze_serializer_serialize_sequence_length .. autocfunction:: serialization.h::ze_deserialize_int8 .. autocfunction:: serialization.h::ze_deserialize_int16 @@ -1222,6 +1268,7 @@ Functions .. autocfunction:: serialization.h::ze_serialize_buf .. autocfunction:: serialization.h::ze_serialize_string .. autocfunction:: serialization.h::ze_serialize_str +.. autocfunction:: serialization.h::ze_serialize_substr Others @@ -1230,8 +1277,6 @@ Others Data Structures --------------- -.. autoctype:: types.h::z_zint_t - .. autoctype:: types.h::zp_task_read_options_t .. autoctype:: types.h::zp_task_lease_options_t .. autoctype:: types.h::zp_read_options_t @@ -1270,10 +1315,52 @@ Functions .. autocfunction:: primitives.h::zp_send_join_options_default .. autocfunction:: primitives.h::zp_send_join -.. TODO Logging -.. TODO ======= +Logging +======= + +.. warning:: This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + +Zenoh-Pico provides a flexible logging system to assist with debugging and monitoring. +By default, logging is disabled in release builds, but it can be enabled and configured +based on the desired level of verbosity. + +Logging Levels +-------------- + +Zenoh-Pico supports three logging levels: + +- **Error**: Only error messages are logged. This is the least verbose level. +- **Info**: Logs informational messages and error messages. +- **Debug**: Logs debug messages, informational messages, and error messages. This is the most verbose level. + +Enabling Logging +---------------- + +To enable logging, you can adjust the logging level by defining the ``ZENOH_DEBUG`` macro at compile time. + +- Set ``ZENOH_DEBUG`` to ``1`` to enable error messages. +- Set ``ZENOH_DEBUG`` to ``2`` to enable informational messages. +- Set ``ZENOH_DEBUG`` to ``3`` to enable debug messages (includes info and error). + +Additionally, logging can be automatically enabled in **debug builds** by defining the ``Z_BUILD_DEBUG`` macro. +In release builds, logging is disabled unless ``ZENOH_DEBUG`` is explicitly set. + +Example of Enabling Logging +--------------------------- + +To enable **debug-level logging** in your build, you would add the following flags during compilation: + +.. code-block:: bash + + gcc -DZENOH_DEBUG=3 -o my_program my_program.c +This will enable the most verbose logging, printing debug, info, and error messages. +Disabling Logging +----------------- +To disable all logging, set ``ZENOH_DEBUG`` to ``0`` or ensure it is undefined in release builds: +.. code-block:: bash + gcc -DZENOH_DEBUG=0 -o my_program my_program.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a3fc911cd..a001356e8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -14,7 +14,7 @@ endif() function(add_example name) add_executable(${name} ${ARGN}) set_property(TARGET ${name} PROPERTY C_STANDARD 11) - target_link_libraries(${name} zenohpico) + target_link_libraries(${name} zenohpico::lib) add_dependencies(examples ${name}) endfunction() diff --git a/examples/espidf/z_get.c b/examples/espidf/z_get.c index 5142009b1..fcfb5f975 100644 --- a/examples/espidf/z_get.c +++ b/examples/espidf/z_get.c @@ -169,7 +169,7 @@ void app_main() { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { diff --git a/examples/espidf/z_queryable.c b/examples/espidf/z_queryable.c index c95ca377e..0939bfac8 100644 --- a/examples/espidf/z_queryable.c +++ b/examples/espidf/z_queryable.c @@ -169,7 +169,7 @@ void app_main() { // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/espidf/z_sub.c b/examples/espidf/z_sub.c index 01bb61de2..d7ac968ae 100644 --- a/examples/espidf/z_sub.c +++ b/examples/espidf/z_sub.c @@ -151,7 +151,7 @@ void app_main() { printf("Declaring Subscriber on '%s'...", KEYEXPR); z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); z_owned_subscriber_t sub; z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/freertos_plus_tcp/CMakeLists.txt b/examples/freertos_plus_tcp/CMakeLists.txt index 83f890f30..3a0d44b54 100644 --- a/examples/freertos_plus_tcp/CMakeLists.txt +++ b/examples/freertos_plus_tcp/CMakeLists.txt @@ -55,9 +55,9 @@ FetchContent_MakeAvailable(freertos_kernel freertos_plus_tcp) set(BUILD_SHARED_LIBS OFF) set(WITH_FREERTOS_PLUS_TCP ON) set(ZENOH_DEBUG 3) -configure_include_project(ZENOHPICO zenohpico zenohpico "../.." zenohpico "https://github.com/eclipse-zenoh/zenoh-pico" "") +configure_include_project(ZENOHPICO zenohpico zenohpico::lib "../.." zenohpico "https://github.com/eclipse-zenoh/zenoh-pico" "") -target_link_libraries(zenohpico +target_link_libraries(zenohpico_static freertos_kernel freertos_plus_tcp ) @@ -74,7 +74,7 @@ function(add_example name) main freertos_kernel freertos_plus_tcp - zenohpico + zenohpico::lib ) endfunction() diff --git a/examples/freertos_plus_tcp/z_get.c b/examples/freertos_plus_tcp/z_get.c index 96931fcab..7d76d8de3 100644 --- a/examples/freertos_plus_tcp/z_get.c +++ b/examples/freertos_plus_tcp/z_get.c @@ -93,7 +93,7 @@ void app_main(void) { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return; diff --git a/examples/freertos_plus_tcp/z_queryable.c b/examples/freertos_plus_tcp/z_queryable.c index 34c1c2a94..a1f8634f8 100644 --- a/examples/freertos_plus_tcp/z_queryable.c +++ b/examples/freertos_plus_tcp/z_queryable.c @@ -85,7 +85,7 @@ void app_main(void) { printf("Creating Queryable on '%s'...\n", KEYEXPR); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/freertos_plus_tcp/z_sub.c b/examples/freertos_plus_tcp/z_sub.c index 45f7c4775..4febeecf7 100644 --- a/examples/freertos_plus_tcp/z_sub.c +++ b/examples/freertos_plus_tcp/z_sub.c @@ -62,7 +62,7 @@ void app_main(void) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/freertos_plus_tcp/z_sub_st.c b/examples/freertos_plus_tcp/z_sub_st.c index 805a0c949..34ae7b6f4 100644 --- a/examples/freertos_plus_tcp/z_sub_st.c +++ b/examples/freertos_plus_tcp/z_sub_st.c @@ -59,7 +59,7 @@ void app_main(void) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/unix/c11/z_get.c b/examples/unix/c11/z_get.c index 034ddb2d5..3bf67421f 100644 --- a/examples/unix/c11/z_get.c +++ b/examples/unix/c11/z_get.c @@ -135,7 +135,7 @@ int main(int argc, char **argv) { } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; diff --git a/examples/unix/c11/z_get_attachment.c b/examples/unix/c11/z_get_attachment.c index 842273fc2..1d20e3c96 100644 --- a/examples/unix/c11/z_get_attachment.c +++ b/examples/unix/c11/z_get_attachment.c @@ -68,12 +68,11 @@ void reply_handler(z_loaned_reply_t *reply, void *ctx) { // Check attachment const z_loaned_bytes_t *attachment = z_sample_attachment(sample); - if (attachment == NULL) { - return; - } ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); size_t attachment_len; - ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len); + if (ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len) < 0) { + return; + } kv_pair_t *kvp = (kv_pair_t *)malloc(sizeof(kv_pair_t) * attachment_len); for (size_t i = 0; i < attachment_len; ++i) { ze_deserializer_deserialize_string(&deserializer, &kvp[i].key); @@ -178,7 +177,7 @@ int main(int argc, char **argv) { ze_owned_serializer_t serializer; ze_serializer_empty(&serializer); - ze_serializer_serialize_sequence_length(z_loan_mut(serializer), 2); + ze_serializer_serialize_sequence_length(z_loan_mut(serializer), 1); for (size_t i = 0; i < 1; ++i) { ze_serializer_serialize_string(z_loan_mut(serializer), z_loan(kvs[i].key)); ze_serializer_serialize_string(z_loan_mut(serializer), z_loan(kvs[i].value)); @@ -193,7 +192,7 @@ int main(int argc, char **argv) { opts.encoding = z_move(encoding); z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; diff --git a/examples/unix/c11/z_info.c b/examples/unix/c11/z_info.c index 94df7db68..fe4b61beb 100644 --- a/examples/unix/c11/z_info.c +++ b/examples/unix/c11/z_info.c @@ -86,14 +86,14 @@ int main(int argc, char **argv) { printf("Routers IDs:\n"); z_owned_closure_zid_t callback; - z_closure(&callback, print_zid); + z_closure(&callback, print_zid, NULL, NULL); z_info_routers_zid(z_loan(s), z_move(callback)); // `callback` has been `z_move`d just above, so it's safe to reuse the variable, // we'll just have to make sure we `z_move` it again to avoid mem-leaks. printf("Peers IDs:\n"); z_owned_closure_zid_t callback2; - z_closure(&callback2, print_zid); + z_closure(&callback2, print_zid, NULL, NULL); z_info_peers_zid(z_loan(s), z_move(callback2)); z_drop(z_move(s)); diff --git a/examples/unix/c11/z_queryable.c b/examples/unix/c11/z_queryable.c index 13ced6dfc..6ec72f517 100644 --- a/examples/unix/c11/z_queryable.c +++ b/examples/unix/c11/z_queryable.c @@ -146,7 +146,7 @@ int main(int argc, char **argv) { printf("Creating Queryable on '%s'...\n", keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/unix/c11/z_queryable_attachment.c b/examples/unix/c11/z_queryable_attachment.c index 20a2e9ad2..fceed2e2f 100644 --- a/examples/unix/c11/z_queryable_attachment.c +++ b/examples/unix/c11/z_queryable_attachment.c @@ -68,10 +68,9 @@ void query_handler(z_loaned_query_t *query, void *ctx) { // Check attachment const z_loaned_bytes_t *attachment = z_query_attachment(query); - if (attachment != NULL) { - ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); - size_t attachment_len; - ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len); + ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); + size_t attachment_len; + if (ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len) == Z_OK) { kv_pair_t *kvp = (kv_pair_t *)malloc(sizeof(kv_pair_t) * attachment_len); for (size_t i = 0; i < attachment_len; ++i) { ze_deserializer_deserialize_string(&deserializer, &kvp[i].key); @@ -186,7 +185,7 @@ int main(int argc, char **argv) { printf("Creating Queryable on '%s'...\n", keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/unix/c11/z_sub.c b/examples/unix/c11/z_sub.c index 1c9df33b1..0d8b73e39 100644 --- a/examples/unix/c11/z_sub.c +++ b/examples/unix/c11/z_sub.c @@ -98,7 +98,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/unix/c11/z_sub_attachment.c b/examples/unix/c11/z_sub_attachment.c index 5720f86fd..0421f419e 100644 --- a/examples/unix/c11/z_sub_attachment.c +++ b/examples/unix/c11/z_sub_attachment.c @@ -64,12 +64,10 @@ void data_handler(z_loaned_sample_t *sample, void *ctx) { printf(" with timestamp: %" PRIu64 "\n", z_timestamp_ntp64_time(ts)); } // Check attachment - const z_loaned_bytes_t *attachment = z_sample_attachment(sample); - if (attachment != NULL) { - ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); - size_t attachment_len; - ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len); + ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); + size_t attachment_len; + if (ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len) == Z_OK) { kv_pair_t *kvp = (kv_pair_t *)malloc(sizeof(kv_pair_t) * attachment_len); for (size_t i = 0; i < attachment_len; ++i) { ze_deserializer_deserialize_string(&deserializer, &kvp[i].key); @@ -149,7 +147,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/unix/c11/z_sub_st.c b/examples/unix/c11/z_sub_st.c index 083d9465d..edc3b4e5e 100644 --- a/examples/unix/c11/z_sub_st.c +++ b/examples/unix/c11/z_sub_st.c @@ -90,7 +90,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/windows/z_get.c b/examples/windows/z_get.c index 3c5a3f338..dc4cfc862 100644 --- a/examples/windows/z_get.c +++ b/examples/windows/z_get.c @@ -92,7 +92,7 @@ int main(int argc, char **argv) { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; diff --git a/examples/windows/z_info.c b/examples/windows/z_info.c index 96f8dcc62..62a459156 100644 --- a/examples/windows/z_info.c +++ b/examples/windows/z_info.c @@ -59,14 +59,14 @@ int main(int argc, char **argv) { printf("Routers IDs:\n"); z_owned_closure_zid_t callback; - z_closure(&callback, print_zid); + z_closure(&callback, print_zid, NULL, NULL); z_info_routers_zid(z_loan(s), z_move(callback)); // `callback` has been `z_move`d just above, so it's safe to reuse the variable, // we'll just have to make sure we `z_move` it again to avoid mem-leaks. printf("Peers IDs:\n"); z_owned_closure_zid_t callback2; - z_closure(&callback2, print_zid); + z_closure(&callback2, print_zid, NULL, NULL); z_info_peers_zid(z_loan(s), z_move(callback2)); z_drop(z_move(s)); diff --git a/examples/windows/z_queryable.c b/examples/windows/z_queryable.c index 11a01d92e..4a1c2e469 100644 --- a/examples/windows/z_queryable.c +++ b/examples/windows/z_queryable.c @@ -79,7 +79,7 @@ int main(int argc, char **argv) { printf("Creating Queryable on '%s'...\n", keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/windows/z_sub.c b/examples/windows/z_sub.c index 166775ea1..8df2bb696 100644 --- a/examples/windows/z_sub.c +++ b/examples/windows/z_sub.c @@ -59,7 +59,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/windows/z_sub_st.c b/examples/windows/z_sub_st.c index 16507ef28..b1d2a6634 100644 --- a/examples/windows/z_sub_st.c +++ b/examples/windows/z_sub_st.c @@ -56,7 +56,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/zephyr/z_get.c b/examples/zephyr/z_get.c index 8d22aa0c7..c56049899 100644 --- a/examples/zephyr/z_get.c +++ b/examples/zephyr/z_get.c @@ -66,7 +66,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -87,12 +87,12 @@ int main(int argc, char **argv) { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); - exit(-1); + return -1; } } diff --git a/examples/zephyr/z_pub.c b/examples/zephyr/z_pub.c index ce91c4d38..4f9f063b7 100644 --- a/examples/zephyr/z_pub.c +++ b/examples/zephyr/z_pub.c @@ -48,7 +48,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -62,7 +62,7 @@ int main(int argc, char **argv) { z_owned_publisher_t pub; if (z_declare_publisher(z_loan(s), &pub, z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); - exit(-1); + return -1; } printf("OK\n"); diff --git a/examples/zephyr/z_pull.c b/examples/zephyr/z_pull.c index 06562eed6..e3be5f345 100644 --- a/examples/zephyr/z_pull.c +++ b/examples/zephyr/z_pull.c @@ -48,7 +48,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -56,7 +56,7 @@ int main(int argc, char **argv) { if (zp_start_read_task(z_loan_mut(s), NULL) < 0 || zp_start_lease_task(z_loan_mut(s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_session_drop(z_session_move(&s)); - exit(-1); + return -1; } printf("Declaring Subscriber on '%s'...\n", KEYEXPR); @@ -68,7 +68,7 @@ int main(int argc, char **argv) { z_view_keyexpr_from_str(&ke, KEYEXPR); if (z_declare_subscriber(z_loan(s), &sub, z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); - exit(-1); + return -1; } printf("Pulling data every %zu ms... Ring size: %zd\n", INTERVAL, SIZE); diff --git a/examples/zephyr/z_queryable.c b/examples/zephyr/z_queryable.c index 0d34c4c03..1eafda347 100644 --- a/examples/zephyr/z_queryable.c +++ b/examples/zephyr/z_queryable.c @@ -71,7 +71,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -82,13 +82,13 @@ int main(int argc, char **argv) { // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare queryable.\n"); - exit(-1); + return -1; } printf("OK\n"); printf("Zenoh setup finished!\n"); diff --git a/examples/zephyr/z_sub.c b/examples/zephyr/z_sub.c index 68c0f46e1..c49668b3c 100644 --- a/examples/zephyr/z_sub.c +++ b/examples/zephyr/z_sub.c @@ -55,7 +55,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -65,13 +65,13 @@ int main(int argc, char **argv) { printf("Declaring Subscriber on '%s'...", KEYEXPR); z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); z_owned_subscriber_t sub; if (z_declare_subscriber(z_loan(s), &sub, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); - exit(-1); + return -1; } printf("OK!\n"); diff --git a/include/zenoh-pico/api/encoding.h b/include/zenoh-pico/api/encoding.h index 3544693b8..7393ae259 100644 --- a/include/zenoh-pico/api/encoding.h +++ b/include/zenoh-pico/api/encoding.h @@ -78,84 +78,84 @@ extern const z_owned_encoding_t ZP_ENCODING_ZENOH_SERIALIZED; * Constant alias for string: `"application/octet-stream"`. */ const z_loaned_encoding_t *z_encoding_application_octet_stream(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_OCTET_STREAM; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_OCTET_STREAM; /** * A textual file. * Constant alias for string: `"text/plain"`. */ const z_loaned_encoding_t *z_encoding_text_plain(void); -extern const z_owned_encoding_t ENCODING_TEXT_PLAIN; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_PLAIN; /** * JSON data intended to be consumed by an application. * Constant alias for string: `"application/json"`. */ const z_loaned_encoding_t *z_encoding_application_json(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSON; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSON; /** * JSON data intended to be human readable. * Constant alias for string: `"text/json"`. */ const z_loaned_encoding_t *z_encoding_text_json(void); -extern const z_owned_encoding_t ENCODING_TEXT_JSON; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_JSON; /** * A Common Data Representation (CDR)-encoded data. * Constant alias for string: `"application/cdr"`. */ const z_loaned_encoding_t *z_encoding_application_cdr(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_CDR; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_CDR; /** * A Concise Binary Object Representation (CBOR)-encoded data. * Constant alias for string: `"application/cbor"`. */ const z_loaned_encoding_t *z_encoding_application_cbor(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_CBOR; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_CBOR; /** * YAML data intended to be consumed by an application. * Constant alias for string: `"application/yaml"`. */ const z_loaned_encoding_t *z_encoding_application_yaml(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_YAML; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_YAML; /** * YAML data intended to be human readable. * Constant alias for string: `"text/yaml"`. */ const z_loaned_encoding_t *z_encoding_text_yaml(void); -extern const z_owned_encoding_t ENCODING_TEXT_YAML; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_YAML; /** * JSON5 encoded data that are human readable. * Constant alias for string: `"text/json5"`. */ const z_loaned_encoding_t *z_encoding_text_json5(void); -extern const z_owned_encoding_t ENCODING_TEXT_JSON5; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_JSON5; /** * A Python object serialized using `pickle `_. * Constant alias for string: `"application/python-serialized-object"`. */ const z_loaned_encoding_t *z_encoding_application_python_serialized_object(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_PYTHON_SERIALIZED_OBJECT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_PYTHON_SERIALIZED_OBJECT; /** * An application-specific protobuf-encoded data. * Constant alias for string: `"application/protobuf"`. */ const z_loaned_encoding_t *z_encoding_application_protobuf(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_PROTOBUF; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_PROTOBUF; /** * A Java serialized object. * Constant alias for string: `"application/java-serialized-object"`. */ const z_loaned_encoding_t *z_encoding_application_java_serialized_object(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JAVA_SERIALIZED_OBJECT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JAVA_SERIALIZED_OBJECT; /** * An `openmetrics `_ data, commonly used by @@ -163,266 +163,266 @@ extern const z_owned_encoding_t ENCODING_APPLICATION_JAVA_SERIALIZED_OBJECT; * Constant alias for string: `"application/openmetrics-text"`. */ const z_loaned_encoding_t *z_encoding_application_openmetrics_text(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_OPENMETRICS_TEXT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_OPENMETRICS_TEXT; /** * A Portable Network Graphics (PNG) image. * Constant alias for string: `"image/png"`. */ const z_loaned_encoding_t *z_encoding_image_png(void); -extern const z_owned_encoding_t ENCODING_IMAGE_PNG; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_PNG; /** * A Joint Photographic Experts Group (JPEG) image. * Constant alias for string: `"image/jpeg"`. */ const z_loaned_encoding_t *z_encoding_image_jpeg(void); -extern const z_owned_encoding_t ENCODING_IMAGE_JPEG; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_JPEG; /** * A Graphics Interchange Format (GIF) image. * Constant alias for string: `"image/gif"`. */ const z_loaned_encoding_t *z_encoding_image_gif(void); -extern const z_owned_encoding_t ENCODING_IMAGE_GIF; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_GIF; /** * A BitMap (BMP) image. * Constant alias for string: `"image/bmp"`. */ const z_loaned_encoding_t *z_encoding_image_bmp(void); -extern const z_owned_encoding_t ENCODING_IMAGE_BMP; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_BMP; /** * A Web Portable (WebP) image. * Constant alias for string: `"image/webp"`. */ const z_loaned_encoding_t *z_encoding_image_webp(void); -extern const z_owned_encoding_t ENCODING_IMAGE_WEBP; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_WEBP; /** * An XML file intended to be consumed by an application. * Constant alias for string: `"application/xml"`. */ const z_loaned_encoding_t *z_encoding_application_xml(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_XML; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_XML; /** * An encoded list of tuples, each consisting of a name and a value. * Constant alias for string: `"application/x-www-form-urlencoded"`. */ const z_loaned_encoding_t *z_encoding_application_x_www_form_urlencoded(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_X_WWW_FORM_URLENCODED; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_X_WWW_FORM_URLENCODED; /** * An HTML file. * Constant alias for string: `"text/html"`. */ const z_loaned_encoding_t *z_encoding_text_html(void); -extern const z_owned_encoding_t ENCODING_TEXT_HTML; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_HTML; /** * An XML file that is human-readable. * Constant alias for string: `"text/xml"`. */ const z_loaned_encoding_t *z_encoding_text_xml(void); -extern const z_owned_encoding_t ENCODING_TEXT_XML; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_XML; /** * A CSS file. * Constant alias for string: `"text/css"`. */ const z_loaned_encoding_t *z_encoding_text_css(void); -extern const z_owned_encoding_t ENCODING_TEXT_CSS; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_CSS; /** * A JavaScript file. * Constant alias for string: `"text/javascript"`. */ const z_loaned_encoding_t *z_encoding_text_javascript(void); -extern const z_owned_encoding_t ENCODING_TEXT_JAVASCRIPT; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_JAVASCRIPT; /** * A Markdown file. * Constant alias for string: `"text/markdown"`. */ const z_loaned_encoding_t *z_encoding_text_markdown(void); -extern const z_owned_encoding_t ENCODING_TEXT_MARKDOWN; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_MARKDOWN; /** * A CSV file. * Constant alias for string: `"text/csv"`. */ const z_loaned_encoding_t *z_encoding_text_csv(void); -extern const z_owned_encoding_t ENCODING_TEXT_CSV; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_CSV; /** * An application-specific SQL query. * Constant alias for string: `"application/sql"`. */ const z_loaned_encoding_t *z_encoding_application_sql(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_SQL; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_SQL; /** * Constrained Application Protocol (CoAP) data intended for CoAP-to-HTTP and HTTP-to-CoAP proxies. * Constant alias for string: `"application/coap-payload"`. */ const z_loaned_encoding_t *z_encoding_application_coap_payload(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_COAP_PAYLOAD; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_COAP_PAYLOAD; /** * Defines a JSON document structure for expressing a sequence of operations to apply to a JSON document. * Constant alias for string: `"application/json-patch+json"`. */ const z_loaned_encoding_t *z_encoding_application_json_patch_json(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSON_PATCH_JSON; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSON_PATCH_JSON; /** * A JSON text sequence consists of any number of JSON texts, all encoded in UTF-8. * Constant alias for string: `"application/json-seq"`. */ const z_loaned_encoding_t *z_encoding_application_json_seq(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSON_SEQ; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSON_SEQ; /** * A JSONPath defines a string syntax for selecting and extracting JSON values from within a given JSON value. * Constant alias for string: `"application/jsonpath"`. */ const z_loaned_encoding_t *z_encoding_application_jsonpath(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSONPATH; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSONPATH; /** * A JSON Web Token (JWT). * Constant alias for string: `"application/jwt"`. */ const z_loaned_encoding_t *z_encoding_application_jwt(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JWT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JWT; /** * An application-specific MPEG-4 encoded data, either audio or video. * Constant alias for string: `"application/mp4"`. */ const z_loaned_encoding_t *z_encoding_application_mp4(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_MP4; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_MP4; /** * A SOAP 1.2 message serialized as XML 1.0. * Constant alias for string: `"application/soap+xml"`. */ const z_loaned_encoding_t *z_encoding_application_soap_xml(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_SOAP_XML; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_SOAP_XML; /** * A YANG-encoded data commonly used by the Network Configuration Protocol (NETCONF). * Constant alias for string: `"application/yang"`. */ const z_loaned_encoding_t *z_encoding_application_yang(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_YANG; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_YANG; /** * A MPEG-4 Advanced Audio Coding (AAC) media. * Constant alias for string: `"audio/aac"`. */ const z_loaned_encoding_t *z_encoding_audio_aac(void); -extern const z_owned_encoding_t ENCODING_AUDIO_AAC; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_AAC; /** * A Free Lossless Audio Codec (FLAC) media. * Constant alias for string: `"audio/flac"`. */ const z_loaned_encoding_t *z_encoding_audio_flac(void); -extern const z_owned_encoding_t ENCODING_AUDIO_FLAC; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_FLAC; /** * An audio codec defined in MPEG-1, MPEG-2, MPEG-4, or registered at the MP4 registration authority. * Constant alias for string: `"audio/mp4"`. */ const z_loaned_encoding_t *z_encoding_audio_mp4(void); -extern const z_owned_encoding_t ENCODING_AUDIO_MP4; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_MP4; /** * An Ogg-encapsulated audio stream. * Constant alias for string: `"audio/ogg"`. */ const z_loaned_encoding_t *z_encoding_audio_ogg(void); -extern const z_owned_encoding_t ENCODING_AUDIO_OGG; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_OGG; /** * A Vorbis-encoded audio stream. * Constant alias for string: `"audio/vorbis"`. */ const z_loaned_encoding_t *z_encoding_audio_vorbis(void); -extern const z_owned_encoding_t ENCODING_AUDIO_VORBIS; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_VORBIS; /** * A h261-encoded video stream. * Constant alias for string: `"video/h261"`. */ const z_loaned_encoding_t *z_encoding_video_h261(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H261; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H261; /** * A h263-encoded video stream. * Constant alias for string: `"video/h263"`. */ const z_loaned_encoding_t *z_encoding_video_h263(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H263; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H263; /** * A h264-encoded video stream. * Constant alias for string: `"video/h264"`. */ const z_loaned_encoding_t *z_encoding_video_h264(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H264; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H264; /** * A h265-encoded video stream. * Constant alias for string: `"video/h265"`. */ const z_loaned_encoding_t *z_encoding_video_h265(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H265; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H265; /** * A h266-encoded video stream. * Constant alias for string: `"video/h266"`. */ const z_loaned_encoding_t *z_encoding_video_h266(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H266; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H266; /** * A video codec defined in MPEG-1, MPEG-2, MPEG-4, or registered at the MP4 registration authority. * Constant alias for string: `"video/mp4"`. */ const z_loaned_encoding_t *z_encoding_video_mp4(void); -extern const z_owned_encoding_t ENCODING_VIDEO_MP4; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_MP4; /** * An Ogg-encapsulated video stream. * Constant alias for string: `"video/ogg"`. */ const z_loaned_encoding_t *z_encoding_video_ogg(void); -extern const z_owned_encoding_t ENCODING_VIDEO_OGG; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_OGG; /** * An uncompressed, studio-quality video stream. * Constant alias for string: `"video/raw"`. */ const z_loaned_encoding_t *z_encoding_video_raw(void); -extern const z_owned_encoding_t ENCODING_VIDEO_RAW; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_RAW; /** * A VP8-encoded video stream. * Constant alias for string: `"video/vp8"`. */ const z_loaned_encoding_t *z_encoding_video_vp8(void); -extern const z_owned_encoding_t ENCODING_VIDEO_VP8; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_VP8; /** * A VP9-encoded video stream. * Constant alias for string: `"video/vp9"`. */ const z_loaned_encoding_t *z_encoding_video_vp9(void); -extern const z_owned_encoding_t ENCODING_VIDEO_VP9; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_VP9; /** * Returns a loaned default `z_loaned_encoding_t`. diff --git a/include/zenoh-pico/api/handlers.h b/include/zenoh-pico/api/handlers.h index 52e3f2ce4..c3342302a 100644 --- a/include/zenoh-pico/api/handlers.h +++ b/include/zenoh-pico/api/handlers.h @@ -145,22 +145,37 @@ extern "C" { /* elem_drop_f */ z_##item_name##_drop, \ /* elem_null */ z_internal_##item_name##_null) -#define _Z_CHANNEL_DEFINE_DUMMY(item_name, kind_name) \ - typedef struct { \ - uint8_t _foo; \ - } z_owned_##kind_name##_handler_##item_name##_t; \ - typedef struct { \ - uint8_t _foo; \ - } z_loaned_##kind_name##_handler_##item_name##_t; \ - typedef struct { \ - z_owned_##kind_name##_handler_##item_name##_t *_ptr; \ - } z_moved_##kind_name##_handler_##item_name##_t; \ - void *z_##kind_name##_handler_##item_name##_loan(void); \ - void *z_##kind_name##_handler_##item_name##_move(void); \ - void *z_##kind_name##_handler_##item_name##_drop(void); \ - void *z_##kind_name##_handler_##item_name##_recv(void); \ - void *z_##kind_name##_handler_##item_name##_take(void); \ - void *z_##kind_name##_handler_##item_name##_try_recv(void); +#define _Z_CHANNEL_DUMMY_IMPL(handler_type, handler_name, item_name) \ + _Z_OWNED_TYPE_VALUE(handler_type, handler_name) \ + static inline void _z_##handler_name##_clear(handler_type *handler) { _ZP_UNUSED(handler); } \ + static inline bool _z_##handler_name##_check(const handler_type *handler) { \ + _ZP_UNUSED(handler); \ + return false; \ + } \ + static inline handler_type _z_##handler_name##_null(void) { \ + handler_type h = {0}; \ + return h; \ + } \ + _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_INLINE_IMPL(handler_type, handler_name, _z_##handler_name##_check, \ + _z_##handler_name##_null, _z_##handler_name##_clear) \ + static inline z_result_t z_##handler_name##_try_recv(const z_loaned_##handler_name##_t *handler, \ + z_owned_##item_name##_t *e) { \ + _ZP_UNUSED(handler); \ + _ZP_UNUSED(e); \ + return Z_CHANNEL_DISCONNECTED; \ + } \ + static inline z_result_t z_##handler_name##_recv(const z_loaned_##handler_name##_t *handler, \ + z_owned_##item_name##_t *e) { \ + _ZP_UNUSED(handler); \ + _ZP_UNUSED(e); \ + return Z_CHANNEL_DISCONNECTED; \ + } + +#define _Z_CHANNEL_DEFINE_DUMMY(item_name, kind_name) \ + typedef struct { \ + uint8_t _foo; \ + } _z_##kind_name##_handler_##item_name##_t; \ + _Z_CHANNEL_DUMMY_IMPL(_z_##kind_name##_handler_##item_name##_t, kind_name##_handler_##item_name, item_name) // This macro defines: // z_ring_channel_sample_new() diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index 0d1c9aea8..ca17781d0 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -545,8 +545,8 @@ inline void z_call(const z_loaned_closure_zid_t &closure, const z_id_t *zid) inline void z_closure( z_owned_closure_hello_t* closure, void (*call)(z_loaned_hello_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -554,8 +554,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_query_t* closure, void (*call)(z_loaned_query_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -563,8 +563,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_reply_t* closure, void (*call)(z_loaned_reply_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -572,8 +572,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_sample_t* closure, void (*call)(z_loaned_sample_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -581,8 +581,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_zid_t* closure, void (*call)(const z_id_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 79a01f8c8..b28f3ec6c 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -982,8 +982,8 @@ const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query); * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_sample(z_owned_closure_sample_t *closure, z_sample_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_sample(z_owned_closure_sample_t *closure, z_closure_sample_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a sample closure. @@ -1007,8 +1007,8 @@ void z_closure_sample_call(const z_loaned_closure_sample_t *closure, z_loaned_sa * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_query(z_owned_closure_query_t *closure, z_query_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_query(z_owned_closure_query_t *closure, z_closure_query_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a query closure. @@ -1032,8 +1032,8 @@ void z_closure_query_call(const z_loaned_closure_query_t *closure, z_loaned_quer * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_reply(z_owned_closure_reply_t *closure, z_reply_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_reply(z_owned_closure_reply_t *closure, z_closure_reply_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a reply closure. @@ -1057,8 +1057,8 @@ void z_closure_reply_call(const z_loaned_closure_reply_t *closure, z_loaned_repl * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_hello(z_owned_closure_hello_t *closure, z_loaned_hello_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_hello(z_owned_closure_hello_t *closure, z_closure_hello_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a hello closure. @@ -1074,7 +1074,7 @@ void z_closure_hello_call(const z_loaned_closure_hello_t *closure, z_loaned_hell * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Parameters: - * closure: Pointer to an uninitialized :c:type:`z_owned_closure_zit_t`. + * closure: Pointer to an uninitialized :c:type:`z_owned_closure_zid_t`. * call: Pointer to the callback function. ``context`` will be passed as its last argument. * drop: Pointer to the function that will free the callback state. ``context`` will be passed as its last argument. * context: Pointer to an arbitrary state. @@ -1082,7 +1082,8 @@ void z_closure_hello_call(const z_loaned_closure_hello_t *closure, z_loaned_hell * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_zid(z_owned_closure_zid_t *closure, z_zid_handler_t call, z_dropper_handler_t drop, void *context); +z_result_t z_closure_zid(z_owned_closure_zid_t *closure, z_closure_zid_callback_t call, z_closure_drop_callback_t drop, + void *context); /** * Calls a zid closure. @@ -1706,6 +1707,7 @@ const z_loaned_sample_t *z_reply_ok(const z_loaned_reply_t *reply); */ const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply); +#ifdef Z_FEATURE_UNSTABLE_API /** * Gets the id of the zenoh instance that answered this Reply. * @@ -1716,7 +1718,9 @@ const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply); * `true` if id is present */ bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id); -#endif +#endif // Z_FEATURE_UNSTABLE_API + +#endif // Z_FEATURE_QUERY == 1 #if Z_FEATURE_QUERYABLE == 1 /** @@ -2056,6 +2060,34 @@ z_result_t z_declare_background_subscriber(const z_loaned_session_t *zs, const z const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subscriber); #endif +#ifdef Z_FEATURE_UNSTABLE_API +#if Z_FEATURE_BATCHING == 1 +/** + * Activate the batching mechanism. + * Any message that would have been sent on the network by a subsequent api call (e.g z_put, z_get) + * will be instead stored until the batch is full or batching is stopped with :c:func:`zp_batch_stop`. + * + * Parameters: + * zs: Pointer to a :c:type:`z_loaned_session_t` that will start batching messages. + * + * Return: + * ``0`` if batching started, ``negative value`` otherwise. + */ +z_result_t zp_batch_start(const z_loaned_session_t *zs); + +/** + * Deactivate the batching mechanism and flush the remaining messages. + * + * Parameters: + * zs: Pointer to a :c:type:`z_loaned_session_t` that will stop batching messages. + * + * Return: + * ``0`` if batching stopped and batch successfully sent, ``negative value`` otherwise. + */ +z_result_t zp_batch_stop(const z_loaned_session_t *zs); +#endif +#endif + /************* Multi Thread Tasks helpers **************/ /** * Builds a :c:type:`zp_task_read_options_t` with default value. diff --git a/include/zenoh-pico/api/serialization.h b/include/zenoh-pico/api/serialization.h index d6e579557..d8ff0d648 100644 --- a/include/zenoh-pico/api/serialization.h +++ b/include/zenoh-pico/api/serialization.h @@ -458,6 +458,7 @@ z_result_t ze_deserializer_deserialize_slice(ze_deserializer_t *deserializer, z_ /** * Serializes a null-terminated string and writes it into an underlying :c:type:`z_owned_bytes_t`. + * The string should be a valid UTF-8. * * Parameters: * serializer: A serializer instance. @@ -468,8 +469,23 @@ z_result_t ze_deserializer_deserialize_slice(ze_deserializer_t *deserializer, z_ */ z_result_t ze_serializer_serialize_str(ze_loaned_serializer_t *serializer, const char *val); +/** + * Serializes a substring and writes it into an underlying :c:type:`z_owned_bytes_t`. + * The substring should be a valid UTF-8. + * + * Parameters: + * serializer: A serializer instance. + * start: Pointer to the start of the substring to serialize. + * len: Length of the substring to serialize. + * + * Return: + * ``0`` if serialization is successful, ``negative value`` otherwise. + */ +z_result_t ze_serializer_serialize_substr(ze_loaned_serializer_t *serializer, const char *start, size_t len); + /** * Serializes a string and writes it into an underlying :c:type:`z_owned_bytes_t`. + * The string should be a valid UTF-8. * * Parameters: * serializer: A serializer instance. @@ -523,7 +539,7 @@ z_result_t ze_deserializer_deserialize_sequence_length(ze_deserializer_t *deseri * * Parameters: * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized data. - * data: Pointer to the data to serialize. Ownership is transferred to the `bytes`. + * data: Pointer to the data to serialize. * len: Number of bytes to serialize. * * Return: @@ -534,6 +550,7 @@ z_result_t ze_serialize_buf(z_owned_bytes_t *bytes, const uint8_t *data, size_t /** * Serializes a string into a :c:type:`z_owned_bytes_t`. * + * The string should be a valid UTF-8. * Parameters: * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized string. * s: Pointer to the string to serialize. @@ -545,16 +562,31 @@ z_result_t ze_serialize_string(z_owned_bytes_t *bytes, const z_loaned_string_t * /** * Serializes a null-terminated string into a :c:type:`z_owned_bytes_t`. + * The string should be a valid UTF-8. * * Parameters: * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized string. - * value: Pointer to the string to serialize. Ownership is transferred to the `bytes`. + * value: Pointer to the string to serialize. * * Return: * ``0`` if serialization is successful, ``negative value`` otherwise. */ z_result_t ze_serialize_str(z_owned_bytes_t *bytes, const char *value); +/** + * Serializes a substring into a :c:type:`z_owned_bytes_t`. + * The substring should be a valid UTF-8. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized string. + * start: Pointer to the the start of string to serialize. + * len: Length of the substring to serialize. + * + * Return: + * ``0`` if serialization is successful, ``negative value`` otherwise. + */ +z_result_t ze_serialize_substr(z_owned_bytes_t *bytes, const char *start, size_t len); + /** * Serializes a slice into a :c:type:`z_owned_bytes_t`. * diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index 53010ece7..fd89c4972 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -34,13 +34,6 @@ extern "C" { #endif -/** - * Represents a variable-length encoding unsigned integer. - * - * It is equivalent to the size of a ``size_t``. - */ -typedef _z_zint_t z_zint_t; - /** * Represents a Zenoh ID. * @@ -125,7 +118,7 @@ _Z_OWNED_TYPE_VALUE(_z_queryable_t, queryable) /** * Represents a Zenoh Query entity, received by Zenoh Queryable entities. */ -_Z_OWNED_TYPE_RC(_z_query_rc_t, query) +_Z_OWNED_TYPE_VALUE(_z_query_t, query) /** * Represents the encoding of a payload, in a MIME-like format. @@ -417,13 +410,13 @@ _Z_OWNED_TYPE_VALUE(_z_reply_t, reply) */ _Z_OWNED_TYPE_VALUE(_z_string_svec_t, string_array) -typedef void (*z_dropper_handler_t)(void *arg); -typedef _z_sample_handler_t z_sample_handler_t; +typedef void (*z_closure_drop_callback_t)(void *arg); +typedef _z_closure_sample_callback_t z_closure_sample_callback_t; typedef struct { void *context; - z_sample_handler_t call; - z_dropper_handler_t drop; + z_closure_sample_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_sample_t; /** @@ -431,12 +424,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_sample_t, closure_sample) -typedef _z_query_handler_t z_query_handler_t; +typedef _z_closure_query_callback_t z_closure_query_callback_t; typedef struct { void *context; - z_query_handler_t call; - z_dropper_handler_t drop; + z_closure_query_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_query_t; /** @@ -444,12 +437,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_query_t, closure_query) -typedef _z_reply_handler_t z_reply_handler_t; +typedef _z_closure_reply_callback_t z_closure_reply_callback_t; typedef struct { void *context; - z_reply_handler_t call; - z_dropper_handler_t drop; + z_closure_reply_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_reply_t; /** @@ -457,12 +450,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_reply_t, closure_reply) -typedef void (*z_loaned_hello_handler_t)(z_loaned_hello_t *hello, void *arg); +typedef void (*z_closure_hello_callback_t)(z_loaned_hello_t *hello, void *arg); typedef struct { void *context; - z_loaned_hello_handler_t call; - z_dropper_handler_t drop; + z_closure_hello_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_hello_t; /** @@ -470,12 +463,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_hello_t, closure_hello) -typedef void (*z_zid_handler_t)(const z_id_t *id, void *arg); +typedef void (*z_closure_zid_callback_t)(const z_id_t *id, void *arg); typedef struct { void *context; - z_zid_handler_t call; - z_dropper_handler_t drop; + z_closure_zid_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_zid_t; /** diff --git a/include/zenoh-pico/collections/arc_slice.h b/include/zenoh-pico/collections/arc_slice.h index ce67d2975..782373141 100644 --- a/include/zenoh-pico/collections/arc_slice.h +++ b/include/zenoh-pico/collections/arc_slice.h @@ -24,32 +24,41 @@ #include "slice.h" #include "zenoh-pico/system/platform_common.h" -_Z_REFCOUNT_DEFINE(_z_slice, _z_slice) +#ifdef __cplusplus +extern "C" { +#endif + +_Z_SIMPLE_REFCOUNT_DEFINE(_z_slice, _z_slice) /*-------- ArcSlice --------*/ /** * An atomically reference counted subslice. * * Members: - * _z_slice_rc_t len: Rc counted slice. + * _z_slice_simple_rc_t len: Rc counted slice. * size_t start: Offset to the subslice start. * size_t len: Length of the subslice. */ typedef struct { - _z_slice_rc_t slice; + _z_slice_simple_rc_t slice; size_t start; size_t len; } _z_arc_slice_t; -_z_arc_slice_t _z_arc_slice_empty(void); +static inline _z_arc_slice_t _z_arc_slice_empty(void) { return (_z_arc_slice_t){0}; } +static inline size_t _z_arc_slice_len(const _z_arc_slice_t* s) { return s->len; } +static inline bool _z_arc_slice_is_empty(const _z_arc_slice_t* s) { return _z_arc_slice_len(s) == 0; } _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len); +_z_arc_slice_t _z_arc_slice_wrap_slice_rc(_z_slice_simple_rc_t* slice_rc, size_t offset, size_t len); _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len); -size_t _z_arc_slice_len(const _z_arc_slice_t* s); -bool _z_arc_slice_is_empty(const _z_arc_slice_t* s); const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s); z_result_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src); z_result_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src); z_result_t _z_arc_slice_drop(_z_arc_slice_t* s); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_ARC_SLICE_H */ diff --git a/include/zenoh-pico/collections/array.h b/include/zenoh-pico/collections/array.h index 0c08d9af2..b5d077433 100644 --- a/include/zenoh-pico/collections/array.h +++ b/include/zenoh-pico/collections/array.h @@ -19,6 +19,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Internal Array Macros ------------------*/ #define _Z_ARRAY_DEFINE(name, type) \ typedef struct { \ @@ -71,4 +75,8 @@ } \ } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_ARRAY_H */ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index b662ff613..e452d8b4a 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -23,14 +23,15 @@ #include "vec.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + inline size_t _z_arc_slice_size(const _z_arc_slice_t *s) { (void)s; return sizeof(_z_arc_slice_t); } -static inline void _z_arc_slice_elem_move(void *dst, void *src) { - _z_arc_slice_move((_z_arc_slice_t *)dst, (_z_arc_slice_t *)src); -} -_Z_ELEM_DEFINE(_z_arc_slice, _z_arc_slice_t, _z_arc_slice_size, _z_arc_slice_drop, _z_arc_slice_copy) +_Z_ELEM_DEFINE(_z_arc_slice, _z_arc_slice_t, _z_arc_slice_size, _z_arc_slice_drop, _z_arc_slice_copy, _z_arc_slice_move) _Z_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t) /*-------- Bytes --------*/ @@ -45,14 +46,19 @@ typedef struct { _z_arc_slice_svec_t _slices; } _z_bytes_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_bytes_t _z_bytes_null(void) { return (_z_bytes_t){0}; } +static inline void _z_bytes_alias_arc_slice(_z_bytes_t *dst, _z_arc_slice_t *s) { + dst->_slices = _z_arc_slice_svec_alias_element(s); +} bool _z_bytes_check(const _z_bytes_t *bytes); -_z_bytes_t _z_bytes_null(void); z_result_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src); z_result_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s); z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src); _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src); void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src); void _z_bytes_drop(_z_bytes_t *bytes); +void _z_bytes_aliased_drop(_z_bytes_t *bytes); void _z_bytes_free(_z_bytes_t **bs); size_t _z_bytes_num_slices(const _z_bytes_t *bs); _z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i); @@ -94,4 +100,8 @@ void _z_bytes_writer_clear(_z_bytes_writer_t *writer); void _z_bytes_writer_move(_z_bytes_writer_t *dst, _z_bytes_writer_t *src); size_t _z_bytes_reader_remaining(const _z_bytes_reader_t *reader); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_BYTES_H */ diff --git a/include/zenoh-pico/collections/element.h b/include/zenoh-pico/collections/element.h index ef5178ad1..5657a63b9 100644 --- a/include/zenoh-pico/collections/element.h +++ b/include/zenoh-pico/collections/element.h @@ -21,6 +21,10 @@ #include "zenoh-pico/system/platform.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- element functions --------*/ typedef size_t (*z_element_size_f)(void *e); typedef void (*z_element_clear_f)(void *e); @@ -30,7 +34,7 @@ typedef void (*z_element_move_f)(void *dst, void *src); typedef void *(*z_element_clone_f)(const void *e); typedef bool (*z_element_eq_f)(const void *left, const void *right); -#define _Z_ELEM_DEFINE(name, type, elem_size_f, elem_clear_f, elem_copy_f) \ +#define _Z_ELEM_DEFINE(name, type, elem_size_f, elem_clear_f, elem_copy_f, elem_move_f) \ typedef bool (*name##_eq_f)(const type *left, const type *right); \ static inline void name##_elem_clear(void *e) { elem_clear_f((type *)e); } \ static inline void name##_elem_free(void **e) { \ @@ -41,6 +45,7 @@ typedef bool (*z_element_eq_f)(const void *left, const void *right); *e = NULL; \ } \ } \ + static inline void name##_elem_move(void *dst, void *src) { elem_move_f((type *)dst, (type *)src); } \ static inline void name##_elem_copy(void *dst, const void *src) { elem_copy_f((type *)dst, (type *)src); } \ static inline void *name##_elem_clone(const void *src) { \ type *dst = (type *)z_malloc(elem_size_f((type *)src)); \ @@ -72,6 +77,10 @@ static inline void _z_noop_move(void *dst, void *src) { _ZP_UNUSED(src); } -_Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_COLLECTIONS_ELEMENT_H */ diff --git a/include/zenoh-pico/collections/fifo.h b/include/zenoh-pico/collections/fifo.h index 3e36bb509..0f4a887ce 100644 --- a/include/zenoh-pico/collections/fifo.h +++ b/include/zenoh-pico/collections/fifo.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/ring.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Fifo Buffer --------*/ typedef struct { _z_ring_t _ring; @@ -60,4 +64,8 @@ void _z_fifo_free(_z_fifo_t **xs, z_element_free_f f_f); static inline void name##_fifo_clear(name##_fifo_t *r) { _z_fifo_clear(r, name##_elem_free); } \ static inline void name##_fifo_free(name##_fifo_t **r) { _z_fifo_free(r, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_FIFO_H */ diff --git a/include/zenoh-pico/collections/intmap.h b/include/zenoh-pico/collections/intmap.h index c897e2e50..136cf9772 100644 --- a/include/zenoh-pico/collections/intmap.h +++ b/include/zenoh-pico/collections/intmap.h @@ -22,6 +22,10 @@ #include "zenoh-pico/collections/list.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- int-void map --------*/ #define _Z_DEFAULT_INT_MAP_CAPACITY 16 @@ -113,4 +117,8 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); _z_int_void_map_free(m, name##_intmap_entry_elem_free); \ } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_INTMAP_H */ diff --git a/include/zenoh-pico/collections/lifo.h b/include/zenoh-pico/collections/lifo.h index cf696b994..b6142b05a 100644 --- a/include/zenoh-pico/collections/lifo.h +++ b/include/zenoh-pico/collections/lifo.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Ring Buffer --------*/ typedef struct { void **_val; @@ -61,4 +65,8 @@ void _z_lifo_free(_z_lifo_t **xs, z_element_free_f f_f); static inline void name##_lifo_clear(name##_lifo_t *r) { _z_lifo_clear(r, name##_elem_free); } \ static inline void name##_lifo_free(name##_lifo_t **r) { _z_lifo_free(r, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_LIFO_H */ diff --git a/include/zenoh-pico/collections/list.h b/include/zenoh-pico/collections/list.h index a779706f0..590d0f32d 100644 --- a/include/zenoh-pico/collections/list.h +++ b/include/zenoh-pico/collections/list.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Single-linked List --------*/ /** * A single-linked list. @@ -72,4 +76,8 @@ void _z_list_free(_z_list_t **xs, z_element_free_f f_f); static inline name##_list_t *name##_list_clone(name##_list_t *l) { return _z_list_clone(l, name##_elem_clone); } \ static inline void name##_list_free(name##_list_t **l) { _z_list_free(l, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_LIST_H */ diff --git a/include/zenoh-pico/collections/refcount.h b/include/zenoh-pico/collections/refcount.h index 099ab04ae..f1ad023f0 100644 --- a/include/zenoh-pico/collections/refcount.h +++ b/include/zenoh-pico/collections/refcount.h @@ -34,6 +34,12 @@ z_result_t _z_rc_weak_upgrade(void *cnt); size_t _z_rc_weak_count(void *cnt); size_t _z_rc_strong_count(void *cnt); +z_result_t _z_simple_rc_init(void **cnt); +z_result_t _z_simple_rc_increase(void *cnt); +bool _z_simple_rc_decrease(void **cnt); + +size_t _z_simple_rc_strong_count(void *cnt); + /*------------------ Internal Array Macros ------------------*/ #define _Z_REFCOUNT_DEFINE(name, type) \ typedef struct name##_rc_t { \ @@ -46,18 +52,8 @@ size_t _z_rc_strong_count(void *cnt); void *_cnt; \ } name##_weak_t; \ \ - static inline name##_rc_t name##_rc_null(void) { \ - name##_rc_t p; \ - p._val = NULL; \ - p._cnt = NULL; \ - return p; \ - } \ - static inline name##_weak_t name##_weak_null(void) { \ - name##_weak_t p; \ - p._val = NULL; \ - p._cnt = NULL; \ - return p; \ - } \ + static inline name##_rc_t name##_rc_null(void) { return (name##_rc_t){0}; } \ + static inline name##_weak_t name##_weak_null(void) { return (name##_weak_t){0}; } \ \ static inline name##_rc_t name##_rc_new(type##_t *val) { \ name##_rc_t p = name##_rc_null(); \ @@ -80,11 +76,10 @@ size_t _z_rc_strong_count(void *cnt); return p; \ } \ static inline name##_rc_t name##_rc_clone(const name##_rc_t *p) { \ - name##_rc_t c = name##_rc_null(); \ if (_z_rc_increase_strong(p->_cnt) == _Z_RES_OK) { \ - c = *p; \ + return *p; \ } \ - return c; \ + return name##_rc_null(); \ } \ static inline name##_rc_t *name##_rc_clone_as_ptr(const name##_rc_t *p) { \ name##_rc_t *c = (name##_rc_t *)z_malloc(sizeof(name##_rc_t)); \ @@ -97,12 +92,10 @@ size_t _z_rc_strong_count(void *cnt); return c; \ } \ static inline name##_weak_t name##_rc_clone_as_weak(const name##_rc_t *p) { \ - name##_weak_t c = name##_weak_null(); \ if (_z_rc_increase_weak(p->_cnt) == _Z_RES_OK) { \ - c._val = p->_val; \ - c._cnt = p->_cnt; \ + return (name##_weak_t){._val = p->_val, ._cnt = p->_cnt}; \ } \ - return c; \ + return name##_weak_null(); \ } \ static inline name##_weak_t *name##_rc_clone_as_weak_ptr(const name##_rc_t *p) { \ name##_weak_t *c = (name##_weak_t *)z_malloc(sizeof(name##_weak_t)); \ @@ -141,20 +134,17 @@ size_t _z_rc_strong_count(void *cnt); return res; \ } \ static inline name##_weak_t name##_weak_clone(const name##_weak_t *p) { \ - name##_weak_t c = name##_weak_null(); \ if (_z_rc_increase_weak(p->_cnt) == _Z_RES_OK) { \ - c = *p; \ + return *p; \ } \ - return c; \ + return name##_weak_null(); \ } \ static inline void name##_weak_copy(name##_weak_t *dst, const name##_weak_t *p) { *dst = name##_weak_clone(p); } \ static inline name##_rc_t name##_weak_upgrade(const name##_weak_t *p) { \ - name##_rc_t c = name##_rc_null(); \ if (_z_rc_weak_upgrade(p->_cnt) == _Z_RES_OK) { \ - c._val = p->_val; \ - c._cnt = p->_cnt; \ + return (name##_rc_t){._val = p->_val, ._cnt = p->_cnt}; \ } \ - return c; \ + return name##_rc_null(); \ } \ static inline bool name##_weak_eq(const name##_weak_t *left, const name##_weak_t *right) { \ return (left->_val == right->_val); \ @@ -175,6 +165,86 @@ size_t _z_rc_strong_count(void *cnt); return sizeof(name##_rc_t); \ } +#define _Z_SIMPLE_REFCOUNT_DEFINE(name, type) \ + typedef struct name##_simple_rc_t { \ + type##_t *_val; \ + void *_cnt; \ + } name##_simple_rc_t; \ + \ + static inline name##_simple_rc_t name##_simple_rc_null(void) { return (name##_simple_rc_t){0}; } \ + \ + static inline name##_simple_rc_t name##_simple_rc_new(type##_t *val) { \ + name##_simple_rc_t p = name##_simple_rc_null(); \ + if (_z_simple_rc_init(&p._cnt) == _Z_RES_OK) { \ + p._val = val; \ + } \ + return p; \ + } \ + static inline name##_simple_rc_t name##_simple_rc_new_from_val(const type##_t *val) { \ + type##_t *v = (type##_t *)z_malloc(sizeof(type##_t)); \ + if (v == NULL) { \ + return name##_simple_rc_null(); \ + } \ + *v = *val; \ + name##_simple_rc_t p = name##_simple_rc_new(v); \ + if (p._cnt == NULL) { \ + z_free(v); \ + return name##_simple_rc_null(); \ + } \ + return p; \ + } \ + static inline name##_simple_rc_t name##_simple_rc_clone(const name##_simple_rc_t *p) { \ + if (_z_simple_rc_increase(p->_cnt) == _Z_RES_OK) { \ + return *p; \ + } \ + return name##_simple_rc_null(); \ + } \ + static inline name##_simple_rc_t *name##_simple_rc_clone_as_ptr(const name##_simple_rc_t *p) { \ + name##_simple_rc_t *c = (name##_simple_rc_t *)z_malloc(sizeof(name##_simple_rc_t)); \ + if (c != NULL) { \ + *c = name##_simple_rc_clone(p); \ + if (c->_cnt == NULL) { \ + z_free(c); \ + } \ + } \ + return c; \ + } \ + static inline void name##_simple_rc_copy(name##_simple_rc_t *dst, const name##_simple_rc_t *p) { \ + *dst = name##_simple_rc_clone(p); \ + } \ + static inline bool name##_simple_rc_eq(const name##_simple_rc_t *left, const name##_simple_rc_t *right) { \ + return (left->_val == right->_val); \ + } \ + static inline bool name##_simple_rc_decr(name##_simple_rc_t *p) { \ + if ((p == NULL) || (p->_cnt == NULL)) { \ + return false; \ + } \ + if (_z_simple_rc_decrease(&p->_cnt)) { \ + return true; \ + } \ + return false; \ + } \ + static inline bool name##_simple_rc_drop(name##_simple_rc_t *p) { \ + if (p == NULL) { \ + return false; \ + } \ + bool res = false; \ + if (name##_simple_rc_decr(p) && p->_val != NULL) { \ + type##_clear(p->_val); \ + z_free(p->_val); \ + res = true; \ + } \ + *p = name##_simple_rc_null(); \ + return res; \ + } \ + static inline size_t name##_simple_rc_count(const name##_simple_rc_t *p) { \ + return _z_simple_rc_strong_count(p->_cnt); \ + } \ + static inline size_t name##_simple_rc_size(name##_simple_rc_t *p) { \ + _ZP_UNUSED(p); \ + return sizeof(name##_simple_rc_t); \ + } + #ifdef __cplusplus } #endif diff --git a/include/zenoh-pico/collections/ring.h b/include/zenoh-pico/collections/ring.h index de8743e58..d1e26ec57 100644 --- a/include/zenoh-pico/collections/ring.h +++ b/include/zenoh-pico/collections/ring.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Ring Buffer --------*/ typedef struct { void **_val; @@ -65,4 +69,8 @@ void _z_ring_free(_z_ring_t **xs, z_element_free_f f_f); static inline void name##_ring_clear(name##_ring_t *r) { _z_ring_clear(r, name##_elem_free); } \ static inline void name##_ring_free(name##_ring_t **r) { _z_ring_free(r, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_RING_H */ diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index 8027f6b1c..de0c5987a 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -21,14 +21,22 @@ #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { void (*deleter)(void *data, void *context); void *context; } _z_delete_context_t; -_z_delete_context_t _z_delete_context_null(void); -bool _z_delete_context_is_null(const _z_delete_context_t *c); -_z_delete_context_t _z_delete_context_create(void (*deleter)(void *context, void *data), void *context); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_delete_context_t _z_delete_context_null(void) { return (_z_delete_context_t){0}; } + +static inline _z_delete_context_t _z_delete_context_create(void (*deleter)(void *context, void *data), void *context) { + return (_z_delete_context_t){.deleter = deleter, .context = context}; +} +static inline bool _z_delete_context_is_null(const _z_delete_context_t *c) { return c->deleter == NULL; } _z_delete_context_t _z_delete_context_default(void); void _z_delete_context_delete(_z_delete_context_t *c, void *data); @@ -47,24 +55,30 @@ typedef struct { _z_delete_context_t _delete_context; } _z_slice_t; -_z_slice_t _z_slice_empty(void); -inline static bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; } +static inline _z_slice_t _z_slice_null(void) { return (_z_slice_t){0}; } +static inline void _z_slice_reset(_z_slice_t *bs) { *bs = _z_slice_null(); } +static inline bool _z_slice_is_empty(const _z_slice_t *bs) { return bs->len == 0; } +static inline bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; } +static inline _z_slice_t _z_slice_alias(const _z_slice_t bs) { + return (_z_slice_t){.len = bs.len, .start = bs.start, ._delete_context = _z_delete_context_null()}; +} z_result_t _z_slice_init(_z_slice_t *bs, size_t capacity); _z_slice_t _z_slice_make(size_t capacity); _z_slice_t _z_slice_alias_buf(const uint8_t *bs, size_t len); _z_slice_t _z_slice_from_buf_custom_deleter(const uint8_t *p, size_t len, _z_delete_context_t dc); _z_slice_t _z_slice_copy_from_buf(const uint8_t *bs, size_t len); _z_slice_t _z_slice_steal(_z_slice_t *b); -_z_slice_t _z_slice_alias(const _z_slice_t *bs); z_result_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); z_result_t _z_slice_n_copy(_z_slice_t *dst, const _z_slice_t *src, size_t offset, size_t len); _z_slice_t _z_slice_duplicate(const _z_slice_t *src); void _z_slice_move(_z_slice_t *dst, _z_slice_t *src); -void _z_slice_reset(_z_slice_t *bs); -bool _z_slice_is_empty(const _z_slice_t *bs); bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right); void _z_slice_clear(_z_slice_t *bs); void _z_slice_free(_z_slice_t **bs); bool _z_slice_is_alloced(const _z_slice_t *s); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_SLICE_H */ diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index f2ebd15ac..78fc0e5e5 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -21,6 +21,10 @@ #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- str --------*/ typedef char *_z_str_t; @@ -33,7 +37,7 @@ bool _z_str_eq(const char *left, const char *right); size_t _z_str_size(const char *src); void _z_str_copy(char *dst, const char *src); void _z_str_n_copy(char *dst, const char *src, size_t size); -_Z_ELEM_DEFINE(_z_str, char, _z_str_size, _z_noop_clear, _z_str_copy) +_Z_ELEM_DEFINE(_z_str, char, _z_str_size, _z_noop_clear, _z_str_copy, _z_noop_move) _Z_VEC_DEFINE(_z_str, char) _Z_LIST_DEFINE(_z_str, char) @@ -66,11 +70,17 @@ typedef struct { _z_slice_t _slice; } _z_string_t; -_z_string_t _z_string_null(void); -bool _z_string_check(const _z_string_t *value); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_string_t _z_string_null(void) { return (_z_string_t){0}; } +static inline bool _z_string_check(const _z_string_t *value) { return !_z_slice_is_empty(&value->_slice); } +static inline _z_string_t _z_string_alias(const _z_string_t str) { + return (_z_string_t){._slice = _z_slice_alias(str._slice)}; +} + _z_string_t _z_string_copy_from_str(const char *value); _z_string_t _z_string_copy_from_substr(const char *value, size_t len); _z_string_t *_z_string_copy_from_str_as_ptr(const char *value); +_z_string_t _z_string_alias_slice(const _z_slice_t *slice); _z_string_t _z_string_alias_str(const char *value); _z_string_t _z_string_alias_substr(const char *value, size_t len); _z_string_t _z_string_from_str_custom_deleter(char *value, _z_delete_context_t c); @@ -84,20 +94,23 @@ z_result_t _z_string_copy(_z_string_t *dst, const _z_string_t *src); z_result_t _z_string_copy_substring(_z_string_t *dst, const _z_string_t *src, size_t offset, size_t len); void _z_string_move(_z_string_t *dst, _z_string_t *src); _z_string_t _z_string_steal(_z_string_t *str); -_z_string_t _z_string_alias(const _z_string_t *str); void _z_string_move_str(_z_string_t *dst, char *src); void _z_string_clear(_z_string_t *s); void _z_string_free(_z_string_t **s); void _z_string_reset(_z_string_t *s); bool _z_string_equals(const _z_string_t *left, const _z_string_t *right); -_z_string_t _z_string_convert_bytes(const _z_slice_t *bs); +_z_string_t _z_string_convert_bytes_le(const _z_slice_t *bs); _z_string_t _z_string_preallocate(const size_t len); -_Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy) +char *_z_str_from_string_clone(const _z_string_t *str); -static inline void _z_string_elem_move(void *dst, void *src) { _z_string_move((_z_string_t *)dst, (_z_string_t *)src); } +_Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy, _z_string_move) _Z_SVEC_DEFINE(_z_string, _z_string_t) _Z_LIST_DEFINE(_z_string, _z_string_t) _Z_INT_MAP_DEFINE(_z_string, _z_string_t) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_STRING_H */ diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index d1c12ec6b..08ac8207d 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Dynamically allocated vector --------*/ /** * A dynamically allocated vector. Elements are stored as pointers. @@ -29,8 +33,11 @@ typedef struct { void **_val; } _z_vec_t; +static inline _z_vec_t _z_vec_null(void) { return (_z_vec_t){0}; } +static inline _z_vec_t _z_vec_alias(const _z_vec_t *src) { return *src; } _z_vec_t _z_vec_make(size_t capacity); void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f f); +void _z_vec_move(_z_vec_t *dst, _z_vec_t *src); size_t _z_vec_len(const _z_vec_t *v); bool _z_vec_is_empty(const _z_vec_t *v); @@ -59,6 +66,8 @@ void _z_vec_release(_z_vec_t *v); static inline void name##_vec_copy(name##_vec_t *dst, const name##_vec_t *src) { \ _z_vec_copy(dst, src, name##_elem_clone); \ } \ + static inline name##_vec_t name##_vec_alias(const name##_vec_t *v) { return _z_vec_alias(v); } \ + static inline void name##_vec_move(name##_vec_t *dst, name##_vec_t *src) { _z_vec_move(dst, src); } \ static inline void name##_vec_reset(name##_vec_t *v) { _z_vec_reset(v, name##_elem_free); } \ static inline void name##_vec_clear(name##_vec_t *v) { _z_vec_clear(v, name##_elem_free); } \ static inline void name##_vec_free(name##_vec_t **v) { _z_vec_free(v, name##_elem_free); } \ @@ -74,44 +83,71 @@ typedef struct { void *_val; } _z_svec_t; +static inline _z_svec_t _z_svec_null(void) { return (_z_svec_t){0}; } +static inline _z_svec_t _z_svec_alias(const _z_svec_t *src) { return *src; } +static inline _z_svec_t _z_svec_alias_element(void *element) { + return (_z_svec_t){._capacity = 1, ._len = 1, ._val = element}; +} +void _z_svec_init(_z_svec_t *v, size_t offset, size_t element_size); _z_svec_t _z_svec_make(size_t capacity, size_t element_size); -bool _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size); +z_result_t _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size, + bool use_elem_f); +void _z_svec_move(_z_svec_t *dst, _z_svec_t *src); size_t _z_svec_len(const _z_svec_t *v); bool _z_svec_is_empty(const _z_svec_t *v); -bool _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f m, size_t element_size); +z_result_t _z_svec_expand(_z_svec_t *v, z_element_move_f move, size_t element_size, bool use_elem_f); +z_result_t _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f m, size_t element_size, bool use_elem_f); void *_z_svec_get(const _z_svec_t *v, size_t pos, size_t element_size); +void *_z_svec_get_mut(_z_svec_t *v, size_t i, size_t element_size); void _z_svec_set(_z_svec_t *sv, size_t pos, void *e, z_element_clear_f f, size_t element_size); -void _z_svec_remove(_z_svec_t *sv, size_t pos, z_element_clear_f f, z_element_move_f m, size_t element_size); +void _z_svec_remove(_z_svec_t *sv, size_t pos, z_element_clear_f f, z_element_move_f m, size_t element_size, + bool use_elem_f); void _z_svec_reset(_z_svec_t *v, z_element_clear_f f, size_t element_size); void _z_svec_clear(_z_svec_t *v, z_element_clear_f f, size_t element_size); void _z_svec_free(_z_svec_t **v, z_element_clear_f f, size_t element_size); void _z_svec_release(_z_svec_t *v); -#define _Z_SVEC_DEFINE(name, type) \ - typedef _z_svec_t name##_svec_t; \ - static inline name##_svec_t name##_svec_make(size_t capacity) { return _z_svec_make(capacity, sizeof(type)); } \ - static inline size_t name##_svec_len(const name##_svec_t *v) { return _z_svec_len(v); } \ - static inline bool name##_svec_is_empty(const name##_svec_t *v) { return _z_svec_is_empty(v); } \ - static inline bool name##_svec_append(name##_svec_t *v, type *e) { \ - return _z_svec_append(v, e, name##_elem_move, sizeof(type)); \ - } \ - static inline type *name##_svec_get(const name##_svec_t *v, size_t pos) { \ - return (type *)_z_svec_get(v, pos, sizeof(type)); \ - } \ - static inline void name##_svec_set(name##_svec_t *v, size_t pos, type *e) { \ - _z_svec_set(v, pos, e, name##_elem_clear, sizeof(type)); \ - } \ - static inline void name##_svec_remove(name##_svec_t *v, size_t pos) { \ - _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type)); \ - } \ - static inline bool name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src) { \ - return _z_svec_copy(dst, src, name##_elem_copy, sizeof(type)); \ - } \ - static inline void name##_svec_reset(name##_svec_t *v) { _z_svec_reset(v, name##_elem_clear, sizeof(type)); } \ - static inline void name##_svec_clear(name##_svec_t *v) { _z_svec_clear(v, name##_elem_clear, sizeof(type)); } \ +#define _Z_SVEC_DEFINE(name, type) \ + typedef _z_svec_t name##_svec_t; \ + static inline name##_svec_t name##_svec_null(void) { return _z_svec_null(); } \ + static inline name##_svec_t name##_svec_make(size_t capacity) { return _z_svec_make(capacity, sizeof(type)); } \ + static inline void name##_svec_init(name##_svec_t *v, size_t offset) { _z_svec_init(v, offset, sizeof(type)); } \ + static inline size_t name##_svec_len(const name##_svec_t *v) { return _z_svec_len(v); } \ + static inline bool name##_svec_is_empty(const name##_svec_t *v) { return _z_svec_is_empty(v); } \ + static inline z_result_t name##_svec_expand(name##_svec_t *v, bool use_elem_f) { \ + return _z_svec_expand(v, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline z_result_t name##_svec_append(name##_svec_t *v, const type *e, bool use_elem_f) { \ + return _z_svec_append(v, e, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline type *name##_svec_get(const name##_svec_t *v, size_t pos) { \ + return (type *)_z_svec_get(v, pos, sizeof(type)); \ + } \ + static inline type *name##_svec_get_mut(name##_svec_t *v, size_t pos) { \ + return (type *)_z_svec_get_mut(v, pos, sizeof(type)); \ + } \ + static inline void name##_svec_set(name##_svec_t *v, size_t pos, type *e) { \ + _z_svec_set(v, pos, e, name##_elem_clear, sizeof(type)); \ + } \ + static inline void name##_svec_remove(name##_svec_t *v, size_t pos, bool use_elem_f) { \ + _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline z_result_t name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src, bool use_elem_f) { \ + return _z_svec_copy(dst, src, name##_elem_copy, sizeof(type), use_elem_f); \ + } \ + static inline name##_svec_t name##_svec_alias(const name##_svec_t *v) { return _z_svec_alias(v); } \ + static inline name##_svec_t name##_svec_alias_element(type *e) { return _z_svec_alias_element((void *)e); } \ + static inline void name##_svec_move(name##_svec_t *dst, name##_svec_t *src) { _z_svec_move(dst, src); } \ + static inline void name##_svec_reset(name##_svec_t *v) { _z_svec_reset(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_clear(name##_svec_t *v) { _z_svec_clear(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_release(name##_svec_t *v) { _z_svec_release(v); } \ static inline void name##_svec_free(name##_svec_t **v) { _z_svec_free(v, name##_elem_clear, sizeof(type)); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_VECTOR_H */ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index b3c5d3ec1..060afd51b 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -42,6 +42,10 @@ #define Z_FEATURE_FRAGMENTATION 1 #define Z_FEATURE_ENCODING_VALUES 1 #define Z_FEATURE_TCP_NODELAY 1 +#define Z_FEATURE_LOCAL_SUBSCRIBER 0 +#define Z_FEATURE_PUBLISHER_SESSION_CHECK 0 +#define Z_FEATURE_BATCHING 1 +#define Z_FEATURE_RX_CACHE 1 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index 40941d9fa..4e75ac0cb 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -42,6 +42,10 @@ #define Z_FEATURE_FRAGMENTATION @Z_FEATURE_FRAGMENTATION@ #define Z_FEATURE_ENCODING_VALUES @Z_FEATURE_ENCODING_VALUES@ #define Z_FEATURE_TCP_NODELAY @Z_FEATURE_TCP_NODELAY@ +#define Z_FEATURE_LOCAL_SUBSCRIBER @Z_FEATURE_LOCAL_SUBSCRIBER@ +#define Z_FEATURE_PUBLISHER_SESSION_CHECK @Z_FEATURE_PUBLISHER_SESSION_CHECK@ +#define Z_FEATURE_BATCHING @Z_FEATURE_BATCHING@ +#define Z_FEATURE_RX_CACHE @Z_FEATURE_RX_CACHE@ // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/link/config/bt.h b/include/zenoh-pico/link/config/bt.h index 630b9ae41..fca0740d1 100644 --- a/include/zenoh-pico/link/config/bt.h +++ b/include/zenoh-pico/link/config/bt.h @@ -19,6 +19,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_BLUETOOTH == 1 #define BT_CONFIG_ARGC 3 @@ -50,4 +54,8 @@ z_result_t _z_bt_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_bt_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_BT_H */ diff --git a/include/zenoh-pico/link/config/raweth.h b/include/zenoh-pico/link/config/raweth.h index c30cc6403..65700aaba 100644 --- a/include/zenoh-pico/link/config/raweth.h +++ b/include/zenoh-pico/link/config/raweth.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" +#ifdef __cplusplus +extern "C" { +#endif + #define RAWETH_SCHEMA "reth" z_result_t _z_endpoint_raweth_valid(_z_endpoint_t *endpoint); @@ -29,4 +33,8 @@ char *_z_raweth_config_to_str(const _z_str_intmap_t *s); z_result_t _z_raweth_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); z_result_t _z_raweth_config_from_str(_z_str_intmap_t *strint, const char *s); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_RAWETH_H */ diff --git a/include/zenoh-pico/link/config/serial.h b/include/zenoh-pico/link/config/serial.h index 6180d0a59..3b9f6530a 100644 --- a/include/zenoh-pico/link/config/serial.h +++ b/include/zenoh-pico/link/config/serial.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_SERIAL == 1 #define SERIAL_CONFIG_ARGC 1 @@ -66,4 +70,8 @@ z_result_t _z_serial_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_serial_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_SERIAL_H */ diff --git a/include/zenoh-pico/link/config/tcp.h b/include/zenoh-pico/link/config/tcp.h index 51792c8ac..c521a1751 100644 --- a/include/zenoh-pico/link/config/tcp.h +++ b/include/zenoh-pico/link/config/tcp.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_TCP == 1 #define TCP_CONFIG_ARGC 1 @@ -40,4 +44,8 @@ z_result_t _z_tcp_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_tcp_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_TCP_H */ diff --git a/include/zenoh-pico/link/config/udp.h b/include/zenoh-pico/link/config/udp.h index 8af8b5d47..87cd6655e 100644 --- a/include/zenoh-pico/link/config/udp.h +++ b/include/zenoh-pico/link/config/udp.h @@ -18,6 +18,10 @@ #include "zenoh-pico/collections/intmap.h" #include "zenoh-pico/collections/string.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UDP_CONFIG_ARGC 3 #define UDP_CONFIG_IFACE_KEY 0x01 @@ -48,4 +52,8 @@ z_result_t _z_udp_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_udp_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_UDP_H */ diff --git a/include/zenoh-pico/link/config/ws.h b/include/zenoh-pico/link/config/ws.h index e9c3e6be6..a845807c5 100644 --- a/include/zenoh-pico/link/config/ws.h +++ b/include/zenoh-pico/link/config/ws.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_WS == 1 #define WS_CONFIG_TOUT_KEY 0x01 @@ -39,4 +43,8 @@ z_result_t _z_ws_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_ws_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_WS_H */ diff --git a/include/zenoh-pico/link/endpoint.h b/include/zenoh-pico/link/endpoint.h index 4868f4d44..8aa03390e 100644 --- a/include/zenoh-pico/link/endpoint.h +++ b/include/zenoh-pico/link/endpoint.h @@ -21,6 +21,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Locator ------------------*/ #if Z_FEATURE_LINK_TCP == 1 #define TCP_SCHEMA "tcp" @@ -54,7 +58,7 @@ z_result_t _z_locator_from_string(_z_locator_t *lc, _z_string_t *s); size_t _z_locator_size(_z_locator_t *lc); void _z_locator_clear(_z_locator_t *lc); -_Z_ELEM_DEFINE(_z_locator, _z_locator_t, _z_locator_size, _z_locator_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_locator, _z_locator_t, _z_locator_size, _z_locator_clear, _z_noop_copy, _z_noop_move) /*------------------ Locator array ------------------*/ _Z_ARRAY_DEFINE(_z_locator, _z_locator_t) @@ -72,4 +76,8 @@ z_result_t _z_endpoint_from_string(_z_endpoint_t *ep, _z_string_t *s); void _z_endpoint_clear(_z_endpoint_t *ep); void _z_endpoint_free(_z_endpoint_t **ep); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_ENDPOINT_H */ diff --git a/include/zenoh-pico/link/link.h b/include/zenoh-pico/link/link.h index 6356af3cf..522721fe8 100644 --- a/include/zenoh-pico/link/link.h +++ b/include/zenoh-pico/link/link.h @@ -46,6 +46,10 @@ #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Link transport capability enum. * @@ -144,4 +148,8 @@ z_result_t _z_link_send_wbuf(const _z_link_t *zl, const _z_wbuf_t *wbf); size_t _z_link_recv_zbuf(const _z_link_t *zl, _z_zbuf_t *zbf, _z_slice_t *addr); size_t _z_link_recv_exact_zbuf(const _z_link_t *zl, _z_zbuf_t *zbf, size_t len, _z_slice_t *addr); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_H */ diff --git a/include/zenoh-pico/link/manager.h b/include/zenoh-pico/link/manager.h index e0aba1f93..43146ae01 100644 --- a/include/zenoh-pico/link/manager.h +++ b/include/zenoh-pico/link/manager.h @@ -19,10 +19,13 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" -#if Z_FEATURE_LINK_TCP == 1 +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_endpoint_tcp_valid(_z_endpoint_t *ep); z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *ep); -#endif + #if Z_FEATURE_LINK_UDP_UNICAST == 1 z_result_t _z_endpoint_udp_unicast_valid(_z_endpoint_t *ep); z_result_t _z_new_link_udp_unicast(_z_link_t *zl, _z_endpoint_t ep); @@ -44,4 +47,8 @@ z_result_t _z_endpoint_ws_valid(_z_endpoint_t *ep); z_result_t _z_new_link_ws(_z_link_t *zl, _z_endpoint_t *ep); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_MANAGER_H */ diff --git a/include/zenoh-pico/net/config.h b/include/zenoh-pico/net/config.h index fabc7415f..4977f1b5c 100644 --- a/include/zenoh-pico/net/config.h +++ b/include/zenoh-pico/net/config.h @@ -18,6 +18,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/config.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Create an empty set of properties for zenoh-net session configuration. * @@ -50,4 +54,8 @@ z_result_t _z_config_default(_z_config_t *config); */ z_result_t _z_config_client(_z_config_t *config, const char *locator); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_CONFIG_NETAPI_H */ diff --git a/include/zenoh-pico/net/encoding.h b/include/zenoh-pico/net/encoding.h index 88ac5f0d1..79a678084 100644 --- a/include/zenoh-pico/net/encoding.h +++ b/include/zenoh-pico/net/encoding.h @@ -17,6 +17,10 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/collections/string.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_ENCODING_ID_DEFAULT 0 /** @@ -27,13 +31,20 @@ typedef struct _z_encoding_t { uint16_t id; } _z_encoding_t; -z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_encoding_t _z_encoding_null(void) { return (_z_encoding_t){0}; } +static inline bool _z_encoding_check(const _z_encoding_t *encoding) { + return ((encoding->id != _Z_ENCODING_ID_DEFAULT) || _z_string_check(&encoding->schema)); +} _z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema); -_z_encoding_t _z_encoding_null(void); +z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len); void _z_encoding_clear(_z_encoding_t *encoding); -bool _z_encoding_check(const _z_encoding_t *encoding); z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src); void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src); _z_encoding_t _z_encoding_steal(_z_encoding_t *val); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_ENCODING_NETAPI_H */ diff --git a/include/zenoh-pico/net/filtering.h b/include/zenoh-pico/net/filtering.h index 18023b66d..14461a322 100644 --- a/include/zenoh-pico/net/filtering.h +++ b/include/zenoh-pico/net/filtering.h @@ -20,6 +20,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { WRITE_FILTER_INIT = 0, WRITE_FILTER_ACTIVE = 1, @@ -45,4 +49,8 @@ z_result_t _z_write_filter_create(_z_publisher_t *pub); z_result_t _z_write_filter_destroy(_z_publisher_t *pub); bool _z_write_filter_active(const _z_publisher_t *pub); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_FILTERING_NETAPI_H */ diff --git a/include/zenoh-pico/net/logger.h b/include/zenoh-pico/net/logger.h index 73a4bede1..b9bbede1a 100644 --- a/include/zenoh-pico/net/logger.h +++ b/include/zenoh-pico/net/logger.h @@ -15,9 +15,17 @@ #ifndef ZENOH_PICO_LOGGER_NETAPI_H #define ZENOH_PICO_LOGGER_NETAPI_H +#ifdef __cplusplus +extern "C" { +#endif + /** * Initialise the zenoh runtime logger */ void _z_init_logger(void); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LOGGER_NETAPI_H */ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index f5a27034a..95b47078b 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -26,6 +26,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/config.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Discovery ------------------*/ /** @@ -38,7 +42,7 @@ * timeout: The time that should be spent scouting before returning the results. */ void _z_scout(const z_what_t what, const _z_id_t zid, _z_string_t *locator, const uint32_t timeout, - _z_hello_handler_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop); + _z_closure_hello_callback_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop); /*------------------ Declarations ------------------*/ @@ -144,8 +148,8 @@ z_result_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, _z_bytes_t pay * Returns: * The created :c:type:`_z_subscriber_t` (in null state if the declaration failed). */ -_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_sample_handler_t callback, - _z_drop_handler_t dropper, void *arg); +_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, + _z_closure_sample_callback_t callback, _z_drop_handler_t dropper, void *arg); /** * Undeclare a :c:type:`_z_subscriber_t`. @@ -175,7 +179,7 @@ z_result_t _z_undeclare_subscriber(_z_subscriber_t *sub); * The created :c:type:`_z_queryable_t` (in null state if the declaration failed).. */ _z_queryable_t _z_declare_queryable(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, bool complete, - _z_query_handler_t callback, _z_drop_handler_t dropper, void *arg); + _z_closure_query_callback_t callback, _z_drop_handler_t dropper, void *arg); /** * Undeclare a :c:type:`_z_queryable_t`. @@ -245,9 +249,10 @@ z_result_t _z_send_reply_err(const _z_query_t *query, const _z_session_rc_t *zsr * */ z_result_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, const z_query_target_t target, - const z_consolidation_mode_t consolidation, const _z_value_t value, _z_reply_handler_t callback, - _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms, const _z_bytes_t attachment, - z_congestion_control_t cong_ctrl, z_priority_t priority, bool is_express); + const z_consolidation_mode_t consolidation, const _z_value_t value, + _z_closure_reply_callback_t callback, _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms, + const _z_bytes_t attachment, z_congestion_control_t cong_ctrl, z_priority_t priority, + bool is_express); #endif #if Z_FEATURE_INTEREST == 1 @@ -256,4 +261,8 @@ uint32_t _z_add_interest(_z_session_t *zn, _z_keyexpr_t keyexpr, _z_interest_han z_result_t _z_remove_interest(_z_session_t *zn, uint32_t interest_id); #endif +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_NET_PRIMITIVES_H */ diff --git a/include/zenoh-pico/net/publish.h b/include/zenoh-pico/net/publish.h index 21a8b500f..b270f4eb3 100644 --- a/include/zenoh-pico/net/publish.h +++ b/include/zenoh-pico/net/publish.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Return type when declaring a publisher. */ @@ -37,10 +41,15 @@ typedef struct _z_publisher_t { } _z_publisher_t; #if Z_FEATURE_PUBLICATION == 1 +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_publisher_t _z_publisher_null(void) { return (_z_publisher_t){0}; } +static inline bool _z_publisher_check(const _z_publisher_t *publisher) { return !_Z_RC_IS_NULL(&publisher->_zn); } void _z_publisher_clear(_z_publisher_t *pub); void _z_publisher_free(_z_publisher_t **pub); -bool _z_publisher_check(const _z_publisher_t *publisher); -_z_publisher_t _z_publisher_null(void); +#endif + +#ifdef __cplusplus +} #endif #endif /* INCLUDE_ZENOH_PICO_NET_PUBLISH_H */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 5e57c1eee..82dbe9d8c 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -21,26 +21,33 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * The query to be answered by a queryable. */ typedef struct _z_query_t { - _z_value_t _value; _z_keyexpr_t _key; + _z_value_t _value; uint32_t _request_id; - _z_session_weak_t _zn; // Can't be an rc because of cross referencing - _z_bytes_t attachment; - char *_parameters; + _z_session_rc_t _zn; + _z_bytes_t _attachment; + _z_string_t _parameters; bool _anyke; } _z_query_t; -_z_query_t _z_query_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_query_t _z_query_null(void) { return (_z_query_t){0}; } +static inline bool _z_query_check(const _z_query_t *query) { + return _z_keyexpr_check(&query->_key) || _z_value_check(&query->_value) || _z_bytes_check(&query->_attachment) || + _z_string_check(&query->_parameters); +} void _z_query_clear(_z_query_t *q); z_result_t _z_query_copy(_z_query_t *dst, const _z_query_t *src); void _z_query_free(_z_query_t **query); -_Z_REFCOUNT_DEFINE(_z_query, _z_query) - /** * Return type when declaring a queryable. */ @@ -50,12 +57,29 @@ typedef struct { } _z_queryable_t; #if Z_FEATURE_QUERYABLE == 1 -_z_query_t _z_query_create(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, _z_session_rc_t *zn, - uint32_t request_id, const _z_bytes_t attachment); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_queryable_t _z_queryable_null(void) { return (_z_queryable_t){0}; } +static inline bool _z_queryable_check(const _z_queryable_t *queryable) { return !_Z_RC_IS_NULL(&queryable->_zn); } +static inline _z_query_t _z_query_alias(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, + _z_session_rc_t *zn, uint32_t request_id, const _z_bytes_t *attachment, + bool anyke) { + return (_z_query_t){ + ._key = *key, + ._value = *value, + ._request_id = request_id, + ._zn = *zn, + ._attachment = *attachment, + ._parameters = _z_string_alias_slice(parameters), + ._anyke = anyke, + }; +} void _z_queryable_clear(_z_queryable_t *qbl); void _z_queryable_free(_z_queryable_t **qbl); -_z_queryable_t _z_queryable_null(void); -bool _z_queryable_check(const _z_queryable_t *queryable); + +#endif + +#ifdef __cplusplus +} #endif #endif /* ZENOH_PICO_QUERY_NETAPI_H */ diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index 14ef1b232..17008c14e 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -23,6 +23,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Reply tag values. * @@ -57,10 +61,12 @@ typedef struct _z_reply_data_t { _z_reply_tag_t _tag; } _z_reply_data_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_reply_data_t _z_reply_data_null(void) { return (_z_reply_data_t){0}; } void _z_reply_data_clear(_z_reply_data_t *rd); z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src); -_Z_ELEM_DEFINE(_z_reply_data, _z_reply_data_t, _z_noop_size, _z_reply_data_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_reply_data, _z_reply_data_t, _z_noop_size, _z_reply_data_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_reply_data, _z_reply_data_t) /** @@ -76,15 +82,29 @@ typedef struct _z_reply_t { _z_reply_data_t data; } _z_reply_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_reply_t _z_reply_null(void) { return (_z_reply_t){0}; } +static inline _z_reply_t _z_reply_alias(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, + const _z_bytes_t *attachment) { + _z_reply_t r; + r.data.replier_id = id; + r.data._tag = _Z_REPLY_TAG_DATA; + r.data._result.sample = _z_sample_alias(keyexpr, payload, timestamp, encoding, kind, _Z_N_QOS_DEFAULT, attachment, + Z_RELIABILITY_DEFAULT); + return r; +} +static inline _z_reply_t _z_reply_err_alias(const _z_bytes_t *payload, _z_encoding_t *encoding) { + _z_reply_t r; + r.data._tag = _Z_REPLY_TAG_ERROR; + r.data._result.error.payload = *payload; + r.data._result.error.encoding = *encoding; + return r; +} _z_reply_t _z_reply_move(_z_reply_t *src_reply); - -_z_reply_t _z_reply_null(void); void _z_reply_clear(_z_reply_t *src); void _z_reply_free(_z_reply_t **hello); z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src); -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, z_sample_kind_t kind, const _z_bytes_t attachment); -_z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding); typedef struct _z_pending_reply_t { _z_reply_t _reply; @@ -94,7 +114,11 @@ typedef struct _z_pending_reply_t { bool _z_pending_reply_eq(const _z_pending_reply_t *one, const _z_pending_reply_t *two); void _z_pending_reply_clear(_z_pending_reply_t *res); -_Z_ELEM_DEFINE(_z_pending_reply, _z_pending_reply_t, _z_noop_size, _z_pending_reply_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_pending_reply, _z_pending_reply_t, _z_noop_size, _z_pending_reply_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_pending_reply, _z_pending_reply_t) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_REPLY_NETAPI_H */ diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index 9fadfbc76..1a93909dc 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -18,6 +18,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * A zenoh-net data sample. * @@ -40,8 +44,27 @@ typedef struct _z_sample_t { } _z_sample_t; void _z_sample_clear(_z_sample_t *sample); -_z_sample_t _z_sample_null(void); -bool _z_sample_check(const _z_sample_t *sample); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_sample_t _z_sample_null(void) { return (_z_sample_t){0}; } +static inline bool _z_sample_check(const _z_sample_t *sample) { + return _z_keyexpr_check(&sample->keyexpr) || _z_encoding_check(&sample->encoding) || + _z_bytes_check(&sample->payload) || _z_bytes_check(&sample->attachment); +} +static inline _z_sample_t _z_sample_alias(const _z_keyexpr_t *key, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, const _z_encoding_t *encoding, + const z_sample_kind_t kind, const _z_qos_t qos, const _z_bytes_t *attachment, + z_reliability_t reliability) { + return (_z_sample_t){ + .keyexpr = *key, + .payload = *payload, + .timestamp = *timestamp, + .encoding = *encoding, + .kind = kind, + .qos = qos, + .attachment = *attachment, + .reliability = reliability, + }; +} void _z_sample_move(_z_sample_t *dst, _z_sample_t *src); /** @@ -55,8 +78,7 @@ void _z_sample_free(_z_sample_t **sample); z_result_t _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src); _z_sample_t _z_sample_duplicate(const _z_sample_t *src); -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t attachment, z_reliability_t reliability); - +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_SAMPLE_NETAPI_H */ diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index 6d7ede3a4..1d3d1e6a5 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -21,9 +21,15 @@ #include "zenoh-pico/collections/list.h" #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/session.h" +#include "zenoh-pico/session/subscription.h" #include "zenoh-pico/utils/config.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * A zenoh-net session. */ @@ -52,11 +58,17 @@ typedef struct _z_session_t { #if Z_FEATURE_SUBSCRIPTION == 1 _z_subscription_rc_list_t *_local_subscriptions; _z_subscription_rc_list_t *_remote_subscriptions; +#if Z_FEATURE_RX_CACHE == 1 + _z_subscription_cache_t _subscription_cache; +#endif #endif // Session queryables #if Z_FEATURE_QUERYABLE == 1 _z_session_queryable_rc_list_t *_local_queryable; +#if Z_FEATURE_RX_CACHE == 1 + _z_queryable_cache_t _queryable_cache; +#endif #endif #if Z_FEATURE_QUERY == 1 _z_pending_query_list_t *_pending_queries; @@ -199,4 +211,8 @@ z_result_t _zp_start_lease_task(_z_session_t *z, z_task_attr_t *attr); z_result_t _zp_stop_lease_task(_z_session_t *z); #endif // Z_FEATURE_MULTI_THREAD == 1 +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_NET_SESSION_H */ diff --git a/include/zenoh-pico/net/subscribe.h b/include/zenoh-pico/net/subscribe.h index 4cf0cb4d4..2357a0c8a 100644 --- a/include/zenoh-pico/net/subscribe.h +++ b/include/zenoh-pico/net/subscribe.h @@ -20,6 +20,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Return type when declaring a subscriber. */ @@ -29,11 +33,16 @@ typedef struct { } _z_subscriber_t; #if Z_FEATURE_SUBSCRIPTION == 1 - +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_subscriber_t _z_subscriber_null(void) { return (_z_subscriber_t){0}; } +static inline bool _z_subscriber_check(const _z_subscriber_t *subscriber) { return !_Z_RC_IS_NULL(&subscriber->_zn); } void _z_subscriber_clear(_z_subscriber_t *sub); void _z_subscriber_free(_z_subscriber_t **sub); -bool _z_subscriber_check(const _z_subscriber_t *subscriber); -_z_subscriber_t _z_subscriber_null(void); + +#endif + +#ifdef __cplusplus +} #endif #endif /* ZENOH_PICO_SUBSCRIBE_NETAPI_H */ diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h index c86d1b18c..db0acee39 100644 --- a/include/zenoh-pico/protocol/codec/core.h +++ b/include/zenoh-pico/protocol/codec/core.h @@ -24,6 +24,10 @@ #include "zenoh-pico/utils/config.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef z_result_t (*__z_single_byte_reader_t)(uint8_t *, void *context); /*------------------ Internal Zenoh-net Macros ------------------*/ z_result_t _z_consolidation_mode_encode(_z_wbuf_t *wbf, z_consolidation_mode_t en); @@ -61,7 +65,7 @@ z_result_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf); z_result_t _z_slice_encode(_z_wbuf_t *buf, const _z_slice_t *bs); z_result_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *buf); -z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf); +z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf, _z_arc_slice_t *arcs); z_result_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs); z_result_t _z_zbuf_read_exact(_z_zbuf_t *zbf, uint8_t *dest, size_t length); @@ -84,4 +88,8 @@ z_result_t _z_timestamp_encode(_z_wbuf_t *buf, const _z_timestamp_t *ts); z_result_t _z_timestamp_encode_ext(_z_wbuf_t *buf, const _z_timestamp_t *ts); z_result_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *buf); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_CORE_H */ diff --git a/include/zenoh-pico/protocol/codec/declarations.h b/include/zenoh-pico/protocol/codec/declarations.h index 86efb1a64..840061d92 100644 --- a/include/zenoh-pico/protocol/codec/declarations.h +++ b/include/zenoh-pico/protocol/codec/declarations.h @@ -17,6 +17,11 @@ #include "zenoh-pico/protocol/definitions/declarations.h" #include "zenoh-pico/protocol/iobuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_DECL_KEXPR_MID 0 #define _Z_DECL_KEXPR_FLAG_N 0x20 #define _Z_UNDECL_KEXPR_MID 1 @@ -50,4 +55,8 @@ z_result_t _z_undecl_token_decode(_z_undecl_token_t *decl, _z_zbuf_t *zbf, uint8 z_result_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl); z_result_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/codec/ext.h b/include/zenoh-pico/protocol/codec/ext.h index 7efd7063e..cc339dd0d 100644 --- a/include/zenoh-pico/protocol/codec/ext.h +++ b/include/zenoh-pico/protocol/codec/ext.h @@ -21,6 +21,10 @@ #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Message Extension ------------------*/ z_result_t _z_msg_ext_encode(_z_wbuf_t *wbf, const _z_msg_ext_t *ext, bool has_next); z_result_t _z_msg_ext_decode(_z_msg_ext_t *ext, _z_zbuf_t *zbf, bool *has_next); @@ -66,4 +70,8 @@ z_result_t _z_msg_ext_encode_zbuf(_z_wbuf_t *wbf, const _z_msg_ext_zbuf_t *pld); z_result_t _z_msg_ext_decode_zbuf(_z_msg_ext_zbuf_t *pld, _z_zbuf_t *zbf); z_result_t _z_msg_ext_decode_zbuf_na(_z_msg_ext_zbuf_t *pld, _z_zbuf_t *zbf); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TEST_H */ diff --git a/include/zenoh-pico/protocol/codec/interest.h b/include/zenoh-pico/protocol/codec/interest.h index 4e8aa4921..b8781efbe 100644 --- a/include/zenoh-pico/protocol/codec/interest.h +++ b/include/zenoh-pico/protocol/codec/interest.h @@ -18,7 +18,15 @@ #include "zenoh-pico/protocol/definitions/interest.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_interest_encode(_z_wbuf_t *wbf, const _z_interest_t *interest, bool is_final); z_result_t _z_interest_decode(_z_interest_t *decl, _z_zbuf_t *zbf, bool is_final, bool has_ext); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/codec/message.h b/include/zenoh-pico/protocol/codec/message.h index c9bd9c039..c877ea884 100644 --- a/include/zenoh-pico/protocol/codec/message.h +++ b/include/zenoh-pico/protocol/codec/message.h @@ -18,22 +18,30 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb); -z_result_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *query); z_result_t _z_query_decode(_z_msg_query_t *query, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_reply_encode(_z_wbuf_t *wbf, const _z_msg_reply_t *reply); -z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_err_encode(_z_wbuf_t *wbf, const _z_msg_err_t *err); -z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_put_encode(_z_wbuf_t *wbf, const _z_msg_put_t *put); -z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del); z_result_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_MESSAGE_H */ diff --git a/include/zenoh-pico/protocol/codec/network.h b/include/zenoh-pico/protocol/codec/network.h index 64a5229c8..661ee9de2 100644 --- a/include/zenoh-pico/protocol/codec/network.h +++ b/include/zenoh-pico/protocol/codec/network.h @@ -19,12 +19,17 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/iobuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_push_encode(_z_wbuf_t *wbf, const _z_n_msg_push_t *msg); -z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_request_encode(_z_wbuf_t *wbf, const _z_n_msg_request_t *msg); -z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg); -z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_final_t *msg); z_result_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_declare_encode(_z_wbuf_t *wbf, const _z_n_msg_declare_t *decl); @@ -33,6 +38,10 @@ z_result_t _z_n_interest_encode(_z_wbuf_t *wbf, const _z_n_msg_interest_t *inter z_result_t _z_n_interest_decode(_z_n_msg_interest_t *interest, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg); -z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf); +z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_t *arcs); + +#ifdef __cplusplus +} +#endif #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/codec/transport.h b/include/zenoh-pico/protocol/codec/transport.h index cd0e4a2c5..eee9feb47 100644 --- a/include/zenoh-pico/protocol/codec/transport.h +++ b/include/zenoh-pico/protocol/codec/transport.h @@ -17,13 +17,17 @@ #include "zenoh-pico/protocol/definitions/transport.h" #include "zenoh-pico/protocol/iobuf.h" -#define _ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE 32 + +#ifdef __cplusplus +extern "C" { +#endif z_result_t _z_scouting_message_encode(_z_wbuf_t *buf, const _z_scouting_message_t *msg); z_result_t _z_scouting_message_decode(_z_scouting_message_t *msg, _z_zbuf_t *buf); z_result_t _z_transport_message_encode(_z_wbuf_t *buf, const _z_transport_message_t *msg); -z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *buf); +z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *buf, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool); z_result_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg); z_result_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header); @@ -41,11 +45,14 @@ z_result_t _z_keep_alive_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_k z_result_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_t *msg); -z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool); z_result_t _z_fragment_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_fragment_t *msg); z_result_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t header); -z_result_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_message_t *msg); -z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index 7dcf49508..7a9a79efb 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -29,6 +29,10 @@ #include "zenoh-pico/net/encoding.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_OPTIONAL #define _Z_MOVE(x) x * @@ -54,22 +58,28 @@ typedef size_t _z_zint_t; typedef struct { uint8_t id[16]; } _z_id_t; +extern const _z_id_t empty_id; uint8_t _z_id_len(_z_id_t id); -bool _z_id_check(_z_id_t id); -_z_id_t _z_id_empty(void); +static inline bool _z_id_check(_z_id_t id) { return memcmp(&id, &empty_id, sizeof(id)) != 0; } +static inline _z_id_t _z_id_empty(void) { return (_z_id_t){0}; } /** * A zenoh timestamp. */ typedef struct { + bool valid; _z_id_t id; uint64_t time; } _z_timestamp_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_timestamp_t _z_timestamp_null(void) { return (_z_timestamp_t){0}; } +static inline void _z_timestamp_invalid(_z_timestamp_t *tstamp) { tstamp->valid = false; } +static inline bool _z_timestamp_check(const _z_timestamp_t *tstamp) { return tstamp->valid; } +void _z_timestamp_copy(_z_timestamp_t *dst, const _z_timestamp_t *src); _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp); -_z_timestamp_t _z_timestamp_null(void); void _z_timestamp_clear(_z_timestamp_t *tstamp); -bool _z_timestamp_check(const _z_timestamp_t *stamp); +void _z_timestamp_move(_z_timestamp_t *dst, _z_timestamp_t *src); uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos); /** @@ -163,7 +173,12 @@ typedef struct { _z_bytes_t payload; _z_encoding_t encoding; } _z_value_t; -_z_value_t _z_value_null(void); + +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_value_t _z_value_null(void) { return (_z_value_t){0}; } +static inline bool _z_value_check(const _z_value_t *value) { + return _z_bytes_check(&value->payload) || _z_encoding_check(&value->encoding); +} _z_value_t _z_value_steal(_z_value_t *value); z_result_t _z_value_copy(_z_value_t *dst, const _z_value_t *src); void _z_value_move(_z_value_t *dst, _z_value_t *src); @@ -184,13 +199,16 @@ typedef struct { z_whatami_t _whatami; uint8_t _version; } _z_hello_t; + +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_hello_t _z_hello_null(void) { return (_z_hello_t){0}; } void _z_hello_clear(_z_hello_t *src); void _z_hello_free(_z_hello_t **hello); z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src); -_z_hello_t _z_hello_null(void); + bool _z_hello_check(const _z_hello_t *hello); -_Z_ELEM_DEFINE(_z_hello, _z_hello_t, _z_noop_size, _z_hello_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_hello, _z_hello_t, _z_noop_size, _z_hello_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_hello, _z_hello_t) typedef struct { @@ -202,11 +220,17 @@ typedef struct { uint32_t _entity_id; uint32_t _source_sn; } _z_source_info_t; -_z_source_info_t _z_source_info_null(void); + +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_source_info_t _z_source_info_null(void) { return (_z_source_info_t){0}; } typedef struct { uint32_t _request_id; uint32_t _entity_id; } _z_reply_context_t; +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CORE_H */ diff --git a/include/zenoh-pico/protocol/definitions/declarations.h b/include/zenoh-pico/protocol/definitions/declarations.h index c33cab627..35c5e3a8e 100644 --- a/include/zenoh-pico/protocol/definitions/declarations.h +++ b/include/zenoh-pico/protocol/definitions/declarations.h @@ -20,26 +20,34 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { uint16_t _id; _z_keyexpr_t _keyexpr; } _z_decl_kexpr_t; -_z_decl_kexpr_t _z_decl_kexpr_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_kexpr_t _z_decl_kexpr_null(void) { return (_z_decl_kexpr_t){0}; } typedef struct { uint16_t _id; } _z_undecl_kexpr_t; -_z_undecl_kexpr_t _z_undecl_kexpr_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_kexpr_t _z_undecl_kexpr_null(void) { return (_z_undecl_kexpr_t){0}; } typedef struct { _z_keyexpr_t _keyexpr; uint32_t _id; } _z_decl_subscriber_t; -_z_decl_subscriber_t _z_decl_subscriber_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_subscriber_t _z_decl_subscriber_null(void) { return (_z_decl_subscriber_t){0}; } typedef struct { uint32_t _id; _z_keyexpr_t _ext_keyexpr; } _z_undecl_subscriber_t; -_z_undecl_subscriber_t _z_undecl_subscriber_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_subscriber_t _z_undecl_subscriber_null(void) { return (_z_undecl_subscriber_t){0}; } typedef struct { _z_keyexpr_t _keyexpr; @@ -49,28 +57,33 @@ typedef struct { uint16_t _distance; } _ext_queryable_info; } _z_decl_queryable_t; -_z_decl_queryable_t _z_decl_queryable_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_queryable_t _z_decl_queryable_null(void) { return (_z_decl_queryable_t){0}; } typedef struct { uint32_t _id; _z_keyexpr_t _ext_keyexpr; } _z_undecl_queryable_t; -_z_undecl_queryable_t _z_undecl_queryable_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_queryable_t _z_undecl_queryable_null(void) { return (_z_undecl_queryable_t){0}; } typedef struct { _z_keyexpr_t _keyexpr; uint32_t _id; } _z_decl_token_t; -_z_decl_token_t _z_decl_token_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_token_t _z_decl_token_null(void) { return (_z_decl_token_t){0}; } typedef struct { uint32_t _id; _z_keyexpr_t _ext_keyexpr; } _z_undecl_token_t; -_z_undecl_token_t _z_undecl_token_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_token_t _z_undecl_token_null(void) { return (_z_undecl_token_t){0}; } typedef struct { bool _placeholder; // In case we add extensions } _z_decl_final_t; -_z_decl_final_t _z_decl_final_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_final_t _z_decl_final_null(void) { return (_z_decl_final_t){0}; } typedef struct { enum { @@ -113,4 +126,8 @@ _z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL const _z_keyexpr_ _z_declaration_t _z_make_decl_final(void); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/definitions/interest.h b/include/zenoh-pico/protocol/definitions/interest.h index ca2900874..46a9ac7a3 100644 --- a/include/zenoh-pico/protocol/definitions/interest.h +++ b/include/zenoh-pico/protocol/definitions/interest.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_INTEREST_FLAG_KEYEXPRS (1) #define _Z_INTEREST_FLAG_SUBSCRIBERS (1 << 1) #define _Z_INTEREST_FLAG_QUERYABLES (1 << 2) @@ -36,11 +40,15 @@ typedef struct { uint32_t _id; uint8_t flags; } _z_interest_t; -_z_interest_t _z_interest_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_interest_t _z_interest_null(void) { return (_z_interest_t){0}; } void _z_interest_clear(_z_interest_t* decl); - _z_interest_t _z_make_interest(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint8_t flags); _z_interest_t _z_make_interest_final(uint32_t id); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_INTEREST_H */ diff --git a/include/zenoh-pico/protocol/definitions/message.h b/include/zenoh-pico/protocol/definitions/message.h index 5d43defa4..2cfa93cd3 100644 --- a/include/zenoh-pico/protocol/definitions/message.h +++ b/include/zenoh-pico/protocol/definitions/message.h @@ -18,6 +18,11 @@ #include "zenoh-pico/net/encoding.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/core.h" + +#ifdef __cplusplus +extern "C" { +#endif + /* Zenoh Messages */ #define _Z_MID_Z_OAM 0x00 #define _Z_MID_Z_PUT 0x01 @@ -140,4 +145,8 @@ typedef struct { void _z_msg_reply_clear(_z_msg_reply_t *msg); #define _Z_FLAG_Z_R_C 0x20 +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_MESSAGE_H */ diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index f0cd40f01..f828d48f1 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -25,6 +25,11 @@ #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/keyexpr.h" + +#ifdef __cplusplus +extern "C" { +#endif + /* Network Messages */ #define _Z_MID_N_OAM 0x1f #define _Z_MID_N_DECLARE 0x1e @@ -91,7 +96,7 @@ static inline bool _z_n_qos_get_express(_z_n_qos_t n_qos) { return (bool)(n_qos. #define _z_n_qos_make(express, nodrop, priority) \ _z_n_qos_create((bool)express, nodrop ? Z_CONGESTION_CONTROL_BLOCK : Z_CONGESTION_CONTROL_DROP, \ (z_priority_t)priority) -#define _Z_N_QOS_DEFAULT _z_n_qos_make(0, 0, 5) +#define _Z_N_QOS_DEFAULT ((_z_qos_t){._val = 5}) // RESPONSE FINAL message flags: // Z Extensions if Z==1 then Zenoh extensions are present @@ -149,7 +154,9 @@ _z_n_msg_request_exts_t _z_n_msg_request_needed_exts(const _z_n_msg_request_t *m void _z_n_msg_request_clear(_z_n_msg_request_t *msg); typedef _z_reply_body_t _z_push_body_t; -_z_push_body_t _z_push_body_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_push_body_t _z_push_body_null(void) { return (_z_push_body_t){0}; } + _z_push_body_t _z_push_body_steal(_z_push_body_t *msg); void _z_push_body_clear(_z_push_body_t *msg); @@ -287,8 +294,8 @@ void _z_n_msg_clear(_z_network_message_t *m); void _z_n_msg_free(_z_network_message_t **m); inline static void _z_msg_clear(_z_zenoh_message_t *msg) { _z_n_msg_clear(msg); } inline static void _z_msg_free(_z_zenoh_message_t **msg) { _z_n_msg_free(msg); } -_Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_clear, _z_noop_copy) -_Z_VEC_DEFINE(_z_network_message, _z_network_message_t) +_Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_clear, _z_noop_copy, _z_noop_move) +_Z_SVEC_DEFINE(_z_network_message, _z_network_message_t) void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping); _z_network_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_slice_t) parameters, _z_zint_t qid, @@ -300,5 +307,10 @@ _z_network_message_t _z_n_msg_make_response_final(_z_zint_t rid); _z_network_message_t _z_n_msg_make_declare(_z_declaration_t declaration, bool has_interest_id, uint32_t interest_id); _z_network_message_t _z_n_msg_make_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_push_body_t) body); _z_network_message_t _z_n_msg_make_interest(_z_interest_t interest); +z_result_t _z_n_msg_copy(_z_network_message_t *dst, const _z_network_message_t *src); + +#ifdef __cplusplus +} +#endif #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/definitions/transport.h b/include/zenoh-pico/protocol/definitions/transport.h index 7334f391a..046cd815b 100644 --- a/include/zenoh-pico/protocol/definitions/transport.h +++ b/include/zenoh-pico/protocol/definitions/transport.h @@ -21,6 +21,10 @@ #include "zenoh-pico/link/endpoint.h" #include "zenoh-pico/protocol/definitions/network.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_MID_SCOUT 0x01 #define _Z_MID_HELLO 0x02 @@ -444,7 +448,7 @@ void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg); // - if R==1 then the FRAME is sent on the reliable channel, best-effort otherwise. // typedef struct { - _z_network_message_vec_t _messages; + _z_network_message_svec_t _messages; _z_zint_t _sn; } _z_t_msg_frame_t; void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg); @@ -507,7 +511,7 @@ _z_transport_message_t _z_t_msg_make_open_syn(_z_zint_t lease, _z_zint_t initial _z_transport_message_t _z_t_msg_make_open_ack(_z_zint_t lease, _z_zint_t initial_sn); _z_transport_message_t _z_t_msg_make_close(uint8_t reason, bool link_only); _z_transport_message_t _z_t_msg_make_keep_alive(void); -_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages, +_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_svec_t messages, z_reliability_t reliability); _z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t reliability); _z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, z_reliability_t reliability, bool is_last); @@ -541,4 +545,8 @@ void _z_s_msg_copy(_z_scouting_message_t *clone, _z_scouting_message_t *msg); void _z_s_msg_copy_scout(_z_s_msg_scout_t *clone, _z_s_msg_scout_t *msg); void _z_s_msg_copy_hello(_z_s_msg_hello_t *clone, _z_s_msg_hello_t *msg); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/ext.h b/include/zenoh-pico/protocol/ext.h index cba1ab55d..989d7491d 100644 --- a/include/zenoh-pico/protocol/ext.h +++ b/include/zenoh-pico/protocol/ext.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /*=============================*/ /* Message header */ /*=============================*/ @@ -96,7 +100,11 @@ void _z_msg_ext_copy_unit(_z_msg_ext_unit_t *clone, const _z_msg_ext_unit_t *ext void _z_msg_ext_copy_zint(_z_msg_ext_zint_t *clone, const _z_msg_ext_zint_t *ext); void _z_msg_ext_copy_zbuf(_z_msg_ext_zbuf_t *clone, const _z_msg_ext_zbuf_t *ext); -_Z_ELEM_DEFINE(_z_msg_ext, _z_msg_ext_t, _z_noop_size, _z_msg_ext_clear, _z_msg_ext_copy) +_Z_ELEM_DEFINE(_z_msg_ext, _z_msg_ext_t, _z_noop_size, _z_msg_ext_clear, _z_msg_ext_copy, _z_noop_move) _Z_VEC_DEFINE(_z_msg_ext, _z_msg_ext_t) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_PROTOCOL_EXTENSION_H */ diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index 888b69d46..bea659d34 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -19,10 +19,15 @@ #include #include +#include "zenoh-pico/collections/arc_slice.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ IOSli ------------------*/ typedef struct { @@ -33,13 +38,16 @@ typedef struct { bool _is_alloc; } _z_iosli_t; +static inline _z_iosli_t _z_iosli_null(void) { return (_z_iosli_t){0}; } _z_iosli_t _z_iosli_make(size_t capacity); _z_iosli_t *_z_iosli_new(size_t capacity); _z_iosli_t _z_iosli_wrap(const uint8_t *buf, size_t length, size_t r_pos, size_t w_pos); +_z_iosli_t _z_iosli_steal(_z_iosli_t *ios); size_t _z_iosli_readable(const _z_iosli_t *ios); uint8_t _z_iosli_read(_z_iosli_t *ios); void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dest, size_t offset, size_t length); +void _z_iosli_copy_bytes(_z_iosli_t *dst, const _z_iosli_t *src); uint8_t _z_iosli_get(const _z_iosli_t *ios, size_t pos); size_t _z_iosli_writable(const _z_iosli_t *ios); @@ -56,14 +64,17 @@ void _z_iosli_free(_z_iosli_t **ios); void _z_iosli_copy(_z_iosli_t *dst, const _z_iosli_t *src); _z_iosli_t *_z_iosli_clone(const _z_iosli_t *src); -_Z_ELEM_DEFINE(_z_iosli, _z_iosli_t, _z_iosli_size, _z_iosli_clear, _z_iosli_copy) +_Z_ELEM_DEFINE(_z_iosli, _z_iosli_t, _z_iosli_size, _z_iosli_clear, _z_iosli_copy, _z_noop_move) _Z_VEC_DEFINE(_z_iosli, _z_iosli_t) /*------------------ ZBuf ------------------*/ typedef struct { _z_iosli_t _ios; + _z_slice_simple_rc_t _slice; } _z_zbuf_t; +static inline size_t _z_zbuf_get_ref_count(const _z_zbuf_t *zbf) { return _z_slice_simple_rc_count(&zbf->_slice); } +static inline _z_zbuf_t _z_zbuf_null(void) { return (_z_zbuf_t){0}; } _z_zbuf_t _z_zbuf_make(size_t capacity); _z_zbuf_t _z_zbuf_view(_z_zbuf_t *zbf, size_t length); /// Constructs a _borrowing_ reader on `slice` @@ -72,6 +83,7 @@ _z_zbuf_t _z_slice_as_zbuf(_z_slice_t slice); size_t _z_zbuf_capacity(const _z_zbuf_t *zbf); uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf); size_t _z_zbuf_len(const _z_zbuf_t *zbf); +void _z_zbuf_copy_bytes(_z_zbuf_t *dst, const _z_zbuf_t *src); bool _z_zbuf_can_read(const _z_zbuf_t *zbf); size_t _z_zbuf_space_left(const _z_zbuf_t *zbf); @@ -101,6 +113,7 @@ typedef struct { size_t _expansion_step; } _z_wbuf_t; +static inline _z_wbuf_t _z_wbuf_null(void) { return (_z_wbuf_t){0}; } _z_wbuf_t _z_wbuf_make(size_t capacity, bool is_expandable); size_t _z_wbuf_capacity(const _z_wbuf_t *wbf); @@ -122,6 +135,7 @@ _z_iosli_t *_z_wbuf_get_iosli(const _z_wbuf_t *wbf, size_t idx); size_t _z_wbuf_len_iosli(const _z_wbuf_t *wbf); _z_zbuf_t _z_wbuf_to_zbuf(const _z_wbuf_t *wbf); +_z_zbuf_t _z_wbuf_moved_as_zbuf(_z_wbuf_t *wbf); z_result_t _z_wbuf_siphon(_z_wbuf_t *dst, _z_wbuf_t *src, size_t length); void _z_wbuf_copy(_z_wbuf_t *dst, const _z_wbuf_t *src); @@ -129,4 +143,8 @@ void _z_wbuf_reset(_z_wbuf_t *wbf); void _z_wbuf_clear(_z_wbuf_t *wbf); void _z_wbuf_free(_z_wbuf_t **wbf); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_PROTOCOL_IOBUF_H */ diff --git a/include/zenoh-pico/protocol/keyexpr.h b/include/zenoh-pico/protocol/keyexpr.h index f171ee32f..0c347c251 100644 --- a/include/zenoh-pico/protocol/keyexpr.h +++ b/include/zenoh-pico/protocol/keyexpr.h @@ -19,6 +19,10 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + zp_keyexpr_canon_status_t _z_keyexpr_is_canon(const char *start, size_t len); zp_keyexpr_canon_status_t _z_keyexpr_canonize(char *start, size_t *len); bool _z_keyexpr_suffix_includes(const _z_keyexpr_t *left, const _z_keyexpr_t *right); @@ -26,23 +30,32 @@ bool _z_keyexpr_suffix_intersects(const _z_keyexpr_t *left, const _z_keyexpr_t * bool _z_keyexpr_suffix_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right); /*------------------ clone/Copy/Free helpers ------------------*/ +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_keyexpr_t _z_keyexpr_null(void) { return (_z_keyexpr_t){0}; } +static inline _z_keyexpr_t _z_keyexpr_alias(const _z_keyexpr_t src) { + return (_z_keyexpr_t){ + ._id = src._id, + ._mapping = src._mapping, + ._suffix = _z_string_alias(src._suffix), + }; +} + _z_keyexpr_t _z_keyexpr_from_string(uint16_t rid, _z_string_t *str); _z_keyexpr_t _z_keyexpr_from_substr(uint16_t rid, const char *str, size_t len); z_result_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src); -_z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src); -_z_keyexpr_t _z_keyexpr_alias(_z_keyexpr_t src); +_z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src); /// Returns either keyexpr defined by id + mapping with null suffix if try_declared is true and id is non-zero, /// or keyexpr defined by its suffix only, with 0 id and no mapping. This is to be used only when forwarding /// keyexpr in user api to properly separate declared keyexpr from its suffix. _z_keyexpr_t _z_keyexpr_alias_from_user_defined(_z_keyexpr_t src, bool try_declared); _z_keyexpr_t _z_keyexpr_steal(_Z_MOVE(_z_keyexpr_t) src); -static inline _z_keyexpr_t _z_keyexpr_null(void) { - _z_keyexpr_t keyexpr = {0, {0}, _z_string_null()}; - return keyexpr; -} bool _z_keyexpr_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right); void _z_keyexpr_move(_z_keyexpr_t *dst, _z_keyexpr_t *src); void _z_keyexpr_clear(_z_keyexpr_t *rk); void _z_keyexpr_free(_z_keyexpr_t **rk); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_KEYEXPR_H */ diff --git a/include/zenoh-pico/session/interest.h b/include/zenoh-pico/session/interest.h index 3e1f6d4da..d8792ca77 100644 --- a/include/zenoh-pico/session/interest.h +++ b/include/zenoh-pico/session/interest.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_INTEREST == 1 _z_session_interest_rc_t *_z_get_interest_by_id(_z_session_t *zn, const _z_zint_t id); _z_session_interest_rc_t *_z_register_interest(_z_session_t *zn, _z_session_interest_t *intr); @@ -32,4 +36,8 @@ z_result_t _z_interest_process_declare_final(_z_session_t *zn, uint32_t id); z_result_t _z_interest_process_interest_final(_z_session_t *zn, uint32_t id); z_result_t _z_interest_process_interest(_z_session_t *zn, _z_keyexpr_t key, uint32_t id, uint8_t flags); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_INTEREST_H */ diff --git a/include/zenoh-pico/session/push.h b/include/zenoh-pico/session/push.h index 5c774b704..49da5bf21 100644 --- a/include/zenoh-pico/session/push.h +++ b/include/zenoh-pico/session/push.h @@ -21,6 +21,14 @@ #ifndef ZENOH_PICO_SESSION_PUSH_H #define ZENOH_PICO_SESSION_PUSH_H +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push, z_reliability_t reliability); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_PUSH_H */ diff --git a/include/zenoh-pico/session/query.h b/include/zenoh-pico/session/query.h index 1bf03b74d..f7a671a05 100644 --- a/include/zenoh-pico/session/query.h +++ b/include/zenoh-pico/session/query.h @@ -18,6 +18,12 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + +void _z_pending_query_process_timeout(_z_session_t *zn); + #if Z_FEATURE_QUERY == 1 /*------------------ Query ------------------*/ _z_zint_t _z_get_query_id(_z_session_t *zn); @@ -25,7 +31,7 @@ _z_zint_t _z_get_query_id(_z_session_t *zn); _z_pending_query_t *_z_get_pending_query_by_id(_z_session_t *zn, const _z_zint_t id); z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pq); -z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, _z_zint_t reply_context, const _z_keyexpr_t keyexpr, +z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, _z_zint_t reply_context, _z_keyexpr_t *keyexpr, _z_msg_put_t *msg, z_sample_kind_t kind); z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg); z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id); @@ -33,4 +39,8 @@ void _z_unregister_pending_query(_z_session_t *zn, _z_pending_query_t *pq); void _z_flush_pending_queries(_z_session_t *zn); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_QUERY_H */ diff --git a/include/zenoh-pico/session/queryable.h b/include/zenoh-pico/session/queryable.h index 4498a5bed..684880c17 100644 --- a/include/zenoh-pico/session/queryable.h +++ b/include/zenoh-pico/session/queryable.h @@ -16,20 +16,37 @@ #define ZENOH_PICO_SESSION_QUERYABLE_H #include +#include -#include "zenoh-pico/net/session.h" +// Forward declaration to avoid cyclical include +typedef struct _z_session_t _z_session_t; +typedef struct _z_session_rc_t _z_session_rc_t; + +// Queryable infos +typedef struct { + _z_closure_query_callback_t callback; + void *arg; +} _z_queryable_infos_t; + +_Z_ELEM_DEFINE(_z_queryable_infos, _z_queryable_infos_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) +_Z_SVEC_DEFINE(_z_queryable_infos, _z_queryable_infos_t) + +typedef struct { + _z_keyexpr_t ke_in; + _z_keyexpr_t ke_out; + _z_queryable_infos_svec_t infos; + size_t qle_nb; +} _z_queryable_cache_t; #if Z_FEATURE_QUERYABLE == 1 #define _Z_QUERYABLE_COMPLETE_DEFAULT false #define _Z_QUERYABLE_DISTANCE_DEFAULT 0 /*------------------ Queryable ------------------*/ +void _z_queryable_cache_clear(_z_queryable_cache_t *cache); _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id); -_z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t key); - _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_session_queryable_t *q); -z_result_t _z_trigger_queryables(_z_session_rc_t *zn, _z_msg_query_t *query, const _z_keyexpr_t q_key, uint32_t qid, - const _z_bytes_t attachment); +z_result_t _z_trigger_queryables(_z_session_rc_t *zn, _z_msg_query_t *query, _z_keyexpr_t *q_key, uint32_t qid); void _z_unregister_session_queryable(_z_session_t *zn, _z_session_queryable_rc_t *q); void _z_flush_session_queryable(_z_session_t *zn); #endif diff --git a/include/zenoh-pico/session/reply.h b/include/zenoh-pico/session/reply.h index c10aa0b28..b2aea9e5c 100644 --- a/include/zenoh-pico/session/reply.h +++ b/include/zenoh-pico/session/reply.h @@ -19,13 +19,21 @@ #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/definitions/network.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef ZENOH_PICO_SESSION_REPLY_H #define ZENOH_PICO_SESSION_REPLY_H -z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t key, _z_msg_reply_t *reply); +z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t *key, _z_msg_reply_t *reply); z_result_t _z_trigger_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *error); z_result_t _z_trigger_reply_final(_z_session_t *zn, _z_n_msg_response_final_t *final); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_REPLY_H */ diff --git a/include/zenoh-pico/session/resource.h b/include/zenoh-pico/session/resource.h index 3702a86cd..61af9989b 100644 --- a/include/zenoh-pico/session/resource.h +++ b/include/zenoh-pico/session/resource.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Entity ------------------*/ uint32_t _z_get_entity_id(_z_session_t *zn); @@ -32,8 +36,12 @@ void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping); void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping); void _z_flush_resources(_z_session_t *zn); -_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); +_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr, bool force_alias); _z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t id); _z_resource_t *__unsafe_z_get_resource_matching_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_RESOURCE_H */ diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index 9d1d00038..e1a39584e 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -26,6 +26,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/manager.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * The callback signature of the cleanup functions. */ @@ -45,7 +49,7 @@ void _z_resource_clear(_z_resource_t *res); void _z_resource_copy(_z_resource_t *dst, const _z_resource_t *src); void _z_resource_free(_z_resource_t **res); -_Z_ELEM_DEFINE(_z_resource, _z_resource_t, _z_noop_size, _z_resource_clear, _z_resource_copy) +_Z_ELEM_DEFINE(_z_resource, _z_resource_t, _z_noop_size, _z_resource_clear, _z_resource_copy, _z_noop_move) _Z_LIST_DEFINE(_z_resource, _z_resource_t) // Forward declaration to avoid cyclical include @@ -54,13 +58,13 @@ typedef struct _z_sample_t _z_sample_t; /** * The callback signature of the functions handling data messages. */ -typedef void (*_z_sample_handler_t)(_z_sample_t *sample, void *arg); +typedef void (*_z_closure_sample_callback_t)(_z_sample_t *sample, void *arg); typedef struct { _z_keyexpr_t _key; uint16_t _key_id; uint32_t _id; - _z_sample_handler_t _callback; + _z_closure_sample_callback_t _callback; _z_drop_handler_t _dropper; void *_arg; } _z_subscription_t; @@ -69,9 +73,9 @@ bool _z_subscription_eq(const _z_subscription_t *one, const _z_subscription_t *t void _z_subscription_clear(_z_subscription_t *sub); _Z_REFCOUNT_DEFINE(_z_subscription, _z_subscription) -_Z_ELEM_DEFINE(_z_subscriber, _z_subscription_t, _z_noop_size, _z_subscription_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_subscriber, _z_subscription_t, _z_noop_size, _z_subscription_clear, _z_noop_copy, _z_noop_move) _Z_ELEM_DEFINE(_z_subscription_rc, _z_subscription_rc_t, _z_subscription_rc_size, _z_subscription_rc_drop, - _z_subscription_rc_copy) + _z_subscription_rc_copy, _z_noop_move) _Z_LIST_DEFINE(_z_subscription_rc, _z_subscription_rc_t) typedef struct { @@ -80,17 +84,17 @@ typedef struct { } _z_publication_t; // Forward type declaration to avoid cyclical include -typedef struct _z_query_rc_t _z_query_rc_t; +typedef struct _z_query_t _z_query_t; /** * The callback signature of the functions handling query messages. */ -typedef void (*_z_query_handler_t)(_z_query_rc_t *query, void *arg); +typedef void (*_z_closure_query_callback_t)(_z_query_t *query, void *arg); typedef struct { _z_keyexpr_t _key; uint32_t _id; - _z_query_handler_t _callback; + _z_closure_query_callback_t _callback; _z_drop_handler_t _dropper; void *_arg; bool _complete; @@ -100,9 +104,10 @@ bool _z_session_queryable_eq(const _z_session_queryable_t *one, const _z_session void _z_session_queryable_clear(_z_session_queryable_t *res); _Z_REFCOUNT_DEFINE(_z_session_queryable, _z_session_queryable) -_Z_ELEM_DEFINE(_z_session_queryable, _z_session_queryable_t, _z_noop_size, _z_session_queryable_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_session_queryable, _z_session_queryable_t, _z_noop_size, _z_session_queryable_clear, _z_noop_copy, + _z_noop_move) _Z_ELEM_DEFINE(_z_session_queryable_rc, _z_session_queryable_rc_t, _z_noop_size, _z_session_queryable_rc_drop, - _z_noop_copy) + _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_session_queryable_rc, _z_session_queryable_rc_t) // Forward declaration to avoid cyclical includes @@ -114,13 +119,15 @@ typedef struct _z_reply_t _z_reply_t; /** * The callback signature of the functions handling query replies. */ -typedef void (*_z_reply_handler_t)(_z_reply_t *reply, void *arg); +typedef void (*_z_closure_reply_callback_t)(_z_reply_t *reply, void *arg); typedef struct { _z_keyexpr_t _key; _z_zint_t _id; - _z_reply_handler_t _callback; + _z_closure_reply_callback_t _callback; _z_drop_handler_t _dropper; + z_clock_t _start_time; + uint64_t _timeout; void *_arg; _z_pending_reply_list_t *_pending_replies; z_query_target_t _target; @@ -131,7 +138,7 @@ typedef struct { bool _z_pending_query_eq(const _z_pending_query_t *one, const _z_pending_query_t *two); void _z_pending_query_clear(_z_pending_query_t *res); -_Z_ELEM_DEFINE(_z_pending_query, _z_pending_query_t, _z_noop_size, _z_pending_query_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_pending_query, _z_pending_query_t, _z_noop_size, _z_pending_query_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_pending_query, _z_pending_query_t) typedef struct { @@ -142,11 +149,11 @@ typedef struct { _z_reply_data_list_t *_replies; } _z_pending_query_collect_t; -struct __z_hello_handler_wrapper_t; // Forward declaration to be used in _z_hello_handler_t +struct __z_hello_handler_wrapper_t; // Forward declaration to be used in _z_closure_hello_callback_t /** * The callback signature of the functions handling hello messages. */ -typedef void (*_z_hello_handler_t)(_z_hello_t *hello, struct __z_hello_handler_wrapper_t *arg); +typedef void (*_z_closure_hello_callback_t)(_z_hello_t *hello, struct __z_hello_handler_wrapper_t *arg); z_result_t _z_session_generate_zid(_z_id_t *bs, uint8_t size); @@ -182,9 +189,10 @@ bool _z_session_interest_eq(const _z_session_interest_t *one, const _z_session_i void _z_session_interest_clear(_z_session_interest_t *res); _Z_REFCOUNT_DEFINE(_z_session_interest, _z_session_interest) -_Z_ELEM_DEFINE(_z_session_interest, _z_session_interest_t, _z_noop_size, _z_session_interest_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_session_interest, _z_session_interest_t, _z_noop_size, _z_session_interest_clear, _z_noop_copy, + _z_noop_move) _Z_ELEM_DEFINE(_z_session_interest_rc, _z_session_interest_rc_t, _z_noop_size, _z_session_interest_rc_drop, - _z_noop_copy) + _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_session_interest_rc, _z_session_interest_rc_t) typedef enum { @@ -200,7 +208,11 @@ typedef struct { } _z_declare_data_t; void _z_declare_data_clear(_z_declare_data_t *data); -_Z_ELEM_DEFINE(_z_declare_data, _z_declare_data_t, _z_noop_size, _z_declare_data_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_declare_data, _z_declare_data_t, _z_noop_size, _z_declare_data_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_declare_data, _z_declare_data_t) +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_SESSION_H */ diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index dd48ecb83..a103b0c21 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -16,23 +16,54 @@ #define INCLUDE_ZENOH_PICO_SESSION_SUBSCRIPTION_H #include "zenoh-pico/net/encoding.h" -#include "zenoh-pico/net/session.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/session.h" + +// Forward declaration to avoid cyclical include +typedef struct _z_session_t _z_session_t; + +// Subscription infos +typedef struct { + _z_closure_sample_callback_t callback; + void *arg; +} _z_subscription_infos_t; + +_Z_ELEM_DEFINE(_z_subscription_infos, _z_subscription_infos_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) +_Z_SVEC_DEFINE(_z_subscription_infos, _z_subscription_infos_t) + +typedef struct { + _z_keyexpr_t ke_in; + _z_keyexpr_t ke_out; + _z_subscription_infos_svec_t infos; + size_t sub_nb; +} _z_subscription_cache_t; + +#ifdef __cplusplus +extern "C" { +#endif /*------------------ Subscription ------------------*/ -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t attachment, z_reliability_t reliability); + _z_bytes_t *attachment, z_reliability_t reliability); #if Z_FEATURE_SUBSCRIPTION == 1 -_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); -_z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); +#if Z_FEATURE_RX_CACHE == 1 +void _z_subscription_cache_clear(_z_subscription_cache_t *cache); +#endif + +_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, const _z_bytes_t attachment, z_reliability_t reliability); + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability); void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub); void _z_flush_subscriptions(_z_session_t *zn); #endif +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_SUBSCRIPTION_H */ diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index 75eaac2e8..44c48ff91 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -22,6 +22,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Session ------------------*/ _z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t id, _z_string_t *locator, const uint32_t timeout, const bool exit_on_first); @@ -31,10 +35,17 @@ void _z_session_clear(_z_session_t *zn); z_result_t _z_session_close(_z_session_t *zn, uint8_t reason); z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t *z_msg, uint16_t local_peer_id); -z_result_t _z_send_n_msg(_z_session_t *zn, _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl); -void _zp_session_lock_mutex(_z_session_t *zn); -void _zp_session_unlock_mutex(_z_session_t *zn); +#if Z_FEATURE_MULTI_THREAD == 1 +static inline void _z_session_mutex_lock(_z_session_t *zn) { (void)_z_mutex_lock(&zn->_mutex_inner); } +static inline void _z_session_mutex_unlock(_z_session_t *zn) { (void)_z_mutex_unlock(&zn->_mutex_inner); } +#else +static inline void _z_session_mutex_lock(_z_session_t *zn) { _ZP_UNUSED(zn); } +static inline void _z_session_mutex_unlock(_z_session_t *zn) { _ZP_UNUSED(zn); } +#endif + +#ifdef __cplusplus +} +#endif #endif /* INCLUDE_ZENOH_PICO_SESSION_UTILS_H */ diff --git a/include/zenoh-pico/system/link/raweth.h b/include/zenoh-pico/system/link/raweth.h index d48bf1fa4..b1fa878fe 100644 --- a/include/zenoh-pico/system/link/raweth.h +++ b/include/zenoh-pico/system/link/raweth.h @@ -21,6 +21,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_RAWETH_TRANSPORT == 1 // Ethernet types (big endian) @@ -43,14 +47,15 @@ typedef struct { void _z_raweth_clear_mapping_entry(_zp_raweth_mapping_entry_t *entry); _Z_ELEM_DEFINE(_zp_raweth_mapping, _zp_raweth_mapping_entry_t, _z_noop_size, _z_raweth_clear_mapping_entry, - _z_noop_copy) + _z_noop_copy, _z_noop_move) _Z_ARRAY_DEFINE(_zp_raweth_mapping, _zp_raweth_mapping_entry_t) typedef struct { uint8_t _mac[_ZP_MAC_ADDR_LENGTH]; } _zp_raweth_whitelist_entry_t; -_Z_ELEM_DEFINE(_zp_raweth_whitelist, _zp_raweth_whitelist_entry_t, _z_noop_size, _z_noop_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_zp_raweth_whitelist, _zp_raweth_whitelist_entry_t, _z_noop_size, _z_noop_clear, _z_noop_copy, + _z_noop_move) _Z_ARRAY_DEFINE(_zp_raweth_whitelist, _zp_raweth_whitelist_entry_t) // Ethernet header structure type @@ -92,4 +97,8 @@ uint16_t _z_raweth_htons(uint16_t val); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_RAWETH_H */ diff --git a/include/zenoh-pico/system/link/serial.h b/include/zenoh-pico/system/link/serial.h index 21d832c65..21679d996 100644 --- a/include/zenoh-pico/system/link/serial.h +++ b/include/zenoh-pico/system/link/serial.h @@ -21,6 +21,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_SERIAL == 1 #define _Z_SERIAL_MTU_SIZE 1500 @@ -43,4 +47,8 @@ size_t _z_send_serial(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_BT_H */ diff --git a/include/zenoh-pico/system/link/tcp.h b/include/zenoh-pico/system/link/tcp.h index 22bdc3efc..c6dcd7032 100644 --- a/include/zenoh-pico/system/link/tcp.h +++ b/include/zenoh-pico/system/link/tcp.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_TCP == 1 typedef struct { @@ -38,4 +42,8 @@ size_t _z_read_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len); size_t _z_send_tcp(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_TCP_H */ diff --git a/include/zenoh-pico/system/link/udp.h b/include/zenoh-pico/system/link/udp.h index 47899c04a..a0eb9cb01 100644 --- a/include/zenoh-pico/system/link/udp.h +++ b/include/zenoh-pico/system/link/udp.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_UDP_UNICAST == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 typedef struct { @@ -56,4 +60,8 @@ size_t _z_send_udp_multicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, const _z_sys_net_endpoint_t rep); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_UDP_H */ diff --git a/include/zenoh-pico/system/link/ws.h b/include/zenoh-pico/system/link/ws.h index aa57fcbf8..c3fcadc14 100644 --- a/include/zenoh-pico/system/link/ws.h +++ b/include/zenoh-pico/system/link/ws.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_WS == 1 typedef struct { @@ -38,4 +42,8 @@ size_t _z_read_ws(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len); size_t _z_send_ws(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_WS_H */ diff --git a/include/zenoh-pico/system/platform/arduino/esp32.h b/include/zenoh-pico/system/platform/arduino/esp32.h index af09722a2..9e8df7a07 100644 --- a/include/zenoh-pico/system/platform/arduino/esp32.h +++ b/include/zenoh-pico/system/platform/arduino/esp32.h @@ -21,6 +21,10 @@ #include #endif // Z_FEATURE_MULTI_THREAD == 1 +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef void *_z_task_t; typedef void *z_task_attr_t; // Not used in ESP32 @@ -56,4 +60,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ESP32_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/arduino/opencr.h b/include/zenoh-pico/system/platform/arduino/opencr.h index c9c374d2d..e1fa1da4a 100644 --- a/include/zenoh-pico/system/platform/arduino/opencr.h +++ b/include/zenoh-pico/system/platform/arduino/opencr.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef void *_z_task_t; typedef void *z_task_attr_t; @@ -60,4 +64,8 @@ typedef struct { bool _err; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ARDUINO_OPENCR_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/emscripten.h b/include/zenoh-pico/system/platform/emscripten.h index edb9c6b44..068cca9f2 100644 --- a/include/zenoh-pico/system/platform/emscripten.h +++ b/include/zenoh-pico/system/platform/emscripten.h @@ -19,6 +19,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 #include @@ -50,4 +54,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_WASM_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/espidf.h b/include/zenoh-pico/system/platform/espidf.h index 1f35832a6..aadeb782f 100644 --- a/include/zenoh-pico/system/platform/espidf.h +++ b/include/zenoh-pico/system/platform/espidf.h @@ -22,6 +22,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 #include @@ -69,4 +73,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ESPIDF_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/flipper.h b/include/zenoh-pico/system/platform/flipper.h index 4a51074f6..8eb94b4c7 100644 --- a/include/zenoh-pico/system/platform/flipper.h +++ b/include/zenoh-pico/system/platform/flipper.h @@ -21,6 +21,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #define FLIPPER_DEFAULT_THREAD_STACK_SIZE 2048 #define FLIPPER_SERIAL_STREAM_BUFFER_SIZE 512 #define FLIPPER_SERIAL_STREAM_TRIGGERED_LEVEL 10 @@ -43,4 +47,8 @@ typedef struct { #endif } _z_sys_net_socket_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_FLIPPER_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/freertos_plus_tcp.h b/include/zenoh-pico/system/platform/freertos_plus_tcp.h index 7332889c5..31a2dfc83 100644 --- a/include/zenoh-pico/system/platform/freertos_plus_tcp.h +++ b/include/zenoh-pico/system/platform/freertos_plus_tcp.h @@ -18,6 +18,10 @@ #include "FreeRTOS_IP.h" #include "semphr.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef struct { const char *name; @@ -58,4 +62,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; -#endif \ No newline at end of file +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/zenoh-pico/system/platform/mbed.h b/include/zenoh-pico/system/platform/mbed.h index 08bb09c83..87fdb4626 100644 --- a/include/zenoh-pico/system/platform/mbed.h +++ b/include/zenoh-pico/system/platform/mbed.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef int _z_socket_t; #if Z_FEATURE_MULTI_THREAD == 1 @@ -61,4 +65,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_MBED_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/unix.h b/include/zenoh-pico/system/platform/unix.h index cea7b5868..b83dbb424 100644 --- a/include/zenoh-pico/system/platform/unix.h +++ b/include/zenoh-pico/system/platform/unix.h @@ -19,12 +19,17 @@ #include #include #include +#if Z_FEATURE_MULTI_THREAD == 1 +#include +#endif // Z_FEATURE_MULTI_THREAD == 1 #include "zenoh-pico/config.h" -#if Z_FEATURE_MULTI_THREAD == 1 -#include +#ifdef __cplusplus +extern "C" { +#endif +#if Z_FEATURE_MULTI_THREAD == 1 typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; typedef pthread_mutex_t _z_mutex_t; @@ -51,4 +56,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_UNIX_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/void.h b/include/zenoh-pico/system/platform/void.h index cda1b50ab..f46217281 100644 --- a/include/zenoh-pico/system/platform/void.h +++ b/include/zenoh-pico/system/platform/void.h @@ -17,6 +17,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef void *_z_task_t; typedef void *z_task_attr_t; @@ -27,4 +31,8 @@ typedef void *_z_condvar_t; typedef void *z_clock_t; typedef void *z_time_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_VOID_H */ diff --git a/include/zenoh-pico/system/platform/windows.h b/include/zenoh-pico/system/platform/windows.h index cb41f243d..7ccd38509 100644 --- a/include/zenoh-pico/system/platform/windows.h +++ b/include/zenoh-pico/system/platform/windows.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef HANDLE *_z_task_t; typedef void *z_task_attr_t; // Not used in Windows @@ -48,4 +52,8 @@ typedef struct { inline void __asm__(char *instruction) { (void)(instruction); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_VOID_H */ diff --git a/include/zenoh-pico/system/platform/zephyr.h b/include/zenoh-pico/system/platform/zephyr.h index 966edaa52..1f25e839c 100644 --- a/include/zenoh-pico/system/platform/zephyr.h +++ b/include/zenoh-pico/system/platform/zephyr.h @@ -30,6 +30,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; @@ -59,4 +63,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ZEPHYR_TYPES_H */ diff --git a/include/zenoh-pico/transport/common/lease.h b/include/zenoh-pico/transport/common/lease.h index 900a2f887..858282636 100644 --- a/include/zenoh-pico/transport/common/lease.h +++ b/include/zenoh-pico/transport/common/lease.h @@ -17,7 +17,15 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_send_join(_z_transport_t *zt); z_result_t _z_send_keep_alive(_z_transport_t *zt); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_LEASE_H */ diff --git a/include/zenoh-pico/transport/common/read.h b/include/zenoh-pico/transport/common/read.h index f298d1878..fe6b79b6a 100644 --- a/include/zenoh-pico/transport/common/read.h +++ b/include/zenoh-pico/transport/common/read.h @@ -17,7 +17,15 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_read(_z_transport_t *zt); void *_zp_read_task(void *zt_arg); // The argument is void* to avoid incompatible pointer types in tasks +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_READ_H */ diff --git a/include/zenoh-pico/transport/common/rx.h b/include/zenoh-pico/transport/common/rx.h index 147273816..e4f548c6e 100644 --- a/include/zenoh-pico/transport/common/rx.h +++ b/include/zenoh-pico/transport/common/rx.h @@ -18,8 +18,16 @@ #include "zenoh-pico/link/link.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Transmission and Reception helpers ------------------*/ size_t _z_read_stream_size(_z_zbuf_t *zbuf); z_result_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_RX_H */ diff --git a/include/zenoh-pico/transport/common/tx.h b/include/zenoh-pico/transport/common/tx.h index 1eb4abac1..6809f20f3 100644 --- a/include/zenoh-pico/transport/common/tx.h +++ b/include/zenoh-pico/transport/common/tx.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + void __unsafe_z_prepare_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability); void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability); /*This function is unsafe because it operates in potentially concurrent @@ -26,7 +30,15 @@ void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability); z_result_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn); /*------------------ Transmission and Reception helpers ------------------*/ +z_result_t _z_transport_tx_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg); z_result_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg); z_result_t _z_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_msg); +z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, + z_congestion_control_t cong_ctrl); +z_result_t _z_send_n_batch(_z_session_t *zn, z_congestion_control_t cong_ctrl); + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_TRANSPORT_TX_H */ diff --git a/include/zenoh-pico/transport/manager.h b/include/zenoh-pico/transport/manager.h index 8ac95dd7c..b22eff975 100644 --- a/include/zenoh-pico/transport/manager.h +++ b/include/zenoh-pico/transport/manager.h @@ -19,7 +19,20 @@ #include "zenoh-pico/link/manager.h" #include "zenoh-pico/transport/transport.h" -z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode); +#ifdef __cplusplus +extern "C" { +#endif + +enum _z_peer_op_e { + _Z_PEER_OP_OPEN = 0, + _Z_PEER_OP_LISTEN = 1, +}; + +z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode, int peer_op); void _z_free_transport(_z_transport_t **zt); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H */ diff --git a/include/zenoh-pico/transport/multicast.h b/include/zenoh-pico/transport/multicast.h index 487ef6dae..bdf939514 100644 --- a/include/zenoh-pico/transport/multicast.h +++ b/include/zenoh-pico/transport/multicast.h @@ -17,7 +17,15 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + void _zp_multicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback); void _zp_multicast_info_session(const _z_transport_t *zt, _z_config_t *ps); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_MULTICAST_H */ diff --git a/include/zenoh-pico/transport/multicast/lease.h b/include/zenoh-pico/transport/multicast/lease.h index 09a0b4135..71472bb55 100644 --- a/include/zenoh-pico/transport/multicast/lease.h +++ b/include/zenoh-pico/transport/multicast/lease.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_multicast_send_join(_z_transport_multicast_t *ztm); z_result_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm); z_result_t _zp_multicast_stop_lease_task(_z_transport_multicast_t *ztm); @@ -28,4 +32,8 @@ z_result_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_ z_result_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_MULTICAST_LEASE_H */ diff --git a/include/zenoh-pico/transport/multicast/read.h b/include/zenoh-pico/transport/multicast/read.h index acaa82308..63c9a0eda 100644 --- a/include/zenoh-pico/transport/multicast/read.h +++ b/include/zenoh-pico/transport/multicast/read.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_multicast_read(_z_transport_multicast_t *ztm); z_result_t _zp_multicast_stop_read_task(_z_transport_t *zt); void *_zp_multicast_read_task(void *ztm_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr z_result_t _zp_multicast_start_read_task(_z_transport_t *zt, void *attr, void *task); #endif /* #if Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_MULTICAST_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_MULTICAST_READ_H */ diff --git a/include/zenoh-pico/transport/multicast/rx.h b/include/zenoh-pico/transport/multicast/rx.h index 31a10e64a..f7a81e00a 100644 --- a/include/zenoh-pico/transport/multicast/rx.h +++ b/include/zenoh-pico/transport/multicast/rx.h @@ -17,8 +17,17 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); +z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm); + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_TRANSPORT_LINK_RX_H */ diff --git a/include/zenoh-pico/transport/multicast/transport.h b/include/zenoh-pico/transport/multicast/transport.h index fa9cd085c..3e61f4bc1 100644 --- a/include/zenoh-pico/transport/multicast/transport.h +++ b/include/zenoh-pico/transport/multicast/transport.h @@ -17,6 +17,10 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transport_multicast_establish_param_t *param); z_result_t _z_multicast_open_peer(_z_transport_multicast_establish_param_t *param, const _z_link_t *zl, @@ -26,4 +30,16 @@ z_result_t _z_multicast_open_client(_z_transport_multicast_establish_param_t *pa z_result_t _z_multicast_send_close(_z_transport_multicast_t *ztm, uint8_t reason, bool link_only); z_result_t _z_multicast_transport_close(_z_transport_multicast_t *ztm, uint8_t reason); void _z_multicast_transport_clear(_z_transport_t *zt); + +#if (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 +static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _z_mutex_lock(&ztm->_mutex_peer); } +static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_peer); } +#else +static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } +static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } +#endif // (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_MULTICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/multicast/tx.h b/include/zenoh-pico/transport/multicast/tx.h deleted file mode 100644 index c9721523a..000000000 --- a/include/zenoh-pico/transport/multicast/tx.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#ifndef ZENOH_PICO_MULTICAST_TX_H -#define ZENOH_PICO_MULTICAST_TX_H - -#include "zenoh-pico/net/session.h" -#include "zenoh-pico/transport/transport.h" - -z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl); -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg); - -#endif /* ZENOH_PICO_MULTICAST_TX_H */ diff --git a/include/zenoh-pico/transport/raweth/read.h b/include/zenoh-pico/transport/raweth/read.h index 6ead7be9b..f5cc3a6ee 100644 --- a/include/zenoh-pico/transport/raweth/read.h +++ b/include/zenoh-pico/transport/raweth/read.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_raweth_read(_z_transport_multicast_t *ztm); z_result_t _zp_raweth_stop_read_task(_z_transport_t *zt); void *_zp_raweth_read_task(void *ztm_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _ z_result_t _zp_raweth_start_read_task(_z_transport_t *zt, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_RAWETH_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_RAWETH_READ_H */ diff --git a/include/zenoh-pico/transport/raweth/rx.h b/include/zenoh-pico/transport/raweth/rx.h index 81874d633..19901b68f 100644 --- a/include/zenoh-pico/transport/raweth/rx.h +++ b/include/zenoh-pico/transport/raweth/rx.h @@ -17,7 +17,16 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); +z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm); + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_RAWETH_RX_H */ diff --git a/include/zenoh-pico/transport/raweth/tx.h b/include/zenoh-pico/transport/raweth/tx.h index 83abdd9fb..a338c16f3 100644 --- a/include/zenoh-pico/transport/raweth/tx.h +++ b/include/zenoh-pico/transport/raweth/tx.h @@ -18,9 +18,17 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_msg); z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); -z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg); +z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg); + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_RAWETH_TX_H */ diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index 4e013594e..d4fcf7ea7 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -25,24 +25,39 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/transport.h" -typedef struct { -#if Z_FEATURE_FRAGMENTATION == 1 - // Defragmentation buffers - _z_wbuf_t _dbuf_reliable; - _z_wbuf_t _dbuf_best_effort; +#ifdef __cplusplus +extern "C" { #endif +enum _z_dbuf_state_e { + _Z_DBUF_STATE_NULL = 0, + _Z_DBUF_STATE_INIT = 1, + _Z_DBUF_STATE_OVERFLOW = 2, +}; + +enum _z_batching_state_e { + _Z_BATCHING_IDLE = 0, + _Z_BATCHING_ACTIVE = 1, +}; + +typedef struct { _z_id_t _remote_zid; _z_slice_t _remote_addr; _z_conduit_sn_list_t _sn_rx_sns; - // SN numbers _z_zint_t _sn_res; volatile _z_zint_t _lease; volatile _z_zint_t _next_lease; - uint16_t _peer_id; volatile bool _received; + +#if Z_FEATURE_FRAGMENTATION == 1 + // Defragmentation buffers + uint8_t _state_reliable; + uint8_t _state_best_effort; + _z_wbuf_t _dbuf_reliable; + _z_wbuf_t _dbuf_best_effort; +#endif } _z_transport_peer_entry_t; size_t _z_transport_peer_entry_size(const _z_transport_peer_entry_t *src); @@ -50,7 +65,7 @@ void _z_transport_peer_entry_clear(_z_transport_peer_entry_t *src); void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_transport_peer_entry_t *src); bool _z_transport_peer_entry_eq(const _z_transport_peer_entry_t *left, const _z_transport_peer_entry_t *right); _Z_ELEM_DEFINE(_z_transport_peer_entry, _z_transport_peer_entry_t, _z_transport_peer_entry_size, - _z_transport_peer_entry_clear, _z_transport_peer_entry_copy) + _z_transport_peer_entry_clear, _z_transport_peer_entry_copy, _z_noop_move) _Z_LIST_DEFINE(_z_transport_peer_entry, _z_transport_peer_entry_t) _z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport_peer_entry_list_t *root, _z_transport_peer_entry_t *entry); @@ -58,93 +73,68 @@ _z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport // Forward type declaration to avoid cyclical include typedef struct _z_session_rc_t _z_session_rc_ref_t; -// Forward declaration to be used in _zp_f_send_tmsg* -typedef struct _z_transport_multicast_t _z_transport_multicast_t; -// Send function prototype -typedef z_result_t (*_zp_f_send_tmsg)(_z_transport_multicast_t *self, const _z_transport_message_t *t_msg); +#define _Z_RES_POOL_INIT_SIZE 8 // Arbitrary small value typedef struct { - // Session associated to the transport _z_session_rc_ref_t *_session; - -#if Z_FEATURE_MULTI_THREAD == 1 - // TX and RX mutexes - _z_mutex_t _mutex_rx; - _z_mutex_t _mutex_tx; -#endif // Z_FEATURE_MULTI_THREAD == 1 - _z_link_t _link; - -#if Z_FEATURE_FRAGMENTATION == 1 - // Defragmentation buffer - _z_wbuf_t _dbuf_reliable; - _z_wbuf_t _dbuf_best_effort; -#endif - - // Regular Buffers + // TX and RX buffers _z_wbuf_t _wbuf; _z_zbuf_t _zbuf; - - _z_id_t _remote_zid; - // SN numbers _z_zint_t _sn_res; _z_zint_t _sn_tx_reliable; _z_zint_t _sn_tx_best_effort; - _z_zint_t _sn_rx_reliable; - _z_zint_t _sn_rx_best_effort; + _z_arc_slice_svec_t _arc_pool; + _z_network_message_svec_t _msg_pool; volatile _z_zint_t _lease; - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_task_t *_read_task; - _z_task_t *_lease_task; - volatile bool _read_task_running; - volatile bool _lease_task_running; -#endif // Z_FEATURE_MULTI_THREAD == 1 - - volatile bool _received; volatile bool _transmitted; -} _z_transport_unicast_t; - -typedef struct _z_transport_multicast_t { - // Session associated to the transport - _z_session_rc_ref_t *_session; - #if Z_FEATURE_MULTI_THREAD == 1 // TX and RX mutexes _z_mutex_t _mutex_rx; _z_mutex_t _mutex_tx; - // Peer list mutex - _z_mutex_t _mutex_peer; -#endif // Z_FEATURE_MULTI_THREAD == 1 + _z_task_t *_read_task; + _z_task_t *_lease_task; + volatile bool _read_task_running; + volatile bool _lease_task_running; +#endif +// Transport batching +#if Z_FEATURE_BATCHING == 1 + uint8_t _batch_state; + size_t _batch_count; +#endif +} _z_transport_common_t; - _z_link_t _link; +// Send function prototype +typedef z_result_t (*_zp_f_send_tmsg)(_z_transport_common_t *self, const _z_transport_message_t *t_msg); - // TX and RX buffers - _z_wbuf_t _wbuf; - _z_zbuf_t _zbuf; +typedef struct { + _z_transport_common_t _common; + _z_id_t _remote_zid; + _z_zint_t _sn_rx_reliable; + _z_zint_t _sn_rx_best_effort; + volatile bool _received; - // SN initial numbers - _z_zint_t _sn_res; - _z_zint_t _sn_tx_reliable; - _z_zint_t _sn_tx_best_effort; - volatile _z_zint_t _lease; +#if Z_FEATURE_FRAGMENTATION == 1 + // Defragmentation buffer + uint8_t _state_reliable; + uint8_t _state_best_effort; + _z_wbuf_t _dbuf_reliable; + _z_wbuf_t _dbuf_best_effort; +#endif +} _z_transport_unicast_t; +typedef struct _z_transport_multicast_t { + _z_transport_common_t _common; // Known valid peers _z_transport_peer_entry_list_t *_peers; - // T message send function _zp_f_send_tmsg _send_f; #if Z_FEATURE_MULTI_THREAD == 1 - _z_task_t *_read_task; - _z_task_t *_lease_task; - volatile bool _read_task_running; - volatile bool _lease_task_running; -#endif // Z_FEATURE_MULTI_THREAD == 1 - - volatile bool _transmitted; + _z_mutex_t _mutex_peer; // Peer list mutex +#endif } _z_transport_multicast_t; typedef struct { @@ -157,7 +147,7 @@ typedef struct { enum { _Z_TRANSPORT_UNICAST_TYPE, _Z_TRANSPORT_MULTICAST_TYPE, _Z_TRANSPORT_RAWETH_TYPE, _Z_TRANSPORT_NONE } _type; } _z_transport_t; -_Z_ELEM_DEFINE(_z_transport, _z_transport_t, _z_noop_size, _z_noop_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_transport, _z_transport_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_transport, _z_transport_t) typedef struct { @@ -182,4 +172,35 @@ z_result_t _z_transport_close(_z_transport_t *zt, uint8_t reason); void _z_transport_clear(_z_transport_t *zt); void _z_transport_free(_z_transport_t **zt); +#if Z_FEATURE_BATCHING == 1 +bool _z_transport_start_batching(_z_transport_t *zt); +void _z_transport_stop_batching(_z_transport_t *zt); +#endif + +#if Z_FEATURE_MULTI_THREAD == 1 +static inline z_result_t _z_transport_tx_mutex_lock(_z_transport_common_t *ztc, bool block) { + if (block) { + _z_mutex_lock(&ztc->_mutex_tx); + return _Z_RES_OK; + } else { + return _z_mutex_try_lock(&ztc->_mutex_tx); + } +} +static inline void _z_transport_tx_mutex_unlock(_z_transport_common_t *ztc) { _z_mutex_unlock(&ztc->_mutex_tx); } +static inline void _z_transport_rx_mutex_lock(_z_transport_common_t *ztc) { _z_mutex_lock(&ztc->_mutex_rx); } +static inline void _z_transport_rx_mutex_unlock(_z_transport_common_t *ztc) { _z_mutex_unlock(&ztc->_mutex_rx); } +#else +static inline z_result_t _z_transport_tx_mutex_lock(_z_transport_common_t *ztc, bool block) { + _ZP_UNUSED(ztc); + _ZP_UNUSED(block); + return _Z_RES_OK; +} +static inline void _z_transport_tx_mutex_unlock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } +static inline void _z_transport_rx_mutex_lock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } +static inline void _z_transport_rx_mutex_unlock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } +#endif // Z_FEATURE_MULTI_THREAD == 1 + +#ifdef __cplusplus +} +#endif #endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast.h b/include/zenoh-pico/transport/unicast.h index 652384e47..4c0d525bd 100644 --- a/include/zenoh-pico/transport/unicast.h +++ b/include/zenoh-pico/transport/unicast.h @@ -17,7 +17,15 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback); void _zp_unicast_info_session(const _z_transport_t *zt, _z_config_t *ps); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_H */ diff --git a/include/zenoh-pico/transport/unicast/lease.h b/include/zenoh-pico/transport/unicast/lease.h index 469fd1333..0d607afd6 100644 --- a/include/zenoh-pico/transport/unicast/lease.h +++ b/include/zenoh-pico/transport/unicast/lease.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_unicast_send_keep_alive(_z_transport_unicast_t *ztu); z_result_t _zp_unicast_stop_lease_task(_z_transport_t *zt); void *_zp_unicast_lease_task(void *ztu_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, z_result_t _zp_unicast_start_lease_task(_z_transport_t *zt, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_UNICAST_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_LINK_TASK_LEASE_H */ diff --git a/include/zenoh-pico/transport/unicast/read.h b/include/zenoh-pico/transport/unicast/read.h index 63a8976bb..e703a1ee1 100644 --- a/include/zenoh-pico/transport/unicast/read.h +++ b/include/zenoh-pico/transport/unicast/read.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_unicast_read(_z_transport_unicast_t *ztu); z_result_t _zp_unicast_stop_read_task(_z_transport_t *zt); void *_zp_unicast_read_task(void *ztu_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_result_t _zp_unicast_start_read_task(_z_transport_t *zt, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_UNICAST_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_READ_H */ diff --git a/include/zenoh-pico/transport/unicast/rx.h b/include/zenoh-pico/transport/unicast/rx.h index f36cb592c..8052ebd88 100644 --- a/include/zenoh-pico/transport/unicast/rx.h +++ b/include/zenoh-pico/transport/unicast/rx.h @@ -17,8 +17,17 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_unicast_recv_t_msg(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); +z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu); + +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_UNICAST_RX_H */ diff --git a/include/zenoh-pico/transport/unicast/transport.h b/include/zenoh-pico/transport/unicast/transport.h index 4b60b7c70..3ca322c42 100644 --- a/include/zenoh-pico/transport/unicast/transport.h +++ b/include/zenoh-pico/transport/unicast/transport.h @@ -17,13 +17,22 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transport_unicast_establish_param_t *param); z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, const _z_id_t *local_zid); z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid); + const _z_id_t *local_zid, int peer_op); z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bool link_only); z_result_t _z_unicast_transport_close(_z_transport_unicast_t *ztu, uint8_t reason); void _z_unicast_transport_clear(_z_transport_t *zt); + +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast/tx.h b/include/zenoh-pico/transport/unicast/tx.h deleted file mode 100644 index 56a33bfdd..000000000 --- a/include/zenoh-pico/transport/unicast/tx.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#ifndef ZENOH_PICO_UNICAST_TX_H -#define ZENOH_PICO_UNICAST_TX_H - -#include "zenoh-pico/net/session.h" -#include "zenoh-pico/transport/transport.h" - -z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl); -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg); - -#endif /* ZENOH_PICO_TRANSPORT_LINK_TX_H */ diff --git a/include/zenoh-pico/transport/utils.h b/include/zenoh-pico/transport/utils.h index aff81dc03..62fa319b4 100644 --- a/include/zenoh-pico/transport/utils.h +++ b/include/zenoh-pico/transport/utils.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ SN helpers ------------------*/ _z_zint_t _z_sn_max(uint8_t bits); _z_zint_t _z_sn_half(_z_zint_t sn); @@ -31,4 +35,8 @@ _z_zint_t _z_sn_decrement(const _z_zint_t sn_resolution, const _z_zint_t sn); void _z_conduit_sn_list_copy(_z_conduit_sn_list_t *dst, const _z_conduit_sn_list_t *src); void _z_conduit_sn_list_decrement(const _z_zint_t sn_resolution, _z_conduit_sn_list_t *sns); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_UTILS_H */ diff --git a/include/zenoh-pico/utils/checksum.h b/include/zenoh-pico/utils/checksum.h index b649ad02b..aad153f9c 100644 --- a/include/zenoh-pico/utils/checksum.h +++ b/include/zenoh-pico/utils/checksum.h @@ -18,6 +18,14 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + uint32_t _z_crc32(const uint8_t *message, size_t len); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_CHECKSUM_H */ diff --git a/include/zenoh-pico/utils/config.h b/include/zenoh-pico/utils/config.h index de17a1239..cf67d4189 100644 --- a/include/zenoh-pico/utils/config.h +++ b/include/zenoh-pico/utils/config.h @@ -21,6 +21,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + // Properties returned by _z_info() #define Z_INFO_PID_KEY 0x00 #define Z_INFO_PEER_PID_KEY 0x01 @@ -46,6 +50,7 @@ z_result_t _z_config_init(_z_config_t *ps); * value: The value of the property to add. */ z_result_t _zp_config_insert(_z_config_t *ps, uint8_t key, const char *value); +z_result_t _zp_config_insert_string(_z_config_t *ps, uint8_t key, const _z_string_t *value); /** * Get the property with the given key from a properties map. @@ -109,4 +114,8 @@ char *_z_config_get(const _z_config_t *ps, uint8_t key); */ #define _z_config_free _z_str_intmap_free +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_PROPERTY_H */ diff --git a/include/zenoh-pico/utils/encoding.h b/include/zenoh-pico/utils/encoding.h index 266eb4db1..3ff2c6988 100644 --- a/include/zenoh-pico/utils/encoding.h +++ b/include/zenoh-pico/utils/encoding.h @@ -18,7 +18,15 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + size_t _z_cobs_encode(const uint8_t *input, size_t input_len, uint8_t *output); size_t _z_cobs_decode(const uint8_t *input, size_t input_len, uint8_t *output); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_ENCODING_H */ diff --git a/include/zenoh-pico/utils/logging.h b/include/zenoh-pico/utils/logging.h index 2c9f3ab0d..b50110bdf 100644 --- a/include/zenoh-pico/utils/logging.h +++ b/include/zenoh-pico/utils/logging.h @@ -19,6 +19,10 @@ #include "zenoh-pico/system/platform_common.h" +#ifdef __cplusplus +extern "C" { +#endif + // Logging values #define _Z_LOG_LVL_ERROR 1 #define _Z_LOG_LVL_INFO 2 @@ -72,4 +76,8 @@ static inline void __z_print_timestamp(void) { } while (false) #endif // ZENOH_DEBUG == 0 && !defined(Z_BUILD_DEBUG) +#ifdef __cplusplus +} +#endif + #endif // ZENOH_PICO_UTILS_LOGGING_H diff --git a/include/zenoh-pico/utils/pointers.h b/include/zenoh-pico/utils/pointers.h index 7ce798c64..a5f5156df 100644 --- a/include/zenoh-pico/utils/pointers.h +++ b/include/zenoh-pico/utils/pointers.h @@ -18,6 +18,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * Computes the distance between two ``uint8_t`` pointers as an absolute value. * Note that ``l_ptr`` must be higher than ``r_ptr``. @@ -92,4 +96,8 @@ const char *_z_cptr_char_offset(const char *ptr, ptrdiff_t off); */ char *_z_ptr_char_offset(char *ptr, ptrdiff_t off); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_POINTERS_H */ diff --git a/include/zenoh-pico/utils/result.h b/include/zenoh-pico/utils/result.h index 4dd16f141..6b1061d21 100644 --- a/include/zenoh-pico/utils/result.h +++ b/include/zenoh-pico/utils/result.h @@ -17,6 +17,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define _ZP_UNUSED(x) (void)(x) #define _ZP_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) @@ -106,4 +110,8 @@ typedef enum { #define _Z_IS_OK(expr) (expr == _Z_RES_OK) #define _Z_IS_ERR(expr) (expr != _Z_RES_OK) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_RESULT_H */ diff --git a/include/zenoh-pico/utils/string.h b/include/zenoh-pico/utils/string.h index ca9b5a6b6..e4ffd69d2 100644 --- a/include/zenoh-pico/utils/string.h +++ b/include/zenoh-pico/utils/string.h @@ -12,10 +12,17 @@ // ZettaScale Zenoh Team, // +#ifndef ZENOH_PICO_UTILS_STRING_H +#define ZENOH_PICO_UTILS_STRING_H + #include #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { char const *start; char const *end; @@ -55,3 +62,9 @@ _z_str_se_t _z_splitstr_nextback(_z_splitstr_t *str); size_t _z_strcnt(char const *haystack_start, const char *harstack_end, const char *needle_start); size_t _z_str_startswith(const char *s, const char *needle); + +#ifdef __cplusplus +} +#endif + +#endif /* ZENOH_PICO_UTILS_STRING_H */ diff --git a/include/zenoh-pico/utils/uuid.h b/include/zenoh-pico/utils/uuid.h index 4bd581a91..13631460b 100644 --- a/include/zenoh-pico/utils/uuid.h +++ b/include/zenoh-pico/utils/uuid.h @@ -14,6 +14,16 @@ #include +#include "zenoh-pico/collections/string.h" +#include "zenoh-pico/protocol/core.h" + +#ifndef ZENOH_PICO_UTILS_UUID_H +#define ZENOH_PICO_UTILS_UUID_H + +#ifdef __cplusplus +extern "C" { +#endif + /** * Converts an UUID in string format to a byte array. * @@ -22,3 +32,20 @@ * uuid_str: A valid UUID string. */ void _z_uuid_to_bytes(uint8_t *bytes, const char *uuid_str); + +/** + * Converts an Zenoh ID to string. + * + * Parameters: + * id: Zenoh ID. + * + * Returns: + * ID string representation + */ +_z_string_t _z_id_to_string(const _z_id_t *id); + +#ifdef __cplusplus +} +#endif + +#endif /* ZENOH_PICO_UTILS_UUID_H */ diff --git a/src/api/api.c b/src/api/api.c index d5404d691..37b2e0037 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -39,6 +39,7 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/system/platform.h" #include "zenoh-pico/system/platform_common.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/multicast.h" #include "zenoh-pico/transport/unicast.h" #include "zenoh-pico/utils/endianness.h" @@ -64,8 +65,8 @@ _z_string_svec_t _z_string_array_null(void) { return _z_string_svec_make(0); } void z_string_array_new(z_owned_string_array_t *a) { a->_val = _z_string_array_null(); } size_t z_string_array_push_by_alias(z_loaned_string_array_t *a, const z_loaned_string_t *value) { - _z_string_t str = _z_string_alias(value); - _z_string_svec_append(a, &str); + _z_string_t str = _z_string_alias(*value); + _z_string_svec_append(a, &str, true); return _z_string_svec_len(a); } @@ -73,7 +74,7 @@ size_t z_string_array_push_by_alias(z_loaned_string_array_t *a, const z_loaned_s size_t z_string_array_push_by_copy(z_loaned_string_array_t *a, const z_loaned_string_t *value) { _z_string_t str; _z_string_copy(&str, value); - _z_string_svec_append(a, &str); + _z_string_svec_append(a, &str, true); return _z_string_svec_len(a); } @@ -130,7 +131,7 @@ void z_view_keyexpr_from_substr_unchecked(z_view_keyexpr_t *keyexpr, const char } z_result_t z_keyexpr_as_view_string(const z_loaned_keyexpr_t *keyexpr, z_view_string_t *s) { - s->_val = _z_string_alias(&keyexpr->_suffix); + s->_val = _z_string_alias(keyexpr->_suffix); return _Z_RES_OK; } @@ -243,12 +244,12 @@ const uint8_t *z_slice_data(const z_loaned_slice_t *slice) { return slice->start size_t z_slice_len(const z_loaned_slice_t *slice) { return slice->len; } -void z_slice_empty(z_owned_slice_t *slice) { slice->_val = _z_slice_empty(); } +void z_slice_empty(z_owned_slice_t *slice) { slice->_val = _z_slice_null(); } bool z_slice_is_empty(const z_loaned_slice_t *slice) { return _z_slice_is_empty(slice); } z_result_t z_bytes_to_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst) { - dst->_val = _z_slice_empty(); + dst->_val = _z_slice_null(); return _z_bytes_to_slice(bytes, &dst->_val); } @@ -385,6 +386,7 @@ z_result_t z_timestamp_new(z_timestamp_t *ts, const z_loaned_session_t *zs) { *ts = _z_timestamp_null(); _z_time_since_epoch t; _Z_RETURN_IF_ERR(_z_get_time_since_epoch(&t)); + ts->valid = true; ts->time = _z_timestamp_ntp64_from_time(t.secs, t.nanos); ts->id = _Z_RC_IN_VAL(zs)->_local_zid; return _Z_RES_OK; @@ -415,17 +417,16 @@ z_query_consolidation_t z_query_consolidation_none(void) { z_query_consolidation_t z_query_consolidation_default(void) { return z_query_consolidation_auto(); } void z_query_parameters(const z_loaned_query_t *query, z_view_string_t *parameters) { - parameters->_val = _z_string_alias_str(_Z_RC_IN_VAL(query)->_parameters); + parameters->_val = _z_string_alias(query->_parameters); } -const z_loaned_bytes_t *z_query_attachment(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->attachment; } +const z_loaned_bytes_t *z_query_attachment(const z_loaned_query_t *query) { return &query->_attachment; } -const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->_key; } +const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query) { return &query->_key; } -const z_loaned_bytes_t *z_query_payload(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->_value.payload; } -const z_loaned_encoding_t *z_query_encoding(const z_loaned_query_t *query) { - return &_Z_RC_IN_VAL(query)->_value.encoding; -} +const z_loaned_bytes_t *z_query_payload(const z_loaned_query_t *query) { return &query->_value.payload; } + +const z_loaned_encoding_t *z_query_encoding(const z_loaned_query_t *query) { return &query->_value.encoding; } void z_closure_sample_call(const z_loaned_closure_sample_t *closure, z_loaned_sample_t *sample) { if (closure->call != NULL) { @@ -468,16 +469,13 @@ _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_config_t, config, _z_config_check, _z_config_nu _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_string_t, string, _z_string_check, _z_string_null, _z_string_copy, _z_string_clear) -bool _z_value_check(const _z_value_t *value) { - return _z_encoding_check(&value->encoding) || _z_bytes_check(&value->payload); -} _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_value_t, reply_err, _z_value_check, _z_value_null, _z_value_copy, _z_value_clear) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_keyexpr_t, keyexpr, _z_keyexpr_check, _z_keyexpr_null, _z_keyexpr_copy, _z_keyexpr_clear) _Z_VIEW_FUNCTIONS_IMPL(_z_keyexpr_t, keyexpr, _z_keyexpr_check, _z_keyexpr_null) _Z_VIEW_FUNCTIONS_IMPL(_z_string_t, string, _z_string_check, _z_string_null) -_Z_VIEW_FUNCTIONS_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_empty) +_Z_VIEW_FUNCTIONS_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_null) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_hello_t, hello, _z_hello_check, _z_hello_null, _z_hello_copy, _z_hello_clear) @@ -515,12 +513,11 @@ z_result_t z_whatami_to_view_string(z_whatami_t whatami, z_view_string_t *str_ou bool _z_string_array_check(const _z_string_svec_t *val) { return !_z_string_svec_is_empty(val); } z_result_t _z_string_array_copy(_z_string_svec_t *dst, const _z_string_svec_t *src) { - _z_string_svec_copy(dst, src); - return dst->_len == src->_len ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_string_svec_copy(dst, src, true); } _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_string_svec_t, string_array, _z_string_array_check, _z_string_array_null, _z_string_array_copy, _z_string_svec_clear) -_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_empty, _z_slice_copy, _z_slice_clear) +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_null, _z_slice_copy, _z_slice_clear) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_bytes_t, bytes, _z_bytes_check, _z_bytes_null, _z_bytes_copy, _z_bytes_drop) _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_bytes_writer_t, bytes_writer, _z_bytes_writer_check, _z_bytes_writer_empty, _z_bytes_writer_clear) @@ -549,15 +546,15 @@ static _z_encoding_t _z_encoding_from_owned(const z_owned_encoding_t *encoding) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_sample_t, sample, _z_sample_check, _z_sample_null, _z_sample_copy, _z_sample_clear) _Z_OWNED_FUNCTIONS_RC_IMPL(session) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_sample, _z_sample_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_query, _z_query_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_reply, _z_reply_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_hello, z_loaned_hello_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_zid, z_zid_handler_t, z_dropper_handler_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_sample, _z_closure_sample_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_query, _z_closure_query_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_reply, _z_closure_reply_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_hello, z_closure_hello_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_zid, z_closure_zid_callback_t, z_closure_drop_callback_t) /************* Primitives **************/ typedef struct __z_hello_handler_wrapper_t { - z_loaned_hello_handler_t user_call; + z_closure_hello_callback_t user_call; void *ctx; } __z_hello_handler_wrapper_t; @@ -715,8 +712,7 @@ z_result_t z_info_routers_zid(const z_loaned_session_t *zs, z_moved_closure_zid_ z_id_t z_info_zid(const z_loaned_session_t *zs) { return _Z_RC_IN_VAL(zs)->_local_zid; } z_result_t z_id_to_string(const z_id_t *id, z_owned_string_t *str) { - _z_slice_t buf = _z_slice_alias_buf(id->id, sizeof(id->id)); - str->_val = _z_string_convert_bytes(&buf); + str->_val = _z_id_to_string(id); if (!_z_string_check(&str->_val)) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -822,18 +818,22 @@ z_result_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr reliability = opt.reliability; #endif + _z_bytes_t payload_bytes = _z_bytes_from_owned_bytes(&payload->_this); + _z_bytes_t attachment_bytes = _z_bytes_from_owned_bytes(&opt.attachment->_this); _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); - ret = _z_write(_Z_RC_IN_VAL(zs), keyexpr_aliased, _z_bytes_from_owned_bytes(&payload->_this), + ret = _z_write(_Z_RC_IN_VAL(zs), keyexpr_aliased, payload_bytes, opt.encoding == NULL ? NULL : &opt.encoding->_this._val, Z_SAMPLE_KIND_PUT, opt.congestion_control, - opt.priority, opt.is_express, opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), - reliability); + opt.priority, opt.is_express, opt.timestamp, attachment_bytes, reliability); // Trigger local subscriptions +#if Z_FEATURE_LOCAL_SUBSCRIBER == 1 + _z_timestamp_t local_timestamp = (opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null(); + _z_encoding_t local_encoding = (opt.encoding != NULL) ? &opt.encoding->_this._val : _z_encoding_null(); _z_trigger_local_subscriptions( - _Z_RC_IN_VAL(zs), keyexpr_aliased, _z_bytes_from_owned_bytes(&payload->_this), - opt.encoding == NULL ? NULL : &opt.encoding->_this._val, + _Z_RC_IN_VAL(zs), &keyexpr_aliased, &payload_bytes, &local_encoding, _z_n_qos_make(opt.is_express, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority), - opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); + &local_timestamp, &attachment_bytes, reliability); +#endif // Clean-up z_encoding_drop(opt.encoding); z_bytes_drop(opt.attachment); @@ -950,28 +950,43 @@ z_result_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *pay // Remove potentially redundant ke suffix _z_keyexpr_t pub_keyexpr = _z_keyexpr_alias_from_user_defined(pub->_key, true); + _z_session_t *session = NULL; +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 // Try to upgrade session rc _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&pub->_zn); - if (!_Z_RC_IS_NULL(&sess_rc)) { + session = _Z_RC_IN_VAL(&sess_rc); + } else { + ret = _Z_ERR_SESSION_CLOSED; + } +#else + session = _Z_RC_IN_VAL(&pub->_zn); +#endif + + if (session != NULL) { + _z_bytes_t payload_bytes = _z_bytes_from_owned_bytes(&payload->_this); + _z_bytes_t attachment_bytes = _z_bytes_from_owned_bytes(&opt.attachment->_this); + // Check if write filter is active before writing if (!_z_write_filter_active(pub)) { // Write value - ret = _z_write(_Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_from_owned_bytes(&payload->_this), &encoding, - Z_SAMPLE_KIND_PUT, pub->_congestion_control, pub->_priority, pub->_is_express, opt.timestamp, - _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); + ret = _z_write(session, pub_keyexpr, payload_bytes, &encoding, Z_SAMPLE_KIND_PUT, pub->_congestion_control, + pub->_priority, pub->_is_express, opt.timestamp, attachment_bytes, reliability); } // Trigger local subscriptions +#if Z_FEATURE_LOCAL_SUBSCRIBER == 1 + _z_timestamp_t local_timestamp = (opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null(); _z_trigger_local_subscriptions( - _Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_from_owned_bytes(&payload->_this), &encoding, + session, &pub_keyexpr, &payload_bytes, &encoding, _z_n_qos_make(pub->_is_express, pub->_congestion_control == Z_CONGESTION_CONTROL_BLOCK, pub->_priority), - opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); - - _z_session_rc_drop(&sess_rc); - } else { - ret = _Z_ERR_SESSION_CLOSED; + &local_timestamp, &attachment_bytes, reliability); +#endif } +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 + _z_session_rc_drop(&sess_rc); +#endif + // Clean-up _z_encoding_clear(&encoding); z_bytes_drop(opt.attachment); @@ -993,16 +1008,27 @@ z_result_t z_publisher_delete(const z_loaned_publisher_t *pub, const z_publisher // Remove potentially redundant ke suffix _z_keyexpr_t pub_keyexpr = _z_keyexpr_alias_from_user_defined(pub->_key, true); + _z_session_t *session = NULL; +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 // Try to upgrade session rc _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&pub->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (!_Z_RC_IS_NULL(&sess_rc)) { + session = _Z_RC_IN_VAL(&sess_rc); + } else { return _Z_ERR_SESSION_CLOSED; } - z_result_t ret = _z_write(_Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_null(), NULL, Z_SAMPLE_KIND_DELETE, - pub->_congestion_control, pub->_priority, pub->_is_express, opt.timestamp, - _z_bytes_null(), reliability); +#else + session = _Z_RC_IN_VAL(&pub->_zn); +#endif + + z_result_t ret = + _z_write(session, pub_keyexpr, _z_bytes_null(), NULL, Z_SAMPLE_KIND_DELETE, pub->_congestion_control, + pub->_priority, pub->_is_express, opt.timestamp, _z_bytes_null(), reliability); + +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 // Clean up _z_session_rc_drop(&sess_rc); +#endif return ret; } @@ -1046,14 +1072,7 @@ z_result_t z_get(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr z_get_options_t opt; z_get_options_default(&opt); if (options != NULL) { - opt.consolidation = options->consolidation; - opt.target = options->target; - opt.encoding = options->encoding; - opt.payload = options->payload; - opt.attachment = options->attachment; - opt.congestion_control = options->congestion_control; - opt.priority = options->priority; - opt.is_express = options->is_express; + opt = *options; } if (opt.consolidation.mode == Z_CONSOLIDATION_MODE_AUTO) { @@ -1087,6 +1106,7 @@ const z_loaned_sample_t *z_reply_ok(const z_loaned_reply_t *reply) { return &rep const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply) { return &reply->data._result.error; } +#ifdef Z_FEATURE_UNSTABLE_API bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id) { if (_z_id_check(reply->data.replier_id)) { *out_id = reply->data.replier_id; @@ -1094,10 +1114,12 @@ bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id) { } return false; } -#endif +#endif // Z_FEATURE_UNSTABLE_API + +#endif // Z_FEATURE_QUERY == 1 #if Z_FEATURE_QUERYABLE == 1 -_Z_OWNED_FUNCTIONS_RC_IMPL(query) +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_query_t, query, _z_query_check, _z_query_null, _z_query_copy, _z_query_clear) void _z_queryable_drop(_z_queryable_t *queryable) { _z_undeclare_queryable(queryable); @@ -1140,7 +1162,7 @@ z_result_t z_declare_queryable(const z_loaned_session_t *zs, z_owned_queryable_t z_queryable_options_t opt; z_queryable_options_default(&opt); if (options != NULL) { - opt.complete = options->complete; + opt = *options; } queryable->_val = @@ -1167,9 +1189,7 @@ void z_query_reply_options_default(z_query_reply_options_t *options) { z_result_t z_query_reply(const z_loaned_query_t *query, const z_loaned_keyexpr_t *keyexpr, z_moved_bytes_t *payload, const z_query_reply_options_t *options) { - // Try upgrading session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&_Z_RC_IN_VAL(query)->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (_Z_RC_IS_NULL(&query->_zn)) { return _Z_ERR_SESSION_CLOSED; } // Set options @@ -1184,12 +1204,11 @@ z_result_t z_query_reply(const z_loaned_query_t *query, const z_loaned_keyexpr_t _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&payload->_this), .encoding = _z_encoding_from_owned(&opts.encoding->_this)}; - z_result_t ret = _z_send_reply(_Z_RC_IN_VAL(query), &sess_rc, keyexpr_aliased, value, Z_SAMPLE_KIND_PUT, + z_result_t ret = _z_send_reply(query, &query->_zn, keyexpr_aliased, value, Z_SAMPLE_KIND_PUT, opts.congestion_control, opts.priority, opts.is_express, opts.timestamp, _z_bytes_from_owned_bytes(&opts.attachment->_this)); z_bytes_drop(payload); // Clean-up - _z_session_rc_drop(&sess_rc); z_encoding_drop(opts.encoding); z_bytes_drop(opts.attachment); return ret; @@ -1205,9 +1224,7 @@ void z_query_reply_del_options_default(z_query_reply_del_options_t *options) { z_result_t z_query_reply_del(const z_loaned_query_t *query, const z_loaned_keyexpr_t *keyexpr, const z_query_reply_del_options_t *options) { - // Try upgrading session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&_Z_RC_IN_VAL(query)->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (_Z_RC_IS_NULL(&query->_zn)) { return _Z_ERR_SESSION_CLOSED; } _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); @@ -1220,11 +1237,10 @@ z_result_t z_query_reply_del(const z_loaned_query_t *query, const z_loaned_keyex _z_value_t value = {.payload = _z_bytes_null(), .encoding = _z_encoding_null()}; - z_result_t ret = _z_send_reply(_Z_RC_IN_VAL(query), &sess_rc, keyexpr_aliased, value, Z_SAMPLE_KIND_DELETE, + z_result_t ret = _z_send_reply(query, &query->_zn, keyexpr_aliased, value, Z_SAMPLE_KIND_DELETE, opts.congestion_control, opts.priority, opts.is_express, opts.timestamp, _z_bytes_from_owned_bytes(&opts.attachment->_this)); // Clean-up - _z_session_rc_drop(&sess_rc); z_bytes_drop(opts.attachment); return ret; } @@ -1233,9 +1249,7 @@ void z_query_reply_err_options_default(z_query_reply_err_options_t *options) { o z_result_t z_query_reply_err(const z_loaned_query_t *query, z_moved_bytes_t *payload, const z_query_reply_err_options_t *options) { - // Try upgrading session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&_Z_RC_IN_VAL(query)->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (_Z_RC_IS_NULL(&query->_zn)) { return _Z_ERR_SESSION_CLOSED; } z_query_reply_err_options_t opts; @@ -1247,9 +1261,7 @@ z_result_t z_query_reply_err(const z_loaned_query_t *query, z_moved_bytes_t *pay // Set value _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&payload->_this), .encoding = _z_encoding_from_owned(&opts.encoding->_this)}; - - z_result_t ret = _z_send_reply_err(_Z_RC_IN_VAL(query), &sess_rc, value); - _z_session_rc_drop(&sess_rc); + z_result_t ret = _z_send_reply_err(query, &query->_zn, value); z_bytes_drop(payload); // Clean-up z_encoding_drop(opts.encoding); @@ -1408,6 +1420,28 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *sub) } #endif +#ifdef Z_FEATURE_UNSTABLE_API +#if Z_FEATURE_BATCHING == 1 +z_result_t zp_batch_start(const z_loaned_session_t *zs) { + if (_Z_RC_IS_NULL(zs)) { + return _Z_ERR_SESSION_CLOSED; + } + _z_session_t *session = _Z_RC_IN_VAL(zs); + return _z_transport_start_batching(&session->_tp) ? _Z_RES_OK : _Z_ERR_GENERIC; +} + +z_result_t zp_batch_stop(const z_loaned_session_t *zs) { + _z_session_t *session = _Z_RC_IN_VAL(zs); + if (_Z_RC_IS_NULL(zs)) { + return _Z_ERR_SESSION_CLOSED; + } + _z_transport_stop_batching(&session->_tp); + // Send remaining batch + return _z_send_n_batch(session, Z_CONGESTION_CONTROL_DEFAULT); +} +#endif +#endif + /**************** Tasks ****************/ void zp_task_read_options_default(zp_task_read_options_t *options) { #if Z_FEATURE_MULTI_THREAD == 1 @@ -1423,7 +1457,7 @@ z_result_t zp_start_read_task(z_loaned_session_t *zs, const zp_task_read_options zp_task_read_options_t opt; zp_task_read_options_default(&opt); if (options != NULL) { - opt.task_attributes = options->task_attributes; + opt = *options; } return _zp_start_read_task(_Z_RC_IN_VAL(zs), opt.task_attributes); #else @@ -1455,7 +1489,7 @@ z_result_t zp_start_lease_task(z_loaned_session_t *zs, const zp_task_lease_optio zp_task_lease_options_t opt; zp_task_lease_options_default(&opt); if (options != NULL) { - opt.task_attributes = options->task_attributes; + opt = *options; } return _zp_start_lease_task(_Z_RC_IN_VAL(zs), opt.task_attributes); #else diff --git a/src/api/encoding.c b/src/api/encoding.c index 8cbe24ae1..b4ff4cb18 100644 --- a/src/api/encoding.c +++ b/src/api/encoding.c @@ -262,4 +262,6 @@ z_result_t z_encoding_to_string(const z_loaned_encoding_t *encoding, z_owned_str return _Z_RES_OK; } +#if Z_FEATURE_ENCODING_VALUES == 1 const z_loaned_encoding_t *z_encoding_loan_default(void) { return z_encoding_zenoh_bytes(); } +#endif diff --git a/src/api/serialization.c b/src/api/serialization.c index b5ff623d6..c6b018593 100644 --- a/src/api/serialization.c +++ b/src/api/serialization.c @@ -84,9 +84,13 @@ z_result_t ze_deserializer_deserialize_slice(ze_deserializer_t *deserializer, z_ return Z_OK; } +z_result_t ze_serializer_serialize_substr(ze_loaned_serializer_t *serializer, const char *start, size_t len) { + // TODO: perform a UTF-8 correctness check. + return ze_serializer_serialize_buf(serializer, (const uint8_t *)start, len); +} + z_result_t ze_serializer_serialize_str(ze_loaned_serializer_t *serializer, const char *val) { - size_t len = strlen(val); - return ze_serializer_serialize_buf(serializer, (const uint8_t *)val, len); + return ze_serializer_serialize_substr(serializer, val, strlen(val)); } z_result_t ze_serializer_serialize_string(ze_loaned_serializer_t *serializer, const z_loaned_string_t *val) { @@ -121,6 +125,11 @@ z_result_t ze_deserialize_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t * return ze_deserializer_deserialize_slice(&deserializer, data); } +z_result_t ze_serialize_substr(z_owned_bytes_t *bytes, const char *start, size_t len) { + _Z_BUILD_BYTES_FROM_SERIALIZER(ze_serializer_serialize_substr(&serializer, start, len)); + return _Z_RES_OK; +} + z_result_t ze_serialize_str(z_owned_bytes_t *bytes, const char *data) { _Z_BUILD_BYTES_FROM_SERIALIZER(ze_serializer_serialize_str(&serializer, data)); return _Z_RES_OK; diff --git a/src/collections/arc_slice.c b/src/collections/arc_slice.c index 01f7d8038..28603aff9 100644 --- a/src/collections/arc_slice.c +++ b/src/collections/arc_slice.c @@ -19,19 +19,11 @@ #include #include -_z_arc_slice_t _z_arc_slice_empty(void) { - _z_arc_slice_t s; - s.len = 0; - s.start = 0; - s.slice = _z_slice_rc_null(); - return s; -} - _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len) { assert(offset + len <= s.len); _z_arc_slice_t arc_s; - arc_s.slice = _z_slice_rc_new_from_val(&s); + arc_s.slice = _z_slice_simple_rc_new_from_val(&s); if (_Z_RC_IS_NULL(&arc_s.slice)) { return _z_arc_slice_empty(); } @@ -40,6 +32,15 @@ _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len) { return arc_s; } +_z_arc_slice_t _z_arc_slice_wrap_slice_rc(_z_slice_simple_rc_t* slice_rc, size_t offset, size_t len) { + assert(offset + len <= _Z_RC_IN_VAL(slice_rc)->len); + _z_arc_slice_t arc_s; + arc_s.slice = _z_slice_simple_rc_clone(slice_rc); + arc_s.len = len; + arc_s.start = offset; + return arc_s; +} + _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len) { assert(offset + len <= s->len); assert(!_Z_RC_IS_NULL(&s->slice) || (len == 0 && offset == 0)); @@ -48,20 +49,16 @@ _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, return _z_arc_slice_empty(); } _z_arc_slice_t out; - out.slice = _z_slice_rc_clone(&s->slice); + out.slice = _z_slice_simple_rc_clone(&s->slice); out.len = len; out.start = s->start + offset; return out; } -size_t _z_arc_slice_len(const _z_arc_slice_t* s) { return s->len; } - -bool _z_arc_slice_is_empty(const _z_arc_slice_t* s) { return _z_arc_slice_len(s) == 0; } - const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s) { return _Z_RC_IN_VAL(&s->slice)->start + s->start; } z_result_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src) { - _z_slice_rc_copy(&dst->slice, &src->slice); + _z_slice_simple_rc_copy(&dst->slice, &src->slice); dst->len = src->len; dst->start = src->start; return _Z_RES_OK; @@ -73,12 +70,12 @@ z_result_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src) { dst->start = src->start; src->len = 0; src->start = 0; - src->slice = _z_slice_rc_null(); + src->slice = _z_slice_simple_rc_null(); return _Z_RES_OK; } z_result_t _z_arc_slice_drop(_z_arc_slice_t* s) { - _z_slice_rc_drop(&s->slice); - *s = _z_arc_slice_empty(); + _z_slice_simple_rc_drop(&s->slice); + s->len = 0; return _Z_RES_OK; } diff --git a/src/collections/bytes.c b/src/collections/bytes.c index 698e4bb5a..ab3507a95 100644 --- a/src/collections/bytes.c +++ b/src/collections/bytes.c @@ -27,19 +27,8 @@ /*-------- Bytes --------*/ bool _z_bytes_check(const _z_bytes_t *bytes) { return !_z_bytes_is_empty(bytes); } -_z_bytes_t _z_bytes_null(void) { - _z_bytes_t b; - b._slices = _z_arc_slice_svec_make(0); - return b; -} - z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { - _z_arc_slice_svec_copy(&dst->_slices, &src->_slices); - if (_z_arc_slice_svec_len(&dst->_slices) == _z_arc_slice_svec_len(&src->_slices)) { - return _Z_RES_OK; - } else { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + return _z_arc_slice_svec_copy(&dst->_slices, &src->_slices, true); } _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { @@ -74,6 +63,8 @@ _z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i) { void _z_bytes_drop(_z_bytes_t *bytes) { _z_arc_slice_svec_clear(&bytes->_slices); } +void _z_bytes_aliased_drop(_z_bytes_t *bytes) { _z_arc_slice_svec_reset(&bytes->_slices); } + void _z_bytes_free(_z_bytes_t **bs) { _z_bytes_t *ptr = *bs; @@ -104,7 +95,7 @@ z_result_t _z_bytes_from_slice(_z_bytes_t *b, _z_slice_t s) { *b = _z_bytes_null(); _z_arc_slice_t arc_s = _z_arc_slice_wrap(s, 0, s.len); if (_z_arc_slice_len(&arc_s) != s.len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - return _z_arc_slice_svec_append(&b->_slices, &arc_s) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_arc_slice_svec_append(&b->_slices, &arc_s, true); } z_result_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len) { @@ -136,9 +127,12 @@ z_result_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s) { } z_result_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s) { - _Z_CLEAN_RETURN_IF_ERR(_z_arc_slice_svec_append(&dst->_slices, s) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY, - _z_arc_slice_drop(s)); - return _Z_RES_OK; + z_result_t ret = _Z_RES_OK; + ret = _z_arc_slice_svec_append(&dst->_slices, s, true); + if (ret != _Z_RES_OK) { + _z_arc_slice_drop(s); + } + return ret; } z_result_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src) { @@ -161,11 +155,11 @@ _z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs) { _z_arc_slice_t *arc_s = _z_bytes_get_slice(bs, 0); return _z_slice_alias_buf(_z_arc_slice_data(arc_s), _z_arc_slice_len(arc_s)); } - return _z_slice_empty(); + return _z_slice_null(); } void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src) { - dst->_slices = src->_slices; + *dst = *src; *src = _z_bytes_null(); } diff --git a/src/collections/refcount.c b/src/collections/refcount.c index 608548fae..be417fe02 100644 --- a/src/collections/refcount.c +++ b/src/collections/refcount.c @@ -49,9 +49,9 @@ // c11 atomic variant #define _ZP_RC_CNT_TYPE _z_atomic(unsigned int) -#define _ZP_RC_OP_INIT_CNT(p) \ - _z_atomic_store_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_relaxed); \ - _z_atomic_store_explicit(&(p)->_weak_cnt, (unsigned int)1, _z_memory_order_relaxed); +#define _ZP_RC_OP_INIT_STRONG_CNT(p) \ + _z_atomic_store_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_relaxed); +#define _ZP_RC_OP_INIT_WEAK_CNT(p) _z_atomic_store_explicit(&(p)->_weak_cnt, (unsigned int)1, _z_memory_order_relaxed); #define _ZP_RC_OP_INCR_STRONG_CNT(p) \ _z_atomic_fetch_add_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_relaxed); #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) \ @@ -83,10 +83,11 @@ // c99 gcc sync builtin variant #define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT(p) \ +#define _ZP_RC_OP_INIT_STRONG_CNT(p) \ __sync_fetch_and_and(&(p)->_strong_cnt, (unsigned int)0); \ - __sync_fetch_and_add(&(p)->_strong_cnt, (unsigned int)1); \ - __sync_fetch_and_and(&(p)->_weak_cnt, (unsigned int)0); \ + __sync_fetch_and_add(&(p)->_strong_cnt, (unsigned int)1); +#define _ZP_RC_OP_INIT_WEAK_CNT(p) \ + __sync_fetch_and_and(&(p)->_weak_cnt, (unsigned int)0); \ __sync_fetch_and_add(&(p)->_weak_cnt, (unsigned int)1); #define _ZP_RC_OP_INCR_STRONG_CNT(p) __sync_fetch_and_add(&(p)->_strong_cnt, (unsigned int)1); #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) __sync_fetch_and_add(&(p)->_weak_cnt, (unsigned int)1) >= x @@ -117,7 +118,8 @@ // None variant #error "Multi-thread refcount in C99 only exists for GCC, use GCC or C11 or deactivate multi-thread" #define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT(p) +#define _ZP_RC_OP_INIT_STRONG_CNT(p) +#define _ZP_RC_OP_INIT_WEAK_CNT(p) #define _ZP_RC_OP_INCR_STRONG_CNT(p) #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) (x == 0) #define _ZP_RC_OP_DECR_AND_CMP_STRONG(p, x) (x == 0) @@ -136,9 +138,8 @@ // Single thread variant #define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT(p) \ - (p)->_strong_cnt = (unsigned int)1; \ - (p)->_weak_cnt = (unsigned int)1; +#define _ZP_RC_OP_INIT_STRONG_CNT(p) (p)->_strong_cnt = (unsigned int)1; +#define _ZP_RC_OP_INIT_WEAK_CNT(p) (p)->_weak_cnt = (unsigned int)1; #define _ZP_RC_OP_INCR_STRONG_CNT(p) p->_strong_cnt++; #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) p->_weak_cnt++ >= x #define _ZP_RC_OP_DECR_AND_CMP_STRONG(p, x) p->_strong_cnt-- > (unsigned int)x @@ -170,7 +171,8 @@ z_result_t _z_rc_init(void** cnt) { if ((*cnt) == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - _ZP_RC_OP_INIT_CNT((_z_inner_rc_t*)*cnt) + _ZP_RC_OP_INIT_STRONG_CNT((_z_inner_rc_t*)*cnt) + _ZP_RC_OP_INIT_WEAK_CNT((_z_inner_rc_t*)*cnt) return _Z_RES_OK; } @@ -219,3 +221,33 @@ z_result_t _z_rc_weak_upgrade(void* cnt) { return _upgrade((_z_inner_rc_t*)cnt); size_t _z_rc_weak_count(void* cnt) { return ((_z_inner_rc_t*)cnt)->_weak_cnt; } size_t _z_rc_strong_count(void* cnt) { return ((_z_inner_rc_t*)cnt)->_strong_cnt; } + +typedef struct { + _ZP_RC_CNT_TYPE _strong_cnt; +} _z_inner_simple_rc_t; + +z_result_t _z_simple_rc_init(void** cnt) { + *cnt = z_malloc(sizeof(_z_inner_simple_rc_t)); + if ((*cnt) == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _ZP_RC_OP_INIT_STRONG_CNT((_z_inner_simple_rc_t*)*cnt) + return _Z_RES_OK; +} + +z_result_t _z_simple_rc_increase(void* cnt) { + _z_inner_simple_rc_t* c = (_z_inner_simple_rc_t*)cnt; + _ZP_RC_OP_INCR_STRONG_CNT(c); + return _Z_RES_OK; +} + +bool _z_simple_rc_decrease(void** cnt) { + _z_inner_simple_rc_t* c = (_z_inner_simple_rc_t*)*cnt; + if (_ZP_RC_OP_DECR_AND_CMP_STRONG(c, 1)) { + return false; + } + z_free(*cnt); + return true; +} + +size_t _z_simple_rc_strong_count(void* cnt) { return ((_z_inner_simple_rc_t*)cnt)->_strong_cnt; } diff --git a/src/collections/slice.c b/src/collections/slice.c index c6fe1171a..049721a8a 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -28,14 +28,6 @@ void _z_default_deleter(void *data, void *context) { z_free(data); } -_z_delete_context_t _z_delete_context_null(void) { return _z_delete_context_create(NULL, NULL); } - -bool _z_delete_context_is_null(const _z_delete_context_t *c) { return c->deleter == NULL; } - -_z_delete_context_t _z_delete_context_create(void (*deleter)(void *data, void *context), void *context) { - return (_z_delete_context_t){.deleter = deleter, .context = context}; -} - _z_delete_context_t _z_delete_context_default(void) { return _z_delete_context_create(_z_default_deleter, NULL); } void _z_delete_context_delete(_z_delete_context_t *c, void *data) { @@ -45,27 +37,16 @@ void _z_delete_context_delete(_z_delete_context_t *c, void *data) { } /*-------- Slice --------*/ -_z_slice_t _z_slice_empty(void) { - return (_z_slice_t){.start = NULL, .len = 0, ._delete_context = _z_delete_context_null()}; -} - z_result_t _z_slice_init(_z_slice_t *bs, size_t capacity) { - z_result_t ret = _Z_RES_OK; - - bs->start = capacity == 0 ? NULL : (uint8_t *)z_malloc(capacity); - if (bs->start != NULL) { - bs->len = capacity; - bs->_delete_context = _z_delete_context_default(); - } else { + bs->start = (uint8_t *)z_malloc(capacity); + if (bs->start == NULL) { bs->len = 0; bs->_delete_context = _z_delete_context_null(); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - - if (bs->len != capacity) { - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - - return ret; + bs->len = capacity; + bs->_delete_context = _z_delete_context_default(); + return _Z_RES_OK; } _z_slice_t _z_slice_make(size_t capacity) { @@ -82,11 +63,6 @@ _z_slice_t _z_slice_from_buf_custom_deleter(const uint8_t *p, size_t len, _z_del return bs; } -_z_slice_t _z_slice_alias(const _z_slice_t *bs) { - _z_slice_t alias = {.len = bs->len, .start = bs->start, ._delete_context = _z_delete_context_null()}; - return alias; -} - _z_slice_t _z_slice_alias_buf(const uint8_t *p, size_t len) { return _z_slice_from_buf_custom_deleter(p, len, _z_delete_context_null()); } @@ -96,12 +72,6 @@ _z_slice_t _z_slice_copy_from_buf(const uint8_t *p, size_t len) { return _z_slice_duplicate(&bs); } -void _z_slice_reset(_z_slice_t *bs) { - bs->start = NULL; - bs->len = 0; - bs->_delete_context = _z_delete_context_null(); -} - void _z_slice_clear(_z_slice_t *bs) { if ((bs->start != NULL)) { _z_delete_context_delete(&bs->_delete_context, (void *)bs->start); @@ -141,24 +111,19 @@ z_result_t _z_slice_n_copy(_z_slice_t *dst, const _z_slice_t *src, size_t offset } void _z_slice_move(_z_slice_t *dst, _z_slice_t *src) { - dst->start = src->start; - dst->len = src->len; - dst->_delete_context = src->_delete_context; - + *dst = *src; _z_slice_reset(src); } _z_slice_t _z_slice_duplicate(const _z_slice_t *src) { - _z_slice_t dst = _z_slice_empty(); + _z_slice_t dst = _z_slice_null(); _z_slice_copy(&dst, src); return dst; } -bool _z_slice_is_empty(const _z_slice_t *bs) { return bs->len == 0; } - _z_slice_t _z_slice_steal(_z_slice_t *b) { _z_slice_t ret = *b; - *b = _z_slice_empty(); + *b = _z_slice_null(); return ret; } bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right) { diff --git a/src/collections/string.c b/src/collections/string.c index 753c7cad5..236b85077 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -17,16 +17,10 @@ #include #include +#include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/pointers.h" /*-------- string --------*/ -_z_string_t _z_string_null(void) { - _z_string_t s = {._slice = _z_slice_empty()}; - return s; -} - -bool _z_string_check(const _z_string_t *value) { return !_z_slice_is_empty(&value->_slice); } - _z_string_t _z_string_copy_from_str(const char *value) { _z_string_t s; s._slice = _z_slice_copy_from_buf((uint8_t *)value, strlen(value)); @@ -39,6 +33,12 @@ _z_string_t _z_string_copy_from_substr(const char *value, size_t len) { return s; } +_z_string_t _z_string_alias_slice(const _z_slice_t *slice) { + _z_string_t s; + s._slice = _z_slice_alias(*slice); + return s; +} + _z_string_t _z_string_alias_str(const char *value) { _z_string_t s; s._slice = _z_slice_alias_buf((const uint8_t *)(value), strlen(value)); @@ -77,7 +77,7 @@ z_result_t _z_string_copy_substring(_z_string_t *dst, const _z_string_t *src, si return _z_slice_n_copy(&dst->_slice, &src->_slice, offset, len); } -void _z_string_move(_z_string_t *dst, _z_string_t *src) { *dst = _z_string_steal(src); } +void _z_string_move(_z_string_t *dst, _z_string_t *src) { _z_slice_move(&dst->_slice, &src->_slice); } _z_string_t _z_string_steal(_z_string_t *str) { _z_string_t ret; @@ -85,11 +85,6 @@ _z_string_t _z_string_steal(_z_string_t *str) { return ret; } -_z_string_t _z_string_alias(const _z_string_t *str) { - _z_string_t alias = {._slice = _z_slice_alias(&str->_slice)}; - return alias; -} - void _z_string_move_str(_z_string_t *dst, char *src) { *dst = _z_string_alias_str(src); } void _z_string_reset(_z_string_t *str) { _z_slice_reset(&str->_slice); } @@ -113,7 +108,7 @@ bool _z_string_equals(const _z_string_t *left, const _z_string_t *right) { return (strncmp(_z_string_data(left), _z_string_data(right), _z_string_len(left)) == 0); } -_z_string_t _z_string_convert_bytes(const _z_slice_t *bs) { +_z_string_t _z_string_convert_bytes_le(const _z_slice_t *bs) { _z_string_t s = _z_string_null(); size_t len = bs->len * (size_t)2; char *s_val = (char *)z_malloc((len) * sizeof(char)); @@ -121,20 +116,21 @@ _z_string_t _z_string_convert_bytes(const _z_slice_t *bs) { return s; } - const char c[] = "0123456789ABCDEF"; + const char c[] = "0123456789abcdef"; + size_t pos = bs->len * 2; for (size_t i = 0; i < bs->len; i++) { - s_val[i * (size_t)2] = c[(bs->start[i] & (uint8_t)0xF0) >> (uint8_t)4]; - s_val[(i * (size_t)2) + 1] = c[bs->start[i] & (uint8_t)0x0F]; + s_val[--pos] = c[bs->start[i] & (uint8_t)0x0F]; + s_val[--pos] = c[(bs->start[i] & (uint8_t)0xF0) >> (uint8_t)4]; } s._slice = _z_slice_from_buf_custom_deleter((const uint8_t *)s_val, len, _z_delete_context_default()); return s; } _z_string_t _z_string_preallocate(size_t len) { - _z_string_t s = _z_string_null(); - _z_slice_init(&s._slice, len); - if (_z_slice_is_empty(&s._slice)) { - return _z_string_null(); + _z_string_t s; + // As long as _z_string_t is only a slice, no need to do anything more + if (_z_slice_init(&s._slice, len) != _Z_RES_OK) { + _Z_ERROR("String allocation failed"); } return s; } @@ -220,4 +216,8 @@ char *_z_str_n_clone(const char *src, size_t len) { return dst; } +char *_z_str_from_string_clone(const _z_string_t *str) { + return _z_str_n_clone((const char *)str->_slice.start, str->_slice.len); +} + bool _z_str_eq(const char *left, const char *right) { return strcmp(left, right) == 0; } diff --git a/src/collections/vec.c b/src/collections/vec.c index 6556d6b88..e37614cca 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -20,12 +20,12 @@ /*-------- vec --------*/ _z_vec_t _z_vec_make(size_t capacity) { - _z_vec_t v = {._capacity = capacity, ._len = 0, ._val = NULL}; + _z_vec_t v = {0}; if (capacity != 0) { v._val = (void **)z_malloc(sizeof(void *) * capacity); - } - if (v._val != NULL) { - v._capacity = capacity; + if (v._val != NULL) { + v._capacity = capacity; + } } return v; } @@ -41,6 +41,11 @@ void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f d_f) { } } +void _z_vec_move(_z_vec_t *dst, _z_vec_t *src) { + *dst = *src; + *src = _z_vec_null(); +} + void _z_vec_reset(_z_vec_t *v, z_element_free_f free_f) { for (size_t i = 0; i < v->_len; i++) { free_f(&v->_val[i]); @@ -130,7 +135,7 @@ void _z_vec_remove(_z_vec_t *v, size_t pos, z_element_free_f free_f) { /*-------- svec --------*/ _z_svec_t _z_svec_make(size_t capacity, size_t element_size) { - _z_svec_t v = {._capacity = 0, ._len = 0, ._val = NULL}; + _z_svec_t v = _z_svec_null(); if (capacity != 0) { v._val = z_malloc(element_size * capacity); } @@ -140,40 +145,51 @@ _z_svec_t _z_svec_make(size_t capacity, size_t element_size) { return v; } -void __z_svec_copy_inner(void *dst, const void *src, z_element_copy_f copy, size_t num_elements, size_t element_size) { - if (copy == NULL) { - memcpy(dst, src, num_elements * element_size); - } else { - size_t offset = 0; - for (size_t i = 0; i < num_elements; i++) { - copy((uint8_t *)dst + offset, (uint8_t *)src + offset); - offset += element_size; - } - } +void _z_svec_init(_z_svec_t *v, size_t offset, size_t element_size) { + assert(offset <= v->_capacity); + void *start = _z_svec_get_mut(v, offset, element_size); + memset(start, 0, (v->_capacity - offset) * element_size); } -void __z_svec_move_inner(void *dst, void *src, z_element_move_f move, size_t num_elements, size_t element_size) { - if (move == NULL) { - memcpy(dst, src, num_elements * element_size); - } else { +static inline void __z_svec_move_inner(void *dst, void *src, z_element_move_f move, size_t num_elements, + size_t element_size, bool use_elem_f) { + if (use_elem_f) { size_t offset = 0; for (size_t i = 0; i < num_elements; i++) { move((uint8_t *)dst + offset, (uint8_t *)src + offset); offset += element_size; } + } else { + memcpy(dst, src, num_elements * element_size); } } -bool _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size) { +void _z_svec_move(_z_svec_t *dst, _z_svec_t *src) { + *dst = *src; + *src = _z_svec_null(); +} + +z_result_t _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size, + bool use_elem_f) { dst->_capacity = 0; dst->_len = 0; dst->_val = z_malloc(element_size * src->_capacity); - if (dst->_val != NULL) { - dst->_capacity = src->_capacity; - dst->_len = src->_len; - __z_svec_copy_inner(dst->_val, src->_val, copy, src->_len, element_size); + if (dst->_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + dst->_capacity = src->_capacity; + dst->_len = src->_len; + // Copy data to new vector + if (use_elem_f) { + size_t offset = 0; + for (size_t i = 0; i < src->_len; i++) { + copy((uint8_t *)dst->_val + offset, (uint8_t *)src->_val + offset); + offset += element_size; + } + } else { + memcpy(dst->_val, src->_val, src->_len * element_size); } - return dst->_len == src->_len; + return _Z_RES_OK; } void _z_svec_reset(_z_svec_t *v, z_element_clear_f clear, size_t element_size) { @@ -194,10 +210,7 @@ void _z_svec_clear(_z_svec_t *v, z_element_clear_f clear_f, size_t element_size) void _z_svec_release(_z_svec_t *v) { z_free(v->_val); - v->_val = NULL; - v->_capacity = 0; - v->_len = 0; } void _z_svec_free(_z_svec_t **v, z_element_clear_f clear, size_t element_size) { @@ -215,29 +228,32 @@ size_t _z_svec_len(const _z_svec_t *v) { return v->_len; } bool _z_svec_is_empty(const _z_svec_t *v) { return v->_len == 0; } -bool _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f move, size_t element_size) { - if (v->_len == v->_capacity) { - // Allocate a new vector - size_t _capacity = v->_capacity == 0 ? 1 : (v->_capacity << 1); - void *_val = (void *)z_malloc(_capacity * element_size); - if (_val != NULL) { - __z_svec_move_inner(_val, v->_val, move, v->_len, element_size); - // Free the old data - z_free(v->_val); +z_result_t _z_svec_expand(_z_svec_t *v, z_element_move_f move, size_t element_size, bool use_elem_f) { + // Allocate a new vector + size_t _capacity = v->_capacity << 1; + void *_val = (void *)z_malloc(_capacity * element_size); + if (_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Move and clear old data + __z_svec_move_inner(_val, v->_val, move, v->_len, element_size, use_elem_f); + z_free(v->_val); + // Update the current vector + v->_val = _val; + v->_capacity = _capacity; + return _Z_RES_OK; +} - // Update the current vector - v->_val = _val; - v->_capacity = _capacity; - memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); - v->_len++; - } else { - return false; - } - } else { - memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); - v->_len++; +z_result_t _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f move, size_t element_size, bool use_elem_f) { + if (v->_capacity == 0) { + *v = _z_svec_make(1, element_size); + } else if (v->_len == v->_capacity) { + _Z_RETURN_IF_ERR(_z_svec_expand(v, move, element_size, use_elem_f)); } - return true; + // Append element + memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); + v->_len++; + return _Z_RES_OK; } void *_z_svec_get(const _z_svec_t *v, size_t i, size_t element_size) { @@ -245,17 +261,20 @@ void *_z_svec_get(const _z_svec_t *v, size_t i, size_t element_size) { return (uint8_t *)v->_val + i * element_size; } +void *_z_svec_get_mut(_z_svec_t *v, size_t i, size_t element_size) { return (uint8_t *)v->_val + i * element_size; } + void _z_svec_set(_z_svec_t *v, size_t i, void *e, z_element_clear_f clear, size_t element_size) { assert(i < v->_len); clear((uint8_t *)v->_val + i * element_size); memcpy((uint8_t *)v->_val + i * element_size, e, element_size); } -void _z_svec_remove(_z_svec_t *v, size_t pos, z_element_clear_f clear, z_element_move_f move, size_t element_size) { +void _z_svec_remove(_z_svec_t *v, size_t pos, z_element_clear_f clear, z_element_move_f move, size_t element_size, + bool use_elem_f) { assert(pos < v->_len); clear((uint8_t *)v->_val + pos * element_size); __z_svec_move_inner((uint8_t *)v->_val + pos * element_size, (uint8_t *)v->_val + (pos + 1) * element_size, move, - (v->_len - pos - 1) * element_size, element_size); + (v->_len - pos - 1) * element_size, element_size, use_elem_f); v->_len--; } diff --git a/src/link/link.c b/src/link/link.c index 197d68212..8c5ffb312 100644 --- a/src/link/link.c +++ b/src/link/link.c @@ -27,13 +27,10 @@ z_result_t _z_open_link(_z_link_t *zl, _z_string_t *locator) { _z_endpoint_t ep; ret = _z_endpoint_from_string(&ep, locator); if (ret == _Z_RES_OK) { - // TODO[peer]: when peer unicast mode is supported, this must be revisited // Create transport link -#if Z_FEATURE_LINK_TCP == 1 if (_z_endpoint_tcp_valid(&ep) == _Z_RES_OK) { ret = _z_new_link_tcp(zl, &ep); } else -#endif #if Z_FEATURE_LINK_UDP_UNICAST == 1 if (_z_endpoint_udp_unicast_valid(&ep) == _Z_RES_OK) { ret = _z_new_link_udp_unicast(zl, ep); @@ -80,10 +77,12 @@ z_result_t _z_listen_link(_z_link_t *zl, _z_string_t *locator) { _z_endpoint_t ep; ret = _z_endpoint_from_string(&ep, locator); if (ret == _Z_RES_OK) { - // TODO[peer]: when peer unicast mode is supported, this must be revisited // Create transport link + if (_z_endpoint_tcp_valid(&ep) == _Z_RES_OK) { + ret = _z_new_link_tcp(zl, &ep); + } else #if Z_FEATURE_LINK_UDP_MULTICAST == 1 - if (_z_endpoint_udp_multicast_valid(&ep) == _Z_RES_OK) { + if (_z_endpoint_udp_multicast_valid(&ep) == _Z_RES_OK) { ret = _z_new_link_udp_multicast(zl, ep); } else #endif @@ -153,17 +152,8 @@ size_t _z_link_recv_exact_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, size_t len z_result_t _z_link_send_wbuf(const _z_link_t *link, const _z_wbuf_t *wbf) { z_result_t ret = _Z_RES_OK; - bool link_is_streamed = false; - - switch (link->_cap._flow) { - case Z_LINK_CAP_FLOW_STREAM: - link_is_streamed = true; - break; - case Z_LINK_CAP_FLOW_DATAGRAM: - default: - link_is_streamed = false; - break; - } + bool link_is_streamed = link->_cap._flow == Z_LINK_CAP_FLOW_STREAM; + for (size_t i = 0; (i < _z_wbuf_len_iosli(wbf)) && (ret == _Z_RES_OK); i++) { _z_slice_t bs = _z_iosli_to_bytes(_z_wbuf_get_iosli(wbf, i)); size_t n = bs.len; diff --git a/src/link/multicast/bt.c b/src/link/multicast/bt.c index 0b26d3643..84216e9bb 100644 --- a/src/link/multicast/bt.c +++ b/src/link/multicast/bt.c @@ -104,8 +104,8 @@ size_t _z_f_link_write_all_bt(const _z_link_t *self, const uint8_t *ptr, size_t size_t _z_f_link_read_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { size_t rb = _z_read_bt(self->_socket._bt._sock, ptr, len); if ((rb > (size_t)0) && (addr != NULL)) { - *addr = _z_slice_make(strlen(self->_socket._bt._gname)); - (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, addr->len); + addr->len = strlen(self->_socket._bt._gname); + (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, strlen(self->_socket._bt._gname)); } return rb; @@ -114,8 +114,8 @@ size_t _z_f_link_read_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_sli size_t _z_f_link_read_exact_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { size_t rb = _z_read_exact_bt(self->_socket._bt._sock, ptr, len); if ((rb == len) && (addr != NULL)) { - *addr = _z_slice_make(strlen(self->_socket._bt._gname)); - (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, addr->len); + addr->len = strlen(self->_socket._bt._gname); + (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, strlen(self->_socket._bt._gname)); } return rb; diff --git a/src/link/unicast/tcp.c b/src/link/unicast/tcp.c index d55cf7c31..232b7ffdc 100644 --- a/src/link/unicast/tcp.c +++ b/src/link/unicast/tcp.c @@ -188,4 +188,15 @@ z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *endpoint) { return ret; } +#else +z_result_t _z_endpoint_tcp_valid(_z_endpoint_t *endpoint) { + _ZP_UNUSED(endpoint); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} + +z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *endpoint) { + _ZP_UNUSED(zl); + _ZP_UNUSED(endpoint); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} #endif diff --git a/src/net/encoding.c b/src/net/encoding.c index 5926f4657..45b13e4d3 100644 --- a/src/net/encoding.c +++ b/src/net/encoding.c @@ -19,6 +19,11 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" +_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema) { + return (_z_encoding_t){.id = id, + .schema = (schema == NULL) ? _z_string_null() : _z_string_alias_str((char *)schema)}; +} + z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len) { encoding->id = id; // Clone schema @@ -33,30 +38,30 @@ z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *sc return _Z_RES_OK; } -_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema) { - return (_z_encoding_t){.id = id, - .schema = (schema == NULL) ? _z_string_null() : _z_string_alias_str((char *)schema)}; -} - -_z_encoding_t _z_encoding_null(void) { return _z_encoding_wrap(_Z_ENCODING_ID_DEFAULT, NULL); } - -void _z_encoding_clear(_z_encoding_t *encoding) { _z_string_clear(&encoding->schema); } - -bool _z_encoding_check(const _z_encoding_t *encoding) { - return ((encoding->id != _Z_ENCODING_ID_DEFAULT) || _z_string_check(&encoding->schema)); +void _z_encoding_clear(_z_encoding_t *encoding) { + if (_z_string_check(&encoding->schema)) { + _z_string_clear(&encoding->schema); + } } z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src) { - *dst = _z_encoding_null(); - _Z_RETURN_IF_ERR(_z_string_copy(&dst->schema, &src->schema)); dst->id = src->id; + if (_z_string_check(&src->schema)) { + _Z_RETURN_IF_ERR(_z_string_copy(&dst->schema, &src->schema)); + } else { + dst->schema = _z_string_null(); + } return _Z_RES_OK; } void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src) { dst->id = src->id; src->id = _Z_ENCODING_ID_DEFAULT; - _z_string_move(&dst->schema, &src->schema); + if (_z_string_check(&src->schema)) { + _z_string_move(&dst->schema, &src->schema); + } else { + dst->schema = _z_string_null(); + } } _z_encoding_t _z_encoding_steal(_z_encoding_t *val) { diff --git a/src/net/filtering.c b/src/net/filtering.c index d3be65236..022c6c798 100644 --- a/src/net/filtering.c +++ b/src/net/filtering.c @@ -96,9 +96,10 @@ z_result_t _z_write_filter_create(_z_publisher_t *pub) { z_result_t _z_write_filter_destroy(_z_publisher_t *pub) { if (pub->_filter.ctx != NULL) { - _Z_RETURN_IF_ERR(_z_remove_interest(_Z_RC_IN_VAL(&pub->_zn), pub->_filter._interest_id)); + z_result_t res = _z_remove_interest(_Z_RC_IN_VAL(&pub->_zn), pub->_filter._interest_id); z_free(pub->_filter.ctx); pub->_filter.ctx = NULL; + return res; } return _Z_RES_OK; } diff --git a/src/net/primitives.c b/src/net/primitives.c index b2b8d9d7d..baf24fa50 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -33,12 +33,13 @@ #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" /*------------------ Scouting ------------------*/ void _z_scout(const z_what_t what, const _z_id_t zid, _z_string_t *locator, const uint32_t timeout, - _z_hello_handler_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop) { + _z_closure_hello_callback_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop) { _z_hello_list_t *hellos = _z_scout_inner(what, zid, locator, timeout, false); while (hellos != NULL) { @@ -108,7 +109,7 @@ _z_publisher_t _z_declare_publisher(const _z_session_rc_t *zn, _z_keyexpr_t keye // Allocate publisher _z_publisher_t ret; // Fill publisher - ret._key = _z_keyexpr_duplicate(keyexpr); + ret._key = _z_keyexpr_duplicate(&keyexpr); ret._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); ret._congestion_control = congestion_control; ret._priority = priority; @@ -192,8 +193,8 @@ z_result_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes #if Z_FEATURE_SUBSCRIPTION == 1 /*------------------ Subscriber Declaration ------------------*/ -_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_sample_handler_t callback, - _z_drop_handler_t dropper, void *arg) { +_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, + _z_closure_sample_callback_t callback, _z_drop_handler_t dropper, void *arg) { _z_subscription_t s; s._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); s._key_id = keyexpr._id; @@ -256,7 +257,7 @@ z_result_t _z_undeclare_subscriber(_z_subscriber_t *sub) { #if Z_FEATURE_QUERYABLE == 1 /*------------------ Queryable Declaration ------------------*/ _z_queryable_t _z_declare_queryable(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, bool complete, - _z_query_handler_t callback, _z_drop_handler_t dropper, void *arg) { + _z_closure_query_callback_t callback, _z_drop_handler_t dropper, void *arg) { _z_session_queryable_t q; q._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); q._key = _z_get_expanded_key_from_key(_Z_RC_IN_VAL(zn), &keyexpr); @@ -452,7 +453,7 @@ z_result_t _z_send_reply_err(const _z_query_t *query, const _z_session_rc_t *zsr #if Z_FEATURE_QUERY == 1 /*------------------ Query ------------------*/ z_result_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, const z_query_target_t target, - const z_consolidation_mode_t consolidation, _z_value_t value, _z_reply_handler_t callback, + const z_consolidation_mode_t consolidation, _z_value_t value, _z_closure_reply_callback_t callback, _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms, const _z_bytes_t attachment, z_congestion_control_t cong_ctrl, z_priority_t priority, bool is_express) { z_result_t ret = _Z_RES_OK; @@ -469,6 +470,8 @@ z_result_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *paramete pq->_dropper = dropper; pq->_pending_replies = NULL; pq->_arg = arg; + pq->_timeout = timeout_ms; + pq->_start_time = z_clock_now(); ret = _z_register_pending_query(zn, pq); // Add the pending query to the current session if (ret == _Z_RES_OK) { diff --git a/src/net/publish.c b/src/net/publish.c index d81893d0b..13900de39 100644 --- a/src/net/publish.c +++ b/src/net/publish.c @@ -35,17 +35,4 @@ void _z_publisher_free(_z_publisher_t **pub) { } } -bool _z_publisher_check(const _z_publisher_t *publisher) { return !_Z_RC_IS_NULL(&publisher->_zn); } -_z_publisher_t _z_publisher_null(void) { - return (_z_publisher_t){._congestion_control = Z_CONGESTION_CONTROL_DEFAULT, - ._id = 0, - ._key = _z_keyexpr_null(), - ._priority = Z_PRIORITY_DEFAULT, - ._zn = _z_session_weak_null(), - ._encoding = _z_encoding_null(), -#if Z_FEATURE_INTEREST == 1 - ._filter = (_z_write_filter_t){._interest_id = 0, .ctx = NULL} -#endif - }; -} #endif diff --git a/src/net/query.c b/src/net/query.c index 75bde3f41..dcf5b647a 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -14,32 +14,19 @@ #include "zenoh-pico/net/query.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" -_z_query_t _z_query_null(void) { - return (_z_query_t){ - ._anyke = false, - ._key = _z_keyexpr_null(), - ._parameters = NULL, - ._request_id = 0, - ._value = _z_value_null(), - .attachment = _z_bytes_null(), - ._zn = _z_session_weak_null(), - }; -} - void _z_query_clear_inner(_z_query_t *q) { _z_keyexpr_clear(&q->_key); _z_value_clear(&q->_value); - _z_bytes_drop(&q->attachment); - z_free(q->_parameters); - _z_session_weak_drop(&q->_zn); + _z_bytes_drop(&q->_attachment); + _z_string_clear(&q->_parameters); + _z_session_rc_drop(&q->_zn); } void _z_query_clear(_z_query_t *q) { - // Try to upgrade session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&q->_zn); - if (!_Z_RC_IS_NULL(&sess_rc)) { + if (!_Z_RC_IS_NULL(&q->_zn)) { // Send REPLY_FINAL message _z_zenoh_message_t z_msg = _z_n_msg_make_response_final(q->_request_id); if (_z_send_n_msg(_Z_RC_IN_VAL(&q->_zn), &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != @@ -47,7 +34,6 @@ void _z_query_clear(_z_query_t *q) { _Z_ERROR("Query send REPLY_FINAL transport failure !"); } _z_msg_clear(&z_msg); - _z_session_rc_drop(&sess_rc); } // Clean up memory _z_query_clear_inner(q); @@ -57,13 +43,9 @@ z_result_t _z_query_copy(_z_query_t *dst, const _z_query_t *src) { *dst = _z_query_null(); _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_key, &src->_key)); _Z_CLEAN_RETURN_IF_ERR(_z_value_copy(&dst->_value, &src->_value), _z_query_clear_inner(dst)); - _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->attachment, &src->attachment), _z_query_clear_inner(dst)); - dst->_parameters = _z_str_clone(src->_parameters); - if (dst->_parameters == NULL && src->_parameters != NULL) { - _z_query_clear_inner(dst); - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - _z_session_weak_copy(&dst->_zn, &src->_zn); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->_attachment, &src->_attachment), _z_query_clear_inner(dst)); + _Z_CLEAN_RETURN_IF_ERR(_z_string_copy(&dst->_parameters, &src->_parameters), _z_query_clear_inner(dst)); + _z_session_rc_copy(&dst->_zn, &src->_zn); if (_Z_RC_IS_NULL(&dst->_zn)) { _z_query_clear_inner(dst); return _Z_ERR_SYSTEM_OUT_OF_MEMORY; @@ -84,25 +66,6 @@ void _z_query_free(_z_query_t **query) { } #if Z_FEATURE_QUERYABLE == 1 -_z_query_t _z_query_create(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, _z_session_rc_t *zsrc, - uint32_t request_id, const _z_bytes_t attachment) { - _z_query_t q = _z_query_null(); - q._request_id = request_id; - q._zn = _z_session_rc_clone_as_weak(zsrc); - q._parameters = (char *)z_malloc(parameters->len + 1); - memcpy(q._parameters, parameters->start, parameters->len); - q._parameters[parameters->len] = 0; - q._anyke = (strstr(q._parameters, Z_SELECTOR_QUERY_MATCH) == NULL) ? false : true; - q._key = _z_keyexpr_steal(key); - _z_bytes_copy(&q.attachment, &attachment); - _z_value_move(&q._value, value); - return q; -} - -_z_queryable_t _z_queryable_null(void) { return (_z_queryable_t){._entity_id = 0, ._zn = _z_session_weak_null()}; } - -bool _z_queryable_check(const _z_queryable_t *queryable) { return !_Z_RC_IS_NULL(&queryable->_zn); } - void _z_queryable_clear(_z_queryable_t *qbl) { _z_session_weak_drop(&qbl->_zn); *qbl = _z_queryable_null(); diff --git a/src/net/reply.c b/src/net/reply.c index b9038af2e..9c06b2674 100644 --- a/src/net/reply.c +++ b/src/net/reply.c @@ -17,15 +17,6 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" -_z_reply_data_t _z_reply_data_null(void) { - return (_z_reply_data_t){.replier_id = {.id = {0}}, ._result.sample = _z_sample_null(), ._tag = _Z_REPLY_TAG_NONE}; -} - -_z_reply_t _z_reply_null(void) { - _z_reply_t r = {.data = _z_reply_data_null()}; - return r; -} - #if Z_FEATURE_QUERY == 1 void _z_reply_data_clear(_z_reply_data_t *reply_data) { if (reply_data->_tag == _Z_REPLY_TAG_DATA) { @@ -48,14 +39,13 @@ void _z_reply_data_free(_z_reply_data_t **reply_data) { } z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src) { - *dst = _z_reply_data_null(); if (src->_tag == _Z_REPLY_TAG_DATA) { _Z_RETURN_IF_ERR(_z_sample_copy(&dst->_result.sample, &src->_result.sample)); } else if (src->_tag == _Z_REPLY_TAG_ERROR) { _Z_RETURN_IF_ERR(_z_value_copy(&dst->_result.error, &src->_result.error)); } - dst->replier_id = src->replier_id; dst->_tag = src->_tag; + dst->replier_id = src->replier_id; return _Z_RES_OK; } @@ -78,11 +68,7 @@ void _z_reply_free(_z_reply_t **reply) { } } -z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src) { - *dst = _z_reply_null(); - _Z_RETURN_IF_ERR(_z_reply_data_copy(&dst->data, &src->data)); - return _Z_RES_OK; -} +z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src) { return _z_reply_data_copy(&dst->data, &src->data); } bool _z_pending_reply_eq(const _z_pending_reply_t *one, const _z_pending_reply_t *two) { return one->_tstamp.time == two->_tstamp.time; @@ -96,46 +82,4 @@ void _z_pending_reply_clear(_z_pending_reply_t *pr) { _z_timestamp_clear(&pr->_tstamp); } -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, z_sample_kind_t kind, const _z_bytes_t attachment) { - _z_reply_t reply = _z_reply_null(); - reply.data._tag = _Z_REPLY_TAG_DATA; - reply.data.replier_id = id; - - // Create reply sample - reply.data._result.sample.keyexpr = _z_keyexpr_steal(&keyexpr); - reply.data._result.sample.kind = kind; - reply.data._result.sample.timestamp = _z_timestamp_duplicate(timestamp); - _z_bytes_copy(&reply.data._result.sample.payload, &payload); - _z_bytes_copy(&reply.data._result.sample.attachment, &attachment); - _z_encoding_move(&reply.data._result.sample.encoding, encoding); - - return reply; -} - -_z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding) { - _z_reply_t reply = _z_reply_null(); - reply.data._tag = _Z_REPLY_TAG_ERROR; - _z_bytes_copy(&reply.data._result.error.payload, &payload); - _z_encoding_move(&reply.data._result.error.encoding, encoding); - return reply; -} -#else -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, z_sample_kind_t kind, const _z_bytes_t attachment) { - _ZP_UNUSED(keyexpr); - _ZP_UNUSED(id); - _ZP_UNUSED(payload); - _ZP_UNUSED(timestamp); - _ZP_UNUSED(encoding); - _ZP_UNUSED(kind); - _ZP_UNUSED(attachment); - return _z_reply_null(); -} - -_z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding) { - _ZP_UNUSED(payload); - _ZP_UNUSED(encoding); - return _z_reply_null(); -} -#endif +#endif // Z_FEATURE_QUERY == 1 diff --git a/src/net/sample.c b/src/net/sample.c index 6248f57e5..b700e49c1 100644 --- a/src/net/sample.c +++ b/src/net/sample.c @@ -16,39 +16,18 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" -_z_sample_t _z_sample_null(void) { - _z_sample_t s = { - .keyexpr = _z_keyexpr_null(), - .payload = _z_bytes_null(), - .encoding = _z_encoding_null(), - .timestamp = _z_timestamp_null(), - .kind = 0, - .qos = {0}, - .attachment = _z_bytes_null(), - }; - return s; -} - -bool _z_sample_check(const _z_sample_t *sample) { - return _z_keyexpr_check(&sample->keyexpr) || _z_bytes_check(&sample->payload) || - _z_bytes_check(&sample->attachment) || _z_encoding_check(&sample->encoding); -} - void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { _z_keyexpr_move(&dst->keyexpr, &src->keyexpr); _z_bytes_move(&dst->payload, &src->payload); _z_encoding_move(&dst->encoding, &src->encoding); + _z_timestamp_move(&dst->timestamp, &src->timestamp); _z_bytes_move(&dst->attachment, &src->attachment); - - dst->timestamp.time = src->timestamp.time; // FIXME: call the z_timestamp_move - dst->timestamp.id = src->timestamp.id; // FIXME: call the z_timestamp_move } void _z_sample_clear(_z_sample_t *sample) { _z_keyexpr_clear(&sample->keyexpr); - _z_bytes_drop(&sample->payload); _z_encoding_clear(&sample->encoding); - _z_timestamp_clear(&sample->timestamp); + _z_bytes_drop(&sample->payload); _z_bytes_drop(&sample->attachment); } @@ -77,38 +56,3 @@ _z_sample_t _z_sample_duplicate(const _z_sample_t *src) { _z_sample_copy(&dst, src); return dst; } - -#if Z_FEATURE_SUBSCRIPTION == 1 -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t attachment, z_reliability_t reliability) { - _z_sample_t s = _z_sample_null(); - s.keyexpr = _z_keyexpr_steal(key); - s.kind = kind; - if (timestamp != NULL) { - s.timestamp = _z_timestamp_duplicate(timestamp); - } - s.qos = qos; - s.reliability = reliability; - _z_bytes_copy(&s.payload, &payload); - _z_bytes_copy(&s.attachment, &attachment); - if (encoding != NULL) { - _z_encoding_move(&s.encoding, encoding); - } - return s; -} -#else -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t attachment, z_reliability_t reliability) { - _ZP_UNUSED(key); - _ZP_UNUSED(payload); - _ZP_UNUSED(timestamp); - _ZP_UNUSED(encoding); - _ZP_UNUSED(kind); - _ZP_UNUSED(qos); - _ZP_UNUSED(attachment); - _ZP_UNUSED(reliability); - return _z_sample_null(); -} -#endif diff --git a/src/net/session.c b/src/net/session.c index 0e8fcac4e..c70fdbabe 100644 --- a/src/net/session.c +++ b/src/net/session.c @@ -37,7 +37,7 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/uuid.h" -z_result_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t mode) { +static z_result_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t mode, int peer_op) { z_result_t ret = _Z_RES_OK; _z_id_t local_zid = _z_id_empty(); @@ -46,7 +46,7 @@ z_result_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t local_zid = _z_id_empty(); return ret; } - ret = _z_new_transport(&_Z_RC_IN_VAL(zn)->_tp, &local_zid, locator, mode); + ret = _z_new_transport(&_Z_RC_IN_VAL(zn)->_tp, &local_zid, locator, mode, peer_op); if (ret != _Z_RES_OK) { local_zid = _z_id_empty(); return ret; @@ -64,89 +64,89 @@ z_result_t _z_open(_z_session_rc_t *zn, _z_config_t *config) { if (opt_as_str != NULL) { _z_uuid_to_bytes(zid.id, opt_as_str); } + if (config == NULL) { + _Z_ERROR("A valid config is missing."); + return _Z_ERR_GENERIC; + } + int peer_op = _Z_PEER_OP_LISTEN; + _z_string_svec_t locators = _z_string_svec_make(0); + char *connect = _z_config_get(config, Z_CONFIG_CONNECT_KEY); + char *listen = _z_config_get(config, Z_CONFIG_LISTEN_KEY); + if (connect == NULL && listen == NULL) { // Scout if peer is not configured + opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_WHAT_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_SCOUTING_WHAT_DEFAULT; + } + z_what_t what = strtol(opt_as_str, NULL, 10); - if (config != NULL) { - _z_string_svec_t locators = _z_string_svec_make(0); - char *connect = _z_config_get(config, Z_CONFIG_CONNECT_KEY); - char *listen = _z_config_get(config, Z_CONFIG_LISTEN_KEY); - if (connect == NULL && listen == NULL) { // Scout if peer is not configured - opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_WHAT_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_SCOUTING_WHAT_DEFAULT; - } - z_what_t what = strtol(opt_as_str, NULL, 10); - - opt_as_str = _z_config_get(config, Z_CONFIG_MULTICAST_LOCATOR_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; - } - _z_string_t mcast_locator = _z_string_alias_str(opt_as_str); + opt_as_str = _z_config_get(config, Z_CONFIG_MULTICAST_LOCATOR_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; + } + _z_string_t mcast_locator = _z_string_alias_str(opt_as_str); - opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_TIMEOUT_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; - } - uint32_t timeout = (uint32_t)strtoul(opt_as_str, NULL, 10); + opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_TIMEOUT_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; + } + uint32_t timeout = (uint32_t)strtoul(opt_as_str, NULL, 10); - // Scout and return upon the first result - _z_hello_list_t *hellos = _z_scout_inner(what, zid, &mcast_locator, timeout, true); - if (hellos != NULL) { - _z_hello_t *hello = _z_hello_list_head(hellos); - _z_string_svec_copy(&locators, &hello->_locators); + // Scout and return upon the first result + _z_hello_list_t *hellos = _z_scout_inner(what, zid, &mcast_locator, timeout, true); + if (hellos != NULL) { + _z_hello_t *hello = _z_hello_list_head(hellos); + _z_string_svec_copy(&locators, &hello->_locators, true); + } + _z_hello_list_free(&hellos); + } else { + uint_fast8_t key = Z_CONFIG_CONNECT_KEY; + if (listen != NULL) { + if (connect == NULL) { + key = Z_CONFIG_LISTEN_KEY; + _zp_config_insert(config, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_PEER); + } else { + return _Z_ERR_GENERIC; } - _z_hello_list_free(&hellos); } else { - uint_fast8_t key = Z_CONFIG_CONNECT_KEY; - if (listen != NULL) { - if (connect == NULL) { - key = Z_CONFIG_LISTEN_KEY; - _zp_config_insert(config, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_PEER); - } else { - return _Z_ERR_GENERIC; - } - } - locators = _z_string_svec_make(1); - _z_string_t s = _z_string_copy_from_str(_z_config_get(config, key)); - _z_string_svec_append(&locators, &s); + peer_op = _Z_PEER_OP_OPEN; } + locators = _z_string_svec_make(1); + _z_string_t s = _z_string_copy_from_str(_z_config_get(config, key)); + _z_string_svec_append(&locators, &s, true); + } - ret = _Z_ERR_SCOUT_NO_RESULTS; - size_t len = _z_string_svec_len(&locators); - for (size_t i = 0; i < len; i++) { - ret = _Z_RES_OK; + ret = _Z_ERR_SCOUT_NO_RESULTS; + size_t len = _z_string_svec_len(&locators); + for (size_t i = 0; i < len; i++) { + ret = _Z_RES_OK; - _z_string_t *locator = _z_string_svec_get(&locators, i); - // @TODO: check invalid configurations - // For example, client mode in multicast links + _z_string_t *locator = _z_string_svec_get(&locators, i); + // @TODO: check invalid configurations + // For example, client mode in multicast links - // Check operation mode - char *s_mode = _z_config_get(config, Z_CONFIG_MODE_KEY); - z_whatami_t mode = Z_WHATAMI_CLIENT; // By default, zenoh-pico will operate as a client - if (s_mode != NULL) { - if (_z_str_eq(s_mode, Z_CONFIG_MODE_CLIENT) == true) { - mode = Z_WHATAMI_CLIENT; - } else if (_z_str_eq(s_mode, Z_CONFIG_MODE_PEER) == true) { - mode = Z_WHATAMI_PEER; - } else { - ret = _Z_ERR_CONFIG_INVALID_MODE; - } + // Check operation mode + char *s_mode = _z_config_get(config, Z_CONFIG_MODE_KEY); + z_whatami_t mode = Z_WHATAMI_CLIENT; // By default, zenoh-pico will operate as a client + if (s_mode != NULL) { + if (_z_str_eq(s_mode, Z_CONFIG_MODE_CLIENT) == true) { + mode = Z_WHATAMI_CLIENT; + } else if (_z_str_eq(s_mode, Z_CONFIG_MODE_PEER) == true) { + mode = Z_WHATAMI_PEER; + } else { + ret = _Z_ERR_CONFIG_INVALID_MODE; } + } + if (ret == _Z_RES_OK) { + ret = __z_open_inner(zn, locator, mode, peer_op); if (ret == _Z_RES_OK) { - ret = __z_open_inner(zn, locator, mode); - if (ret == _Z_RES_OK) { - break; - } - } else { - _Z_ERROR("Trying to configure an invalid mode."); + break; } + } else { + _Z_ERROR("Trying to configure an invalid mode."); } - _z_string_svec_clear(&locators); - } else { - _Z_ERROR("A valid config is missing."); - ret = _Z_ERR_GENERIC; } - + _z_string_svec_clear(&locators); return ret; } @@ -166,11 +166,8 @@ _z_config_t *_z_info(const _z_session_t *zn) { _z_config_t *ps = (_z_config_t *)z_malloc(sizeof(_z_config_t)); if (ps != NULL) { _z_config_init(ps); - _z_slice_t local_zid = _z_slice_alias_buf(zn->_local_zid.id, _z_id_len(zn->_local_zid)); - // TODO(sasahcmc): is it zero terminated??? - // rework it!!! - _z_string_t s = _z_string_convert_bytes(&local_zid); - _zp_config_insert(ps, Z_INFO_PID_KEY, _z_string_data(&s)); + _z_string_t s = _z_id_to_string(&zn->_local_zid); + _zp_config_insert_string(ps, Z_INFO_PID_KEY, &s); _z_string_clear(&s); switch (zn->_tp._type) { diff --git a/src/net/subscribe.c b/src/net/subscribe.c index 84960a0a2..12a83c6ac 100644 --- a/src/net/subscribe.c +++ b/src/net/subscribe.c @@ -31,7 +31,4 @@ void _z_subscriber_free(_z_subscriber_t **sub) { } } -bool _z_subscriber_check(const _z_subscriber_t *subscriber) { return !_Z_RC_IS_NULL(&subscriber->_zn); } -_z_subscriber_t _z_subscriber_null(void) { return (_z_subscriber_t){._entity_id = 0, ._zn = _z_session_weak_null()}; } - #endif diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 7564ef782..eea67422e 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -19,6 +19,7 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/pointers.h" #include "zenoh-pico/utils/result.h" /*------------------ uint8 -------------------*/ @@ -67,7 +68,7 @@ z_result_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *zbf) { if (_z_zbuf_can_read(zbf) == true) { *u8 = _z_zbuf_read(zbf); } else { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } @@ -182,6 +183,7 @@ z_result_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t uint64_t i = 0; z_result_t res = _z_zint64_decode_with_reader(&i, reader, context); if (res != _Z_RES_OK || i > SIZE_MAX) { + _Z_INFO("Reader decode failed"); res = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } else { *zint = (_z_zint_t)i; @@ -192,35 +194,51 @@ z_result_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t z_result_t _z_uint8_decode_reader(uint8_t *zint, void *context) { return _z_uint8_decode(zint, (_z_zbuf_t *)context); } z_result_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { - return _z_zint64_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); + *zint = 0; + uint8_t b = 0; + _Z_RETURN_IF_ERR(_z_uint8_decode(&b, zbf)); + + uint8_t i = 0; + while (((b & 0x80) != 0) && (i != 7 * (VLE_LEN - 1))) { + *zint = *zint | ((uint64_t)(b & 0x7f)) << i; + _Z_RETURN_IF_ERR(_z_uint8_decode(&b, zbf)); + i = i + (uint8_t)7; + } + *zint = *zint | ((uint64_t)b << i); + return _Z_RES_OK; } z_result_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *zbf) { - z_result_t ret = _Z_RES_OK; uint64_t buf; _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); - if (buf <= UINT16_MAX) { - *zint = (uint16_t)buf; - } else { - ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + if (buf > UINT16_MAX) { + _Z_INFO("Invalid zint16 value decoded"); + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - return ret; + *zint = (uint16_t)buf; + return _Z_RES_OK; } z_result_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *zbf) { - z_result_t ret = _Z_RES_OK; uint64_t buf; _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); - if (buf <= UINT32_MAX) { - *zint = (uint32_t)buf; - } else { - ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + if (buf > UINT32_MAX) { + _Z_INFO("Invalid zint32 value decoded"); + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - return ret; + *zint = (uint32_t)buf; + return _Z_RES_OK; } z_result_t _z_zsize_decode(_z_zint_t *zint, _z_zbuf_t *zbf) { - return _z_zsize_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); + uint64_t buf; + _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); + if (buf > SIZE_MAX) { + _Z_INFO("Invalide zsize value decoded"); + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + *zint = (_z_zint_t)buf; + return _Z_RES_OK; } /*------------------ uint8_array ------------------*/ @@ -255,7 +273,7 @@ z_result_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { *bs = _z_slice_alias_buf(_z_zbuf_get_rptr(zbf), bs->len); // Decode without allocating _z_zbuf_set_rpos(zbf, _z_zbuf_get_rpos(zbf) + bs->len); // Move the read position } else { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); bs->len = 0; bs->start = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; @@ -277,14 +295,16 @@ z_result_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice z_result_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(bs, zbf); } -z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { +z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf, _z_arc_slice_t *arcs) { + // Decode slice _z_slice_t s; _Z_RETURN_IF_ERR(_z_slice_decode(&s, zbf)); - if (_z_slice_is_alloced(&s)) { - return _z_bytes_from_slice(bs, s); - } else { - return _z_bytes_from_buf(bs, s.start, s.len); - } + // Calc offset + size_t offset = _z_ptr_u8_diff(s.start, _Z_RC_IN_VAL(&zbf->_slice)->start); + // Get ownership of subslice + *arcs = _z_arc_slice_wrap_slice_rc(&zbf->_slice, offset, s.len); + _z_bytes_alias_arc_slice(bs, arcs); + return _Z_RES_OK; } z_result_t _z_bytes_encode_val(_z_wbuf_t *wbf, const _z_bytes_t *bs) { @@ -326,11 +346,12 @@ z_result_t _z_str_decode(char **str, _z_zbuf_t *zbf) { } *str = tmp; } else { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); *str = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } else { + _Z_INFO("Size decode failed"); *str = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } @@ -344,22 +365,17 @@ z_result_t _z_string_encode(_z_wbuf_t *wbf, const _z_string_t *s) { } z_result_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf) { - *str = _z_string_null(); _z_zint_t len = 0; // Decode string length _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); // Check if we have enough bytes to read if (_z_zbuf_len(zbf) < len) { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - // Allocate space for the string terminator - *str = _z_string_preallocate(len); - if (str->_slice.start == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - // Read bytes - _z_zbuf_read_bytes(zbf, (uint8_t *)_z_string_data(str), 0, len); + // Alias string + *str = _z_string_alias_substr((const char *)_z_zbuf_get_rptr(zbf), len); + _z_zbuf_set_rpos(zbf, _z_zbuf_get_rpos(zbf) + len); return _Z_RES_OK; } diff --git a/src/protocol/codec/declarations.c b/src/protocol/codec/declarations.c index be68a2f81..905aad397 100644 --- a/src/protocol/codec/declarations.c +++ b/src/protocol/codec/declarations.c @@ -32,6 +32,7 @@ #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/session.h" #include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/logging.h" z_result_t _z_decl_ext_keyexpr_encode(_z_wbuf_t *wbf, _z_keyexpr_t ke, bool has_next_ext) { uint8_t header = _Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 0x0f | (has_next_ext ? _Z_FLAG_Z_Z : 0); @@ -162,7 +163,6 @@ z_result_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl) { case _Z_DECL_FINAL: { ret = _z_decl_final_encode(wbf); } break; - ; } return ret; } @@ -234,6 +234,7 @@ z_result_t _z_decl_commons_decode(_z_zbuf_t *zbf, uint8_t header, bool *has_exte _z_zint_t len; _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); if (_z_zbuf_len(zbf) < len) { + _Z_INFO("Not enough bytes to read"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } ke->_suffix = _z_string_preallocate(len); @@ -364,6 +365,7 @@ z_result_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf) { ret = _z_decl_final_decode(&decl->_body._decl_final, zbf, header); } break; default: { + _Z_INFO("Unknown token type"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index f2bdf6bfb..c11c62e46 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -104,7 +104,9 @@ z_result_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *zbf) { ret |= _z_zint64_decode(&ts->time, zbf); ret |= _z_id_decode_as_slice(&ts->id, zbf); - + if (ret == _Z_RES_OK) { + ts->valid = true; + } return ret; } @@ -200,6 +202,7 @@ z_result_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, info->_id.id, 0, zidlen); } else { + _Z_INFO("Not enough bytes to read"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -208,6 +211,7 @@ z_result_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { if (intbuf <= UINT32_MAX) { info->_entity_id = (uint32_t)intbuf; } else { + _Z_INFO("Invalid value decoded"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -216,6 +220,7 @@ z_result_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { if (intbuf <= UINT32_MAX) { info->_source_sn = (uint32_t)intbuf; } else { + _Z_INFO("Invalid value decoded"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -322,12 +327,11 @@ z_result_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { return ret; } -z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { z_result_t ret = _Z_RES_OK; switch (_Z_MID(header)) { case _Z_MID_Z_PUT: { pshb->_is_put = true; - pshb->_body._put = (_z_msg_put_t){0}; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_P_T)) { _Z_RETURN_IF_ERR(_z_timestamp_decode(&pshb->_body._put._commons._timestamp, zbf)); } @@ -338,13 +342,12 @@ z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t hea _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_push_body_decode_extensions, pshb)); } if (ret == _Z_RES_OK) { - _Z_RETURN_IF_ERR(_z_bytes_decode(&pshb->_body._put._payload, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_decode(&pshb->_body._put._payload, zbf, arcs)); } break; } case _Z_MID_Z_DEL: { pshb->_is_put = false; - pshb->_body._del = (_z_msg_del_t){0}; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_D_T)) { _Z_RETURN_IF_ERR(_z_timestamp_decode(&pshb->_body._put._commons._timestamp, zbf)); } @@ -364,10 +367,10 @@ z_result_t _z_put_encode(_z_wbuf_t *wbf, const _z_msg_put_t *put) { _z_push_body_t body = {._is_put = true, ._body = {._put = *put}}; return _z_push_body_encode(wbf, &body); } -z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { assert(_Z_MID(header) == _Z_MID_Z_PUT); _z_push_body_t body = {._is_put = true, ._body = {._put = *put}}; - z_result_t ret = _z_push_body_decode(&body, zbf, header); + z_result_t ret = _z_push_body_decode(&body, zbf, header, arcs); *put = body._body._put; return ret; } @@ -379,7 +382,7 @@ z_result_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del) { z_result_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header) { assert(_Z_MID(header) == _Z_MID_Z_DEL); _z_push_body_t body = {._is_put = false, ._body = {._del = *del}}; - z_result_t ret = _z_push_body_decode(&body, zbf, header); + z_result_t ret = _z_push_body_decode(&body, zbf, header, NULL); *del = body._body._del; return ret; } @@ -465,7 +468,6 @@ z_result_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { z_result_t _z_query_decode(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header) { _Z_DEBUG("Decoding _Z_MID_Z_QUERY"); - *msg = (_z_msg_query_t){0}; z_result_t ret = _Z_RES_OK; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Q_C)) { @@ -507,8 +509,7 @@ z_result_t _z_reply_decode_extension(_z_msg_ext_t *extension, void *ctx) { } return ret; } -z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header) { - *reply = (_z_msg_reply_t){0}; +z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R_C)) { _Z_RETURN_IF_ERR(_z_uint8_decode((uint8_t *)&reply->_consolidation, zbf)); } else { @@ -519,7 +520,7 @@ z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header } uint8_t put_header = 0; _Z_RETURN_IF_ERR(_z_uint8_decode(&put_header, zbf)); - _Z_RETURN_IF_ERR(_z_push_body_decode(&reply->_body, zbf, put_header)); + _Z_RETURN_IF_ERR(_z_push_body_decode(&reply->_body, zbf, put_header, arcs)); return _Z_RES_OK; } @@ -568,16 +569,14 @@ z_result_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { } return ret; } -z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header) { - *err = (_z_msg_err_t){0}; - +z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { if (_Z_HAS_FLAG(header, _Z_FLAG_Z_E_E)) { _Z_RETURN_IF_ERR(_z_encoding_decode(&err->_encoding, zbf)); } if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_err_decode_extension, err)); } - _Z_RETURN_IF_ERR(_z_bytes_decode(&err->_payload, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_decode(&err->_payload, zbf, arcs)); return _Z_RES_OK; } diff --git a/src/protocol/codec/network.c b/src/protocol/codec/network.c index 426c6d150..44cf9cde9 100644 --- a/src/protocol/codec/network.c +++ b/src/protocol/codec/network.c @@ -73,6 +73,7 @@ z_result_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { switch (_Z_EXT_FULL_ID(extension->_header)) { case _Z_MSG_EXT_ENC_ZINT | 0x01: { // QOS ext if (extension->_body._zint._val > UINT32_MAX) { + _Z_INFO("Invalid value decoded"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } msg->_qos = (_z_n_qos_t){._val = (uint8_t)extension->_body._zint._val}; @@ -91,9 +92,8 @@ z_result_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { return ret; } -z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { z_result_t ret = _Z_RES_OK; - *msg = (_z_n_msg_push_t){0}; msg->_qos = _Z_N_QOS_DEFAULT; ret |= _z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_N)); _z_keyexpr_set_mapping(&msg->_key, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE @@ -104,7 +104,7 @@ z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) if (ret == _Z_RES_OK) { uint8_t msgheader; _Z_RETURN_IF_ERR(_z_uint8_decode(&msgheader, zbf)); - _Z_RETURN_IF_ERR(_z_push_body_decode(&msg->_body, zbf, msgheader)); + _Z_RETURN_IF_ERR(_z_push_body_decode(&msg->_body, zbf, msgheader, arcs)); } return ret; @@ -172,6 +172,7 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { switch (_Z_EXT_FULL_ID(extension->_header)) { case 0x01 | _Z_MSG_EXT_ENC_ZINT: { // QOS ext if (extension->_body._zint._val > UINT8_MAX) { + _Z_INFO("Invalid value decoded"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } msg->_ext_qos = (_z_n_qos_t){._val = (uint8_t)extension->_body._zint._val}; @@ -185,6 +186,7 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { case 0x04 | _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M: { msg->_ext_target = (uint8_t)extension->_body._zint._val; if (msg->_ext_target > 2) { + _Z_INFO("Invalid value decoded"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } break; @@ -204,8 +206,7 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { } return _Z_RES_OK; } -z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint8_t header) { - *msg = (_z_n_msg_request_t){0}; +z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint8_t header, _z_arc_slice_t *arcs) { msg->_ext_qos = _Z_N_QOS_DEFAULT; _Z_RETURN_IF_ERR(_z_zsize_decode(&msg->_rid, zbf)); _Z_RETURN_IF_ERR(_z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_REQUEST_N))); @@ -223,13 +224,14 @@ z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint } break; case _Z_MID_Z_PUT: { msg->_tag = _Z_REQUEST_PUT; - _Z_RETURN_IF_ERR(_z_put_decode(&msg->_body._put, zbf, zheader)); + _Z_RETURN_IF_ERR(_z_put_decode(&msg->_body._put, zbf, zheader, arcs)); } break; case _Z_MID_Z_DEL: { msg->_tag = _Z_REQUEST_DEL; _Z_RETURN_IF_ERR(_z_del_decode(&msg->_body._del, zbf, zheader)); } break; default: + _Z_INFO("Unknown request type received: %d", _Z_MID(zheader)); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } return _Z_RES_OK; @@ -332,9 +334,8 @@ z_result_t _z_response_decode_extension(_z_msg_ext_t *extension, void *ctx) { return ret; } -z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { _Z_DEBUG("Decoding _Z_MID_N_RESPONSE"); - *msg = (_z_n_msg_response_t){0}; msg->_ext_qos = _Z_N_QOS_DEFAULT; z_result_t ret = _Z_RES_OK; _z_keyexpr_set_mapping(&msg->_key, _Z_HAS_FLAG(header, _Z_FLAG_N_RESPONSE_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE @@ -351,12 +352,12 @@ z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t switch (_Z_MID(inner_header)) { case _Z_MID_Z_REPLY: { msg->_tag = _Z_RESPONSE_BODY_REPLY; - ret = _z_reply_decode(&msg->_body._reply, zbf, inner_header); + ret = _z_reply_decode(&msg->_body._reply, zbf, inner_header, arcs); break; } case _Z_MID_Z_ERR: { msg->_tag = _Z_RESPONSE_BODY_ERR; - ret = _z_err_decode(&msg->_body._err, zbf, inner_header); + ret = _z_err_decode(&msg->_body._err, zbf, inner_header, arcs); break; } default: { @@ -380,8 +381,6 @@ z_result_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_fina z_result_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, uint8_t header) { (void)(header); - - *msg = (_z_n_msg_response_final_t){0}; z_result_t ret = _Z_RES_OK; ret |= _z_zsize_decode(&msg->_request_id, zbf); if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { @@ -440,7 +439,6 @@ z_result_t _z_declare_decode_extensions(_z_msg_ext_t *extension, void *ctx) { return _Z_RES_OK; } z_result_t _z_declare_decode(_z_n_msg_declare_t *decl, _z_zbuf_t *zbf, uint8_t header) { - *decl = (_z_n_msg_declare_t){0}; decl->_ext_qos = _Z_N_QOS_DEFAULT; // Retrieve interest id if (_Z_HAS_FLAG(header, _Z_FLAG_N_DECLARE_I)) { @@ -515,7 +513,7 @@ z_result_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t return _Z_ERR_GENERIC; } } -z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) { +z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_t *arcs) { uint8_t header; _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); switch (_Z_MID(header)) { @@ -525,15 +523,15 @@ z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) } break; case _Z_MID_N_PUSH: { msg->_tag = _Z_N_PUSH; - return _z_push_decode(&msg->_body._push, zbf, header); + return _z_push_decode(&msg->_body._push, zbf, header, arcs); } break; case _Z_MID_N_REQUEST: { msg->_tag = _Z_N_REQUEST; - return _z_request_decode(&msg->_body._request, zbf, header); + return _z_request_decode(&msg->_body._request, zbf, header, arcs); } break; case _Z_MID_N_RESPONSE: { msg->_tag = _Z_N_RESPONSE; - return _z_response_decode(&msg->_body._response, zbf, header); + return _z_response_decode(&msg->_body._response, zbf, header, arcs); } break; case _Z_MID_N_RESPONSE_FINAL: { msg->_tag = _Z_N_RESPONSE_FINAL; @@ -544,6 +542,7 @@ z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) return _z_n_interest_decode(&msg->_body._interest, zbf, header); } break; default: + _Z_INFO("Unknown message type received: %d", _Z_MID(header)); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index 7eff8715b..5e07d5fea 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -120,6 +120,7 @@ z_result_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); } else { + _Z_INFO("Invalid zid length received"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -200,6 +201,7 @@ z_result_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); } else { + _Z_INFO("Invalid zid length received"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -219,7 +221,7 @@ z_result_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_INIT_A) == true)) { ret |= _z_slice_decode(&msg->_cookie, zbf); } else { - msg->_cookie = _z_slice_empty(); + msg->_cookie = _z_slice_null(); } if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { @@ -264,10 +266,10 @@ z_result_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header) if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_A) == false)) { ret |= _z_slice_decode(&msg->_cookie, zbf); if (ret != _Z_RES_OK) { - msg->_cookie = _z_slice_empty(); + msg->_cookie = _z_slice_null(); } } else { - msg->_cookie = _z_slice_empty(); + msg->_cookie = _z_slice_null(); } if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x02); @@ -337,50 +339,110 @@ z_result_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_ ret = _Z_ERR_MESSAGE_SERIALIZATION_FAILED; } if (ret == _Z_RES_OK) { - size_t len = _z_network_message_vec_len(&msg->_messages); + size_t len = _z_network_message_svec_len(&msg->_messages); for (size_t i = 0; i < len; i++) { - _Z_RETURN_IF_ERR(_z_network_message_encode(wbf, _z_network_message_vec_get(&msg->_messages, i))) + _Z_RETURN_IF_ERR(_z_network_message_encode(wbf, _z_network_message_svec_get(&msg->_messages, i))) } } return ret; } -z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header) { +static void _z_frame_update_arcs_msg_pool(_z_network_message_svec_t *msg_pool, _z_arc_slice_svec_t *arc_pool) { + for (size_t i = 0; i < arc_pool->_len; i++) { + _z_network_message_t *nm = _z_network_message_svec_get(msg_pool, i); + switch (nm->_tag) { + case _Z_N_PUSH: { + if (!nm->_body._push._body._is_put) { + continue; + } + _z_bytes_alias_arc_slice(&nm->_body._push._body._body._put._payload, + _z_arc_slice_svec_get(arc_pool, i)); + } break; + case _Z_N_REQUEST: { + if (nm->_body._request._tag != _Z_REQUEST_PUT) { + continue; + } + _z_bytes_alias_arc_slice(&nm->_body._request._body._put._payload, _z_arc_slice_svec_get(arc_pool, i)); + } break; + case _Z_N_RESPONSE: { + switch (nm->_body._response._tag) { + case _Z_RESPONSE_BODY_REPLY: + if (!nm->_body._response._body._reply._body._is_put) { + continue; + } + _z_bytes_alias_arc_slice(&nm->_body._response._body._reply._body._body._put._payload, + _z_arc_slice_svec_get(arc_pool, i)); + break; + + case _Z_RESPONSE_BODY_ERR: + _z_bytes_alias_arc_slice(&nm->_body._response._body._err._payload, + _z_arc_slice_svec_get(arc_pool, i)); + break; + + default: + continue; + } + } + default: + continue; + } + } +} + +z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool) { z_result_t ret = _Z_RES_OK; *msg = (_z_t_msg_frame_t){0}; - ret |= _z_zsize_decode(&msg->_sn, zbf); - if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { - ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x04); - } - if (ret == _Z_RES_OK) { - msg->_messages = _z_network_message_vec_make(_ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE); - while (_z_zbuf_len(zbf) > 0) { - // Mark the reading position of the iobfer - size_t r_pos = _z_zbuf_get_rpos(zbf); - _z_network_message_t *nm = (_z_network_message_t *)z_malloc(sizeof(_z_network_message_t)); - memset(nm, 0, sizeof(_z_network_message_t)); - ret |= _z_network_message_decode(nm, zbf); - if (ret == _Z_RES_OK) { - _z_network_message_vec_append(&msg->_messages, nm); - } else { - _z_n_msg_free(&nm); - - _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer - - // FIXME: Check for the return error, since not all of them means a decoding error - // in this particular case. As of now, we roll-back the reading position - // and return to the Zenoh transport-level decoder. - // https://github.com/eclipse-zenoh/zenoh-pico/pull/132#discussion_r1045593602 - if ((ret & _Z_ERR_MESSAGE_ZENOH_UNKNOWN) == _Z_ERR_MESSAGE_ZENOH_UNKNOWN) { - ret = _Z_RES_OK; - } - break; + _Z_RETURN_IF_ERR(_z_zsize_decode(&msg->_sn, zbf)); + if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x04)); + } + // Init message vector + msg_pool->_len = 0; + arc_pool->_len = 0; + _z_network_message_svec_init(msg_pool, 0); + size_t msg_idx = 0; + while (_z_zbuf_len(zbf) > 0) { + // Expand message vector if needed + if (msg_idx >= msg_pool->_capacity) { + _Z_RETURN_IF_ERR(_z_network_message_svec_expand(msg_pool, false)); + _z_network_message_svec_init(msg_pool, msg_pool->_len); + } + // Expand arc pool if needed + if (msg_idx >= arc_pool->_capacity) { + _Z_RETURN_IF_ERR(_z_arc_slice_svec_expand(arc_pool, false)); + // Update arcs references in msg pool + _z_frame_update_arcs_msg_pool(msg_pool, arc_pool); + } + // Mark the reading position of the iobfer + size_t r_pos = _z_zbuf_get_rpos(zbf); + // Retrieve storage in resource pool + _z_network_message_t *nm = _z_network_message_svec_get_mut(msg_pool, msg_idx); + _z_arc_slice_t *arcs = _z_arc_slice_svec_get_mut(arc_pool, msg_idx); + // Decode message + ret = _z_network_message_decode(nm, zbf, arcs); + if (ret != _Z_RES_OK) { + _z_network_message_svec_reset(msg_pool); + _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer + + // FIXME: Check for the return error, since not all of them means a decoding error + // in this particular case. As of now, we roll-back the reading position + // and return to the Zenoh transport-level decoder. + // https://github.com/eclipse-zenoh/zenoh-pico/pull/132#discussion_r1045593602 + if ((ret & _Z_ERR_MESSAGE_ZENOH_UNKNOWN) == _Z_ERR_MESSAGE_ZENOH_UNKNOWN) { + ret = _Z_RES_OK; } + return ret; } + arc_pool->_len++; + msg_pool->_len++; + msg_idx++; } - return ret; + // Alias network message svec in frame struct + msg->_messages = _z_network_message_svec_alias(msg_pool); + return _Z_RES_OK; } /*------------------ Fragment Message ------------------*/ @@ -408,9 +470,7 @@ z_result_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x05); } - - _z_slice_t slice = _z_slice_alias_buf((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf)); - _z_slice_copy(&msg->_payload, &slice); + msg->_payload = _z_slice_alias_buf((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf)); zbf->_ios._r_pos = zbf->_ios._w_pos; return ret; @@ -481,7 +541,8 @@ z_result_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_messag return ret; } -z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf) { +z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool) { z_result_t ret = _Z_RES_OK; ret |= _z_uint8_decode(&msg->_header, zbf); // Decode the header @@ -489,7 +550,7 @@ z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *z uint8_t mid = _Z_MID(msg->_header); switch (mid) { case _Z_MID_T_FRAME: { - ret |= _z_frame_decode(&msg->_body._frame, zbf, msg->_header); + ret |= _z_frame_decode(&msg->_body._frame, zbf, msg->_header, arc_pool, msg_pool); } break; case _Z_MID_T_FRAGMENT: { ret |= _z_fragment_decode(&msg->_body._fragment, zbf, msg->_header); diff --git a/src/protocol/config.c b/src/protocol/config.c index dcdb4f904..1cfcff9c3 100644 --- a/src/protocol/config.c +++ b/src/protocol/config.c @@ -19,6 +19,7 @@ #include #include +#include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/pointers.h" z_result_t _z_config_init(_z_config_t *ps) { @@ -37,6 +38,18 @@ z_result_t _zp_config_insert(_z_config_t *ps, uint8_t key, const char *value) { return ret; } +z_result_t _zp_config_insert_string(_z_config_t *ps, uint8_t key, const _z_string_t *value) { + z_result_t ret = _Z_RES_OK; + char *str = _z_str_from_string_clone(value); + char *res = _z_str_intmap_insert(ps, key, str); + if (strcmp(res, str) != 0) { + ret = _Z_ERR_CONFIG_FAILED_INSERT; + } + z_free(str); + + return ret; +} + char *_z_config_get(const _z_config_t *ps, uint8_t key) { return _z_str_intmap_get(ps, key); } /*------------------ int-string map ------------------*/ diff --git a/src/protocol/core.c b/src/protocol/core.c index ed0479cc5..da1ef9ef8 100644 --- a/src/protocol/core.c +++ b/src/protocol/core.c @@ -27,6 +27,8 @@ #define _Z_ID_LEN (16) +const _z_id_t empty_id = {0}; + uint8_t _z_id_len(_z_id_t id) { uint8_t len = _Z_ID_LEN; while (len > 0) { @@ -38,38 +40,6 @@ uint8_t _z_id_len(_z_id_t id) { } return len; } -bool _z_id_check(_z_id_t id) { - bool ret = false; - for (int i = 0; !ret && i < _Z_ID_LEN; i++) { - ret |= id.id[i] != 0; - } - return ret; -} -_z_id_t _z_id_empty(void) { - return (_z_id_t){.id = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }}; -} - -_z_source_info_t _z_source_info_null(void) { - return (_z_source_info_t){._source_sn = 0, ._entity_id = 0, ._id = _z_id_empty()}; -} -_z_timestamp_t _z_timestamp_null(void) { return (_z_timestamp_t){.id = _z_id_empty(), .time = 0}; } uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos) { const uint64_t FRAC_PER_SEC = (uint64_t)1 << 32; @@ -79,7 +49,6 @@ uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos) { return ((uint64_t)seconds << 32) | fractions; } -_z_value_t _z_value_null(void) { return (_z_value_t){.payload = _z_bytes_null(), .encoding = _z_encoding_null()}; } _z_value_t _z_value_steal(_z_value_t *value) { _z_value_t ret = *value; *value = _z_value_null(); @@ -94,17 +63,13 @@ z_result_t _z_value_copy(_z_value_t *dst, const _z_value_t *src) { z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src) { *dst = _z_hello_null(); - _Z_RETURN_IF_ERR(_z_string_svec_copy(&dst->_locators, &src->_locators) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY); + _Z_RETURN_IF_ERR(_z_string_svec_copy(&dst->_locators, &src->_locators, true)); dst->_version = src->_version; dst->_whatami = src->_whatami; memcpy(&dst->_zid.id, &src->_zid.id, _Z_ID_LEN); return _Z_RES_OK; } -_z_hello_t _z_hello_null(void) { - return (_z_hello_t){._zid = _z_id_empty(), ._version = 0, ._whatami = 0x0, ._locators = _z_string_svec_make(0)}; -} - void _z_value_move(_z_value_t *dst, _z_value_t *src) { _z_encoding_move(&dst->encoding, &src->encoding); _z_bytes_move(&dst->payload, &src->payload); diff --git a/src/protocol/definitions/declarations.c b/src/protocol/definitions/declarations.c index 878f14f6d..df693f2a1 100644 --- a/src/protocol/definitions/declarations.c +++ b/src/protocol/definitions/declarations.c @@ -71,7 +71,7 @@ _z_declaration_t _z_make_undecl_subscriber(uint32_t id, _Z_OPTIONAL const _z_key return (_z_declaration_t){ ._tag = _Z_UNDECL_SUBSCRIBER, ._body = {._undecl_subscriber = { - ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; + ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(key)}}}; } _z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, bool complete, uint16_t distance) { @@ -85,7 +85,7 @@ _z_declaration_t _z_make_undecl_queryable(uint32_t id, _Z_OPTIONAL const _z_keye return (_z_declaration_t){ ._tag = _Z_UNDECL_QUERYABLE, ._body = {._undecl_queryable = { - ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; + ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(key)}}}; } _z_declaration_t _z_make_decl_token(_Z_MOVE(_z_keyexpr_t) key, uint32_t id) { return (_z_declaration_t){._tag = _Z_DECL_TOKEN, @@ -98,22 +98,12 @@ _z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL const _z_keyexpr_ return (_z_declaration_t){ ._tag = _Z_UNDECL_TOKEN, ._body = {._undecl_token = {._id = id, - ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; + ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(key)}}}; } _z_declaration_t _z_make_decl_final(void) { return (_z_declaration_t){._tag = _Z_DECL_FINAL, ._body = {._decl_final = {0}}}; } -_z_decl_kexpr_t _z_decl_kexpr_null(void) { return (_z_decl_kexpr_t){0}; } -_z_decl_subscriber_t _z_decl_subscriber_null(void) { return (_z_decl_subscriber_t){0}; } -_z_decl_queryable_t _z_decl_queryable_null(void) { return (_z_decl_queryable_t){0}; } -_z_decl_token_t _z_decl_token_null(void) { return (_z_decl_token_t){0}; } -_z_undecl_kexpr_t _z_undecl_kexpr_null(void) { return (_z_undecl_kexpr_t){0}; } -_z_undecl_subscriber_t _z_undecl_subscriber_null(void) { return (_z_undecl_subscriber_t){0}; } -_z_undecl_queryable_t _z_undecl_queryable_null(void) { return (_z_undecl_queryable_t){0}; } -_z_undecl_token_t _z_undecl_token_null(void) { return (_z_undecl_token_t){0}; } -_z_decl_final_t _z_decl_final_null(void) { return (_z_decl_final_t){0}; } - void _z_decl_fix_mapping(_z_declaration_t *msg, uint16_t mapping) { switch (msg->_tag) { case _Z_DECL_KEXPR: { diff --git a/src/protocol/definitions/interest.c b/src/protocol/definitions/interest.c index 7c0254ee7..cfdc1795e 100644 --- a/src/protocol/definitions/interest.c +++ b/src/protocol/definitions/interest.c @@ -33,5 +33,3 @@ _z_interest_t _z_make_interest_final(uint32_t id) { .flags = 0, }; } - -_z_interest_t _z_interest_null(void) { return (_z_interest_t){0}; } diff --git a/src/protocol/definitions/message.c b/src/protocol/definitions/message.c index 3001b3372..e8f967e62 100644 --- a/src/protocol/definitions/message.c +++ b/src/protocol/definitions/message.c @@ -23,7 +23,7 @@ void _z_msg_reply_clear(_z_msg_reply_t *msg) { _z_push_body_clear(&msg->_body); } void _z_msg_put_clear(_z_msg_put_t *msg) { - _z_bytes_drop(&msg->_payload); + _z_bytes_aliased_drop(&msg->_payload); _z_bytes_drop(&msg->_attachment); _z_encoding_clear(&msg->_encoding); _z_timestamp_clear(&msg->_commons._timestamp); @@ -44,5 +44,5 @@ void _z_msg_query_clear(_z_msg_query_t *msg) { } void _z_msg_err_clear(_z_msg_err_t *err) { _z_encoding_clear(&err->_encoding); - _z_bytes_drop(&err->_payload); + _z_bytes_aliased_drop(&err->_payload); } diff --git a/src/protocol/definitions/network.c b/src/protocol/definitions/network.c index 177e0bc0a..1364ac039 100644 --- a/src/protocol/definitions/network.c +++ b/src/protocol/definitions/network.c @@ -72,10 +72,15 @@ _z_push_body_t _z_push_body_steal(_z_push_body_t *msg) { *msg = _z_push_body_null(); return ret; } -_z_push_body_t _z_push_body_null(void) { - return (_z_push_body_t){ - ._is_put = false, - ._body._del._commons = {._timestamp = _z_timestamp_null(), ._source_info = _z_source_info_null()}}; + +static z_result_t _z_push_body_copy(_z_push_body_t *dst, const _z_push_body_t *src) { + if (src->_is_put) { + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._put._attachment, &src->_body._put._attachment)); + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._put._payload, &src->_body._put._payload)); + } else { + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._del._attachment, &src->_body._del._attachment)); + } + return _Z_RES_OK; } void _z_n_msg_response_final_clear(_z_n_msg_response_final_t *msg) { (void)(msg); } @@ -229,6 +234,124 @@ _z_network_message_t _z_n_msg_make_interest(_z_interest_t interest) { }; } +static z_result_t _z_n_msg_push_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_body._push._key, &src->_body._push._key)); + return _z_push_body_copy(&dst->_body._push._body, &src->_body._push._body); +} + +static z_result_t _z_n_msg_request_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_body._request._key, &src->_body._request._key)); + switch (src->_body._request._tag) { + case _Z_REQUEST_QUERY: + _Z_RETURN_IF_ERR(_z_slice_copy(&dst->_body._request._body._query._parameters, + &src->_body._request._body._query._parameters)); + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._query._ext_attachment, + &src->_body._request._body._query._ext_attachment)); + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._query._ext_value.payload, + &src->_body._request._body._query._ext_value.payload)); + break; + case _Z_REQUEST_PUT: + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._put._attachment, + &src->_body._request._body._put._attachment)); + _Z_RETURN_IF_ERR( + _z_bytes_copy(&dst->_body._request._body._put._payload, &src->_body._request._body._put._payload)); + break; + case _Z_REQUEST_DEL: + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._del._attachment, + &src->_body._request._body._del._attachment)); + break; + } + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_response_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_body._response._key, &src->_body._response._key)); + switch (src->_body._response._tag) { + case _Z_RESPONSE_BODY_REPLY: + _Z_RETURN_IF_ERR( + _z_push_body_copy(&dst->_body._response._body._reply._body, &src->_body._response._body._reply._body)); + break; + case _Z_RESPONSE_BODY_ERR: + _Z_RETURN_IF_ERR( + _z_bytes_copy(&dst->_body._response._body._err._payload, &src->_body._response._body._err._payload)); + break; + } + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_response_final_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_declare_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + const _z_declaration_t *src_decl = &src->_body._declare._decl; + _z_declaration_t *dst_decl = &dst->_body._declare._decl; + switch (src_decl->_tag) { + case _Z_DECL_KEXPR: { + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst_decl->_body._decl_kexpr._keyexpr, &src_decl->_body._decl_kexpr._keyexpr)); + } break; + case _Z_DECL_SUBSCRIBER: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._decl_subscriber._keyexpr, + &src_decl->_body._decl_subscriber._keyexpr)); + } break; + case _Z_UNDECL_SUBSCRIBER: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._undecl_subscriber._ext_keyexpr, + &src_decl->_body._undecl_subscriber._ext_keyexpr)); + } break; + case _Z_DECL_QUERYABLE: { + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst_decl->_body._decl_queryable._keyexpr, &src_decl->_body._decl_queryable._keyexpr)); + } break; + case _Z_UNDECL_QUERYABLE: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._undecl_queryable._ext_keyexpr, + &src_decl->_body._undecl_queryable._ext_keyexpr)); + } break; + case _Z_DECL_TOKEN: { + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst_decl->_body._decl_token._keyexpr, &src_decl->_body._decl_token._keyexpr)); + } break; + case _Z_UNDECL_TOKEN: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._undecl_token._ext_keyexpr, + &src_decl->_body._undecl_token._ext_keyexpr)); + } break; + default: + break; + } + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_interest_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst->_body._interest._interest._keyexpr, &src->_body._interest._interest._keyexpr)); + return _Z_RES_OK; +} + +z_result_t _z_n_msg_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + switch (src->_tag) { + case _Z_N_PUSH: + return _z_n_msg_push_copy(dst, src); + case _Z_N_REQUEST: + return _z_n_msg_request_copy(dst, src); + case _Z_N_RESPONSE: + return _z_n_msg_response_copy(dst, src); + case _Z_N_RESPONSE_FINAL: + return _z_n_msg_response_final_copy(dst, src); + case _Z_N_DECLARE: + return _z_n_msg_declare_copy(dst, src); + case _Z_N_INTEREST: + return _z_n_msg_interest_copy(dst, src); + default: + return _Z_ERR_ENTITY_UNKNOWN; + } +} + void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping) { switch (msg->_tag) { case _Z_N_DECLARE: { diff --git a/src/protocol/definitions/transport.c b/src/protocol/definitions/transport.c index 2af77cb97..fa910b771 100644 --- a/src/protocol/definitions/transport.c +++ b/src/protocol/definitions/transport.c @@ -40,7 +40,7 @@ void _z_t_msg_close_clear(_z_t_msg_close_t *msg) { (void)(msg); } void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg) { (void)(msg); } -void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { _z_network_message_vec_clear(&msg->_messages); } +void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { (void)(msg); } void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg) { _z_slice_clear(&msg->_payload); } @@ -216,7 +216,7 @@ _z_transport_message_t _z_t_msg_make_keep_alive(void) { return msg; } -_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages, +_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_svec_t messages, z_reliability_t reliability) { _z_transport_message_t msg; msg._header = _Z_MID_T_FRAME; @@ -241,14 +241,14 @@ _z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t _Z_SET_FLAG(msg._header, _Z_FLAG_T_FRAME_R); } - msg._body._frame._messages = _z_network_message_vec_make(0); + msg._body._frame._messages = _z_network_message_svec_null(); return msg; } /*------------------ Fragment Message ------------------*/ _z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, z_reliability_t reliability, bool is_last) { - return _z_t_msg_make_fragment(sn, _z_slice_empty(), reliability, is_last); + return _z_t_msg_make_fragment(sn, _z_slice_null(), reliability, is_last); } _z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_slice_t payload, z_reliability_t reliability, bool is_last) { @@ -307,7 +307,7 @@ void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_ void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg) { clone->_sn = msg->_sn; - _z_network_message_vec_copy(&clone->_messages, &msg->_messages); + _z_network_message_svec_copy(&clone->_messages, &msg->_messages, false); } /*------------------ Transport Message ------------------*/ diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index c398bc766..8c6f6d39d 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -20,6 +20,7 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/pointers.h" #include "zenoh-pico/utils/result.h" @@ -35,6 +36,12 @@ _z_iosli_t _z_iosli_wrap(const uint8_t *buf, size_t length, size_t r_pos, size_t return ios; } +_z_iosli_t _z_iosli_steal(_z_iosli_t *ios) { + _z_iosli_t new_ios = *ios; + *ios = _z_iosli_null(); + return new_ios; +} + void __z_iosli_init(_z_iosli_t *ios, size_t capacity) { ios->_r_pos = 0; ios->_w_pos = 0; @@ -75,6 +82,13 @@ void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dst, size_t offset, size_t le ios->_r_pos = ios->_r_pos + length; } +void _z_iosli_copy_bytes(_z_iosli_t *dst, const _z_iosli_t *src) { + size_t length = _z_iosli_readable(src); + assert(_z_iosli_readable(dst) >= length); + (void)memcpy(dst->_buf + dst->_w_pos, src->_buf + src->_r_pos, length); + dst->_w_pos += length; +} + uint8_t _z_iosli_get(const _z_iosli_t *ios, size_t pos) { assert(pos < ios->_capacity); return ios->_buf[pos]; @@ -160,8 +174,18 @@ _z_iosli_t *_z_iosli_clone(const _z_iosli_t *src) { /*------------------ ZBuf ------------------*/ _z_zbuf_t _z_zbuf_make(size_t capacity) { - _z_zbuf_t zbf; + _z_zbuf_t zbf = _z_zbuf_null(); zbf._ios = _z_iosli_make(capacity); + if (_z_zbuf_capacity(&zbf) == 0) { + return zbf; + } + _z_slice_t s = _z_slice_from_buf_custom_deleter(zbf._ios._buf, zbf._ios._capacity, _z_delete_context_default()); + zbf._slice = _z_slice_simple_rc_new_from_val(&s); + if (_Z_RC_IS_NULL(&zbf._slice)) { + _Z_ERROR("slice rc creation failed"); + _z_iosli_clear(&zbf._ios); + } + zbf._ios._is_alloc = false; return zbf; } @@ -169,6 +193,7 @@ _z_zbuf_t _z_zbuf_view(_z_zbuf_t *zbf, size_t length) { assert(_z_iosli_readable(&zbf->_ios) >= length); _z_zbuf_t v; v._ios = _z_iosli_wrap(_z_zbuf_get_rptr(zbf), length, 0, length); + v._slice = zbf->_slice; return v; } _z_zbuf_t _z_slice_as_zbuf(_z_slice_t slice) { @@ -188,6 +213,8 @@ uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf) { } size_t _z_zbuf_len(const _z_zbuf_t *zbf) { return _z_iosli_readable(&zbf->_ios); } +void _z_zbuf_copy_bytes(_z_zbuf_t *dst, const _z_zbuf_t *src) { _z_iosli_copy_bytes(&dst->_ios, &src->_ios); } + bool _z_zbuf_can_read(const _z_zbuf_t *zbf) { return _z_zbuf_len(zbf) > (size_t)0; } uint8_t _z_zbuf_read(_z_zbuf_t *zbf) { return _z_iosli_read(&zbf->_ios); } @@ -218,7 +245,10 @@ uint8_t *_z_zbuf_get_wptr(const _z_zbuf_t *zbf) { return zbf->_ios._buf + zbf->_ void _z_zbuf_reset(_z_zbuf_t *zbf) { _z_iosli_reset(&zbf->_ios); } -void _z_zbuf_clear(_z_zbuf_t *zbf) { _z_iosli_clear(&zbf->_ios); } +void _z_zbuf_clear(_z_zbuf_t *zbf) { + _z_iosli_clear(&zbf->_ios); + _z_slice_simple_rc_drop(&zbf->_slice); +} void _z_zbuf_compact(_z_zbuf_t *zbf) { if ((zbf->_ios._r_pos != 0) || (zbf->_ios._w_pos != 0)) { @@ -260,15 +290,8 @@ size_t _z_wbuf_len_iosli(const _z_wbuf_t *wbf) { return _z_iosli_vec_len(&wbf->_ _z_wbuf_t _z_wbuf_make(size_t capacity, bool is_expandable) { _z_wbuf_t wbf; - if (is_expandable == true) { - // Preallocate 4 slots, this is usually what we expect - // when fragmenting a zenoh data message with attachment - wbf._ioss = _z_iosli_vec_make(4); - _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); - } else { - wbf._ioss = _z_iosli_vec_make(1); - _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); - } + wbf._ioss = _z_iosli_vec_make(1); + _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); wbf._w_idx = 0; // This __must__ come after adding ioslices to reset w_idx wbf._r_idx = 0; wbf._expansion_step = is_expandable ? capacity : 0; @@ -517,6 +540,23 @@ _z_zbuf_t _z_wbuf_to_zbuf(const _z_wbuf_t *wbf) { return zbf; } +_z_zbuf_t _z_wbuf_moved_as_zbuf(_z_wbuf_t *wbf) { + // Can only move single buffer wbuf + assert(_z_iosli_vec_len(&wbf->_ioss) == 1); + + _z_zbuf_t zbf = _z_zbuf_null(); + _z_iosli_t *ios = _z_wbuf_get_iosli(wbf, 0); + zbf._ios = _z_iosli_steal(ios); + _z_slice_t s = _z_slice_from_buf_custom_deleter(zbf._ios._buf, zbf._ios._capacity, _z_delete_context_default()); + zbf._slice = _z_slice_simple_rc_new_from_val(&s); + if (_Z_RC_IS_NULL(&zbf._slice)) { + _Z_ERROR("slice rc creation failed"); + } + zbf._ios._is_alloc = false; + _z_wbuf_clear(wbf); + return zbf; +} + z_result_t _z_wbuf_siphon(_z_wbuf_t *dst, _z_wbuf_t *src, size_t length) { z_result_t ret = _Z_RES_OK; size_t llength = length; @@ -569,7 +609,10 @@ void _z_wbuf_reset(_z_wbuf_t *wbf) { } } -void _z_wbuf_clear(_z_wbuf_t *wbf) { _z_iosli_vec_clear(&wbf->_ioss); } +void _z_wbuf_clear(_z_wbuf_t *wbf) { + _z_iosli_vec_clear(&wbf->_ioss); + *wbf = _z_wbuf_null(); +} void _z_wbuf_free(_z_wbuf_t **wbf) { _z_wbuf_t *ptr = *wbf; diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index a097b2c40..15e1beee0 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -36,7 +36,7 @@ _z_keyexpr_t _z_keyexpr_from_string(uint16_t rid, _z_string_t *str) { return (_z_keyexpr_t){ ._id = rid, ._mapping = _z_keyexpr_mapping(_Z_KEYEXPR_MAPPING_LOCAL), - ._suffix = (_z_string_check(str)) ? _z_string_alias(str) : _z_string_null(), + ._suffix = (_z_string_check(str)) ? _z_string_alias(*str) : _z_string_null(), }; } @@ -59,9 +59,9 @@ z_result_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { return _Z_RES_OK; } -_z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src) { +_z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src) { _z_keyexpr_t dst; - _z_keyexpr_copy(&dst, &src); + _z_keyexpr_copy(&dst, src); return dst; } @@ -82,7 +82,6 @@ void _z_keyexpr_clear(_z_keyexpr_t *rk) { if (_z_keyexpr_has_suffix(rk)) { _z_string_clear(&rk->_suffix); } - rk->_suffix = _z_string_null(); } void _z_keyexpr_free(_z_keyexpr_t **rk) { @@ -103,16 +102,15 @@ bool _z_keyexpr_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { if (_z_keyexpr_mapping_id(left) != _z_keyexpr_mapping_id(right)) { return false; } - return _z_string_equals(&left->_suffix, &right->_suffix); -} - -_z_keyexpr_t _z_keyexpr_alias(_z_keyexpr_t src) { - _z_keyexpr_t alias = { - ._id = src._id, - ._mapping = src._mapping, - ._suffix = _z_string_alias(&src._suffix), - }; - return alias; + bool l_suffix = _z_keyexpr_has_suffix(left); + bool r_suffix = _z_keyexpr_has_suffix(right); + if (l_suffix != r_suffix) { + return false; + } + if (l_suffix && r_suffix) { + return _z_string_equals(&left->_suffix, &right->_suffix); + } + return true; } _z_keyexpr_t _z_keyexpr_alias_from_user_defined(_z_keyexpr_t src, bool try_declared) { diff --git a/src/session/interest.c b/src/session/interest.c index a16884ee7..8faa6cc2f 100644 --- a/src/session/interest.c +++ b/src/session/interest.c @@ -26,6 +26,7 @@ #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_INTEREST == 1 @@ -94,9 +95,9 @@ static _z_session_interest_rc_list_t *__unsafe_z_get_interest_by_key_and_flags(_ } static z_result_t _z_interest_send_decl_resource(_z_session_t *zn, uint32_t interest_id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_list_t *res_list = _z_resource_list_clone(zn->_local_resources); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); _z_resource_list_t *xs = res_list; while (xs != NULL) { _z_resource_t *res = _z_resource_list_head(xs); @@ -116,9 +117,9 @@ static z_result_t _z_interest_send_decl_resource(_z_session_t *zn, uint32_t inte #if Z_FEATURE_SUBSCRIPTION == 1 static z_result_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t interest_id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_list_t *sub_list = _z_subscription_rc_list_clone(zn->_local_subscriptions); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); _z_subscription_rc_list_t *xs = sub_list; while (xs != NULL) { _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); @@ -145,9 +146,9 @@ static z_result_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t in #if Z_FEATURE_QUERYABLE == 1 static z_result_t _z_interest_send_decl_queryable(_z_session_t *zn, uint32_t interest_id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_queryable_rc_list_t *qle_list = _z_session_queryable_rc_list_clone(zn->_local_queryable); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); _z_session_queryable_rc_list_t *xs = qle_list; while (xs != NULL) { _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); @@ -184,9 +185,9 @@ static z_result_t _z_interest_send_declare_final(_z_session_t *zn, uint32_t inte } _z_session_interest_rc_t *_z_get_interest_by_id(_z_session_t *zn, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_interest_rc_t *intr = __unsafe_z_get_interest_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return intr; } @@ -195,13 +196,13 @@ _z_session_interest_rc_t *_z_register_interest(_z_session_t *zn, _z_session_inte (int)_z_string_len(&intr->_key._suffix), _z_string_data(&intr->_key._suffix)); _z_session_interest_rc_t *ret = NULL; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); ret = (_z_session_interest_rc_t *)z_malloc(sizeof(_z_session_interest_rc_t)); if (ret != NULL) { *ret = _z_session_interest_rc_new_from_val(intr); zn->_local_interests = _z_session_interest_rc_list_push(zn->_local_interests, ret); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -228,7 +229,7 @@ static _z_keyexpr_t _unsafe_z_get_key_from_declare(_z_session_t *zn, uint32_t id while (xs != NULL) { _z_declare_data_t *decl = _z_declare_data_list_head(xs); if (_z_declare_data_eq(&comp, decl)) { - return _z_keyexpr_duplicate(decl->_key); + return _z_keyexpr_duplicate(&decl->_key); } xs = _z_declare_data_list_tail(xs); } @@ -269,17 +270,17 @@ z_result_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; } // Retrieve key - _zp_session_lock_mutex(zn); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, decl_key); + _z_session_mutex_lock(zn); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, decl_key, true); if (!_z_keyexpr_has_suffix(&key)) { - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return _Z_ERR_KEYEXPR_UNKNOWN; } // Register declare _unsafe_z_register_declare(zn, &key, msg.id, decl_type); // Retrieve interests _z_session_interest_rc_list_t *intrs = __unsafe_z_get_interest_by_key_and_flags(zn, flags, &key); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Parse session_interest list _z_session_interest_rc_list_t *xs = intrs; while (xs != NULL) { @@ -315,17 +316,17 @@ z_result_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration default: return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; } - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); // Retrieve declare data _z_keyexpr_t key = _unsafe_z_get_key_from_declare(zn, msg.id, decl_type); if (!_z_keyexpr_has_suffix(&key)) { - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return _Z_ERR_KEYEXPR_UNKNOWN; } _z_session_interest_rc_list_t *intrs = __unsafe_z_get_interest_by_key_and_flags(zn, flags, &key); // Remove declare _unsafe_z_unregister_declare(zn, msg.id, decl_type); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Parse session_interest list _z_session_interest_rc_list_t *xs = intrs; @@ -343,25 +344,25 @@ z_result_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration } void _z_unregister_interest(_z_session_t *zn, _z_session_interest_rc_t *intr) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); zn->_local_interests = _z_session_interest_rc_list_drop_filter(zn->_local_interests, _z_session_interest_rc_eq, intr); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_interest(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_interest_rc_list_free(&zn->_local_interests); _z_declare_data_list_free(&zn->_remote_declares); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } z_result_t _z_interest_process_declare_final(_z_session_t *zn, uint32_t id) { _z_interest_msg_t msg = {.type = _Z_INTEREST_MSG_TYPE_FINAL, .id = id}; // Retrieve interest - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_interest_rc_t *intr = __unsafe_z_get_interest_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); if (intr == NULL) { return _Z_RES_OK; } diff --git a/src/session/push.c b/src/session/push.c index 6b45de25b..a9537be38 100644 --- a/src/session/push.c +++ b/src/session/push.c @@ -30,14 +30,14 @@ z_result_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push, z_reliabilit size_t kind = push->_body._is_put ? Z_SAMPLE_KIND_PUT : Z_SAMPLE_KIND_DELETE; if (push->_body._is_put) { _z_msg_put_t *put = &push->_body._body._put; - ret = _z_trigger_subscriptions(zn, push->_key, put->_payload, &put->_encoding, kind, &put->_commons._timestamp, - push->_qos, put->_attachment, reliability); + ret = _z_trigger_subscriptions(zn, &push->_key, &put->_payload, &put->_encoding, kind, + &put->_commons._timestamp, push->_qos, &put->_attachment, reliability); } else { _z_encoding_t encoding = _z_encoding_null(); _z_bytes_t payload = _z_bytes_null(); _z_msg_del_t *del = &push->_body._body._del; - ret = _z_trigger_subscriptions(zn, push->_key, payload, &encoding, kind, &del->_commons._timestamp, push->_qos, - del->_attachment, reliability); + ret = _z_trigger_subscriptions(zn, &push->_key, &payload, &encoding, kind, &del->_commons._timestamp, + push->_qos, &del->_attachment, reliability); } return ret; } diff --git a/src/session/query.c b/src/session/query.c index 9515f47d3..22f05571c 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -35,6 +35,23 @@ void _z_pending_query_clear(_z_pending_query_t *pen_qry) { bool _z_pending_query_eq(const _z_pending_query_t *one, const _z_pending_query_t *two) { return one->_id == two->_id; } +static bool _z_pending_query_timeout(const _z_pending_query_t *foo, const _z_pending_query_t *pq) { + _ZP_UNUSED(foo); + bool result = z_clock_elapsed_ms((z_clock_t *)&pq->_start_time) >= pq->_timeout; + if (result) { + _Z_INFO("Dropping query because of timeout"); + } + return result; +} + +void _z_pending_query_process_timeout(_z_session_t *zn) { + // Lock session + _z_session_mutex_lock(zn); + // Drop all queries with timeout elapsed + zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_timeout, NULL); + _z_session_mutex_unlock(zn); +} + /*------------------ Query ------------------*/ _z_zint_t _z_get_query_id(_z_session_t *zn) { return zn->_query_id++; } @@ -66,11 +83,11 @@ _z_pending_query_t *__unsafe__z_get_pending_query_by_id(_z_session_t *zn, const } _z_pending_query_t *_z_get_pending_query_by_id(_z_session_t *zn, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_t *pql = __unsafe__z_get_pending_query_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return pql; } @@ -80,7 +97,7 @@ z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_q _Z_DEBUG(">>> Allocating query for (%ju:%.*s)", (uintmax_t)pen_qry->_key._id, (int)_z_string_len(&pen_qry->_key._suffix), _z_string_data(&pen_qry->_key._suffix)); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_t *pql = __unsafe__z_get_pending_query_by_id(zn, pen_qry->_id); if (pql == NULL) { // Register query only if a pending one with the same ID does not exist @@ -89,44 +106,43 @@ z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_q ret = _Z_ERR_ENTITY_DECLARATION_FAILED; } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } -z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, const _z_keyexpr_t keyexpr, - _z_msg_put_t *msg, z_sample_kind_t kind) { - z_result_t ret = _Z_RES_OK; - - _zp_session_lock_mutex(zn); +static z_result_t _z_trigger_query_reply_partial_inner(_z_session_t *zn, const _z_zint_t id, + const _z_keyexpr_t *keyexpr, _z_msg_put_t *msg, + z_sample_kind_t kind) { + _z_session_mutex_lock(zn); + // Get query infos _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); - if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { - ret = _Z_ERR_ENTITY_UNKNOWN; + if (pen_qry == NULL) { + _z_session_mutex_unlock(zn); + return _Z_ERR_ENTITY_UNKNOWN; } - - _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, &keyexpr); - if ((ret == _Z_RES_OK) && - ((pen_qry->_anykey == false) && (_z_keyexpr_suffix_intersects(&pen_qry->_key, &keyexpr) == false))) { - ret = _Z_ERR_QUERY_NOT_MATCH; + _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + if (!pen_qry->_anykey && !_z_keyexpr_suffix_intersects(&pen_qry->_key, keyexpr)) { + _z_session_mutex_unlock(zn); + return _Z_ERR_QUERY_NOT_MATCH; } - // Build the reply - _z_reply_t reply = _z_reply_create(expanded_ke, zn->_local_zid, msg->_payload, &msg->_commons._timestamp, - &msg->_encoding, kind, msg->_attachment); - - bool drop = false; - // Verify if this is a newer reply, free the old one in case it is - if ((ret == _Z_RES_OK) && ((pen_qry->_consolidation == Z_CONSOLIDATION_MODE_LATEST) || - (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC))) { + _z_reply_t reply = _z_reply_alias(&expanded_ke, zn->_local_zid, &msg->_payload, &msg->_commons._timestamp, + &msg->_encoding, kind, &msg->_attachment); + // Process monotonic & latest consolidation mode + if ((pen_qry->_consolidation == Z_CONSOLIDATION_MODE_LATEST) || + (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC)) { + bool drop = false; _z_pending_reply_list_t *pen_rps = pen_qry->_pending_replies; _z_pending_reply_t *pen_rep = NULL; + + // Verify if this is a newer reply, free the old one in case it is while (pen_rps != NULL) { pen_rep = _z_pending_reply_list_head(pen_rps); - // Check if this is the same resource key if (_z_string_equals(&pen_rep->_reply.data._result.sample.keyexpr._suffix, - &reply.data._result.sample.keyexpr._suffix) == true) { + &reply.data._result.sample.keyexpr._suffix)) { if (msg->_commons._timestamp.time <= pen_rep->_tstamp.time) { drop = true; } else { @@ -137,86 +153,74 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, } pen_rps = _z_pending_reply_list_tail(pen_rps); } - - if (drop == false) { + if (!drop) { // Cache most recent reply pen_rep = (_z_pending_reply_t *)z_malloc(sizeof(_z_pending_reply_t)); - if (pen_rep != NULL) { - if (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC) { - // No need to store the whole reply in the monotonic mode. - _z_reply_t partial_reply; - (void)memset(&partial_reply, 0, - sizeof(_z_reply_t)); // Avoid warnings on uninitialized values on the reply - partial_reply.data._tag = _Z_REPLY_TAG_DATA; - partial_reply.data._result.sample.keyexpr = _z_keyexpr_duplicate(reply.data._result.sample.keyexpr); - pen_rep->_reply = partial_reply; - } else { - pen_rep->_reply = reply; // Store the whole reply in the latest mode - } - pen_rep->_tstamp = _z_timestamp_duplicate(&msg->_commons._timestamp); - pen_qry->_pending_replies = _z_pending_reply_list_push(pen_qry->_pending_replies, pen_rep); + if (pen_rep == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + if (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC) { + // No need to store the whole reply in the monotonic mode. + pen_rep->_reply = _z_reply_null(); + pen_rep->_reply.data._tag = _Z_REPLY_TAG_DATA; + pen_rep->_reply.data._result.sample.keyexpr = _z_keyexpr_duplicate(&reply.data._result.sample.keyexpr); } else { - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + // Copy the reply to store it out of context + _Z_RETURN_IF_ERR(_z_reply_copy(&pen_rep->_reply, &reply)); } + pen_rep->_tstamp = _z_timestamp_duplicate(&msg->_commons._timestamp); + pen_qry->_pending_replies = _z_pending_reply_list_push(pen_qry->_pending_replies, pen_rep); } } + _z_session_mutex_unlock(zn); - _zp_session_unlock_mutex(zn); - - // Trigger the user callback - if ((ret == _Z_RES_OK) && (pen_qry->_consolidation != Z_CONSOLIDATION_MODE_LATEST)) { - _z_reply_t cb_reply = _z_reply_null(); - cb_reply = _z_reply_move(&reply); - pen_qry->_callback(&cb_reply, pen_qry->_arg); - _z_reply_clear(&cb_reply); - return ret; - } - // Other cases - if (drop || (ret != _Z_RES_OK)) { - _z_reply_clear(&reply); + // Trigger callback if applicable + if (pen_qry->_consolidation != Z_CONSOLIDATION_MODE_LATEST) { + pen_qry->_callback(&reply, pen_qry->_arg); } + return _Z_RES_OK; +} +z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, _z_keyexpr_t *keyexpr, + _z_msg_put_t *msg, z_sample_kind_t kind) { + z_result_t ret = _z_trigger_query_reply_partial_inner(zn, id, keyexpr, msg, kind); + // Clean up + _z_keyexpr_clear(keyexpr); + _z_bytes_aliased_drop(&msg->_payload); + _z_bytes_drop(&msg->_attachment); + _z_encoding_clear(&msg->_encoding); return ret; } z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg) { z_result_t ret = _Z_RES_OK; - _zp_session_lock_mutex(zn); - + // Retrieve query + _z_session_mutex_lock(zn); _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); - if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { + if (pen_qry == NULL) { ret = _Z_ERR_ENTITY_UNKNOWN; } - - // Build the reply - _z_reply_t reply = _z_reply_err_create(msg->_payload, &msg->_encoding); - - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Trigger the user callback if (ret == _Z_RES_OK) { - _z_reply_t cb_reply = _z_reply_null(); - cb_reply = _z_reply_move(&reply); - pen_qry->_callback(&cb_reply, pen_qry->_arg); - _z_reply_clear(&cb_reply); - } - - if (ret != _Z_RES_OK) { - _z_reply_clear(&reply); + _z_reply_t reply = _z_reply_err_alias(&msg->_payload, &msg->_encoding); + pen_qry->_callback(&reply, pen_qry->_arg); } - + // Clean up + _z_bytes_aliased_drop(&msg->_payload); + _z_encoding_clear(&msg->_encoding); return ret; } z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { z_result_t ret = _Z_RES_OK; - _zp_session_lock_mutex(zn); - - // Final reply received for unknown query id + // Retrieve query + _z_session_mutex_lock(zn); _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); - if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { + if (pen_qry == NULL) { ret = _Z_ERR_ENTITY_UNKNOWN; } // The reply is the final one, apply consolidation if needed @@ -225,37 +229,38 @@ z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { _z_pending_reply_t *pen_rep = _z_pending_reply_list_head(pen_qry->_pending_replies); // Trigger the query handler - _z_reply_t cb_reply = _z_reply_null(); - cb_reply = _z_reply_move(&pen_rep->_reply); - pen_qry->_callback(&cb_reply, pen_qry->_arg); + pen_qry->_callback(&pen_rep->_reply, pen_qry->_arg); pen_qry->_pending_replies = _z_pending_reply_list_pop(pen_qry->_pending_replies, NULL); - _z_reply_clear(&cb_reply); } } - if (ret == _Z_RES_OK) { // Dropping a pending query triggers the dropper callback that is now the equivalent to a reply with the FINAL zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); } - - _zp_session_unlock_mutex(zn); - + _z_session_mutex_unlock(zn); return ret; } void _z_unregister_pending_query(_z_session_t *zn, _z_pending_query_t *pen_qry) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_pending_queries(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_list_free(&zn->_pending_queries); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); +} +#else + +void _z_pending_query_process_timeout(_z_session_t *zn) { + _ZP_UNUSED(zn); + return; } + #endif diff --git a/src/session/queryable.c b/src/session/queryable.c index 3e05a70c3..d3b120751 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -25,8 +25,63 @@ #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/pointers.h" +#include "zenoh-pico/utils/string.h" #if Z_FEATURE_QUERYABLE == 1 + +#define _Z_QLEINFOS_VEC_SIZE 4 // Arbitrary initial size + +#if Z_FEATURE_RX_CACHE == 1 +static inline bool _z_queryable_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_queryable_infos_svec_t *infos_val, size_t *qle_nb) { + if (!_z_keyexpr_equals(ke, &zn->_queryable_cache.ke_in)) { + return false; + } + *ke_val = _z_keyexpr_alias(zn->_queryable_cache.ke_out); + *infos_val = _z_queryable_infos_svec_alias(&zn->_queryable_cache.infos); + *qle_nb = zn->_queryable_cache.qle_nb; + return true; +} + +static inline void _z_queryable_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_queryable_infos_svec_t *infos) { + // Clear previous data + _z_queryable_cache_clear(&zn->_queryable_cache); + // Register new info + zn->_queryable_cache.ke_in = _z_keyexpr_duplicate(ke_in); + zn->_queryable_cache.ke_out = _z_keyexpr_duplicate(ke_out); + zn->_queryable_cache.infos = _z_queryable_infos_svec_alias(infos); + zn->_queryable_cache.qle_nb = _z_queryable_infos_svec_len(infos); +} + +void _z_queryable_cache_clear(_z_queryable_cache_t *cache) { + _z_queryable_infos_svec_clear(&cache->infos); + _z_keyexpr_clear(&cache->ke_in); + _z_keyexpr_clear(&cache->ke_out); +} + +#else +static inline bool _z_queryable_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_queryable_infos_svec_t *infos_val, size_t *sub_nb) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke); + _ZP_UNUSED(ke_val); + _ZP_UNUSED(infos_val); + _ZP_UNUSED(sub_nb); + return false; +} + +static inline void _z_queryable_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_queryable_infos_svec_t *infos) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke_in); + _ZP_UNUSED(ke_out); + _ZP_UNUSED(infos); + return; +} +#endif // Z_FEATURE_RX_CACHE == 1 + bool _z_session_queryable_eq(const _z_session_queryable_t *one, const _z_session_queryable_t *two) { return one->_id == two->_id; } @@ -39,7 +94,8 @@ void _z_session_queryable_clear(_z_session_queryable_t *qle) { } /*------------------ Queryable ------------------*/ -_z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_rc_list_t *qles, const _z_zint_t id) { +static _z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_rc_list_t *qles, + const _z_zint_t id) { _z_session_queryable_rc_t *ret = NULL; _z_session_queryable_rc_list_t *xs = qles; @@ -56,29 +112,12 @@ _z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_ return ret; } -_z_session_queryable_rc_list_t *__z_get_session_queryable_by_key(_z_session_queryable_rc_list_t *qles, - const _z_keyexpr_t key) { - _z_session_queryable_rc_list_t *ret = NULL; - - _z_session_queryable_rc_list_t *xs = qles; - while (xs != NULL) { - _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); - if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(qle)->_key, &key) == true) { - ret = _z_session_queryable_rc_list_push(ret, _z_session_queryable_rc_clone_as_ptr(qle)); - } - - xs = _z_session_queryable_rc_list_tail(xs); - } - - return ret; -} - /** * This function is unsafe because it operates in potentially concurrent data. * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_session_queryable_rc_t *__unsafe_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { +static _z_session_queryable_rc_t *__unsafe_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { _z_session_queryable_rc_list_t *qles = zn->_local_queryable; return __z_get_session_queryable_by_id(qles, id); } @@ -88,38 +127,41 @@ _z_session_queryable_rc_t *__unsafe_z_get_session_queryable_by_id(_z_session_t * * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_session_queryable_rc_list_t *__unsafe_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t key) { +static z_result_t __unsafe_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *key, + _z_queryable_infos_svec_t *qle_infos) { _z_session_queryable_rc_list_t *qles = zn->_local_queryable; - return __z_get_session_queryable_by_key(qles, key); + + *qle_infos = _z_queryable_infos_svec_make(_Z_QLEINFOS_VEC_SIZE); + _z_session_queryable_rc_list_t *xs = qles; + while (xs != NULL) { + // Parse queryable list + _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); + if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(qle)->_key, key)) { + _z_queryable_infos_t new_qle_info = {.arg = _Z_RC_IN_VAL(qle)->_arg, + .callback = _Z_RC_IN_VAL(qle)->_callback}; + _Z_RETURN_IF_ERR(_z_queryable_infos_svec_append(qle_infos, &new_qle_info, false)); + } + xs = _z_session_queryable_rc_list_tail(xs); + } + return _Z_RES_OK; } _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_queryable_rc_t *qle = __unsafe_z_get_session_queryable_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return qle; } -_z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { - _zp_session_lock_mutex(zn); - - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); - _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); - - _zp_session_unlock_mutex(zn); - - return qles; -} - _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_session_queryable_t *q) { _Z_DEBUG(">>> Allocating queryable for (%ju:%.*s)", (uintmax_t)q->_key._id, (int)_z_string_len(&q->_key._suffix), _z_string_data(&q->_key._suffix)); _z_session_queryable_rc_t *ret = NULL; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); ret = (_z_session_queryable_rc_t *)z_malloc(sizeof(_z_session_queryable_rc_t)); if (ret != NULL) { @@ -127,60 +169,102 @@ _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_se zn->_local_queryable = _z_session_queryable_rc_list_push(zn->_local_queryable, ret); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } -z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, const _z_keyexpr_t q_key, uint32_t qid, - const _z_bytes_t attachment) { - z_result_t ret = _Z_RES_OK; - _z_session_t *zn = _Z_RC_IN_VAL(zsrc); - - _zp_session_lock_mutex(zn); - - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key); - if (_z_keyexpr_has_suffix(&key)) { - _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); - - _zp_session_unlock_mutex(zn); +static z_result_t _z_session_queryable_get_infos(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_keyexpr_t *key, + _z_queryable_infos_svec_t *qles, size_t *qle_nb) { + // Check cache + if (!_z_queryable_get_from_cache(zn, keyexpr, key, qles, qle_nb)) { + _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); + _z_session_mutex_lock(zn); + *key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + + if (!_z_keyexpr_has_suffix(key)) { + _z_session_mutex_unlock(zn); + return _Z_ERR_KEYEXPR_UNKNOWN; + } + // Get queryable list + z_result_t ret = __unsafe_z_get_session_queryable_by_key(zn, key, qles); + _z_session_mutex_unlock(zn); + if (ret != _Z_RES_OK) { + return ret; + } + *qle_nb = _z_queryable_infos_svec_len(qles); + // Update cache + _z_queryable_update_cache(zn, keyexpr, key, qles); + } + return _Z_RES_OK; +} - // Build the z_query - _z_query_t q = _z_query_create(&msgq->_ext_value, &key, &msgq->_parameters, zsrc, qid, attachment); - _z_query_rc_t query = _z_query_rc_new_from_val(&q); - // Parse session_queryable list - _z_session_queryable_rc_list_t *xs = qles; - while (xs != NULL) { - _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); - _Z_RC_IN_VAL(qle)->_callback(&query, _Z_RC_IN_VAL(qle)->_arg); - xs = _z_session_queryable_rc_list_tail(xs); +static z_result_t _z_trigger_queryables_inner(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, const _z_keyexpr_t *q_key, + uint32_t qid) { + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); + _z_keyexpr_t key; + _z_queryable_infos_svec_t qles; + size_t qle_nb; + // Retrieve sub infos + _Z_RETURN_IF_ERR(_z_session_queryable_get_infos(zn, q_key, &key, &qles, &qle_nb)); + // Check if there are queryables + _Z_DEBUG("Triggering %ju queryables for key %d - %.*s", (uintmax_t)qle_nb, key._id, + (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); + if (qle_nb == 0) { + _z_keyexpr_clear(&key); + return _Z_RES_OK; + } + // Check anyke + char *slice_end = _z_ptr_char_offset((char *)msgq->_parameters.start, (ptrdiff_t)msgq->_parameters.len); + bool anyke = false; + if (_z_slice_check(&msgq->_parameters)) { + if (_z_strstr((char *)msgq->_parameters.start, slice_end, Z_SELECTOR_QUERY_MATCH) != NULL) { + anyke = true; } - // Clean up - _z_query_rc_drop(&query); - _z_session_queryable_rc_list_free(&qles); - } else { - _zp_session_unlock_mutex(zn); - ret = _Z_ERR_KEYEXPR_UNKNOWN; } + // Build the z_query + _z_query_t query = + _z_query_alias(&msgq->_ext_value, &key, &msgq->_parameters, zsrc, qid, &msgq->_ext_attachment, anyke); + // Parse session_queryable svec + for (size_t i = 0; i < qle_nb; i++) { + _z_queryable_infos_t *qle_info = _z_queryable_infos_svec_get(&qles, i); + qle_info->callback(&query, qle_info->arg); + } + // Clean up + _z_keyexpr_clear(&key); +#if Z_FEATURE_RX_CACHE != 1 + _z_queryable_infos_svec_release(&qles); // Otherwise it's released with cache +#endif + return _Z_RES_OK; +} +z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, _z_keyexpr_t *q_key, uint32_t qid) { + z_result_t ret = _z_trigger_queryables_inner(zsrc, msgq, q_key, qid); + // Clean up + _z_keyexpr_clear(q_key); + _z_encoding_clear(&msgq->_ext_value.encoding); + _z_bytes_drop(&msgq->_ext_value.payload); + _z_bytes_drop(&msgq->_ext_attachment); + _z_slice_clear(&msgq->_parameters); return ret; } void _z_unregister_session_queryable(_z_session_t *zn, _z_session_queryable_rc_t *qle) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); zn->_local_queryable = _z_session_queryable_rc_list_drop_filter(zn->_local_queryable, _z_session_queryable_rc_eq, qle); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_session_queryable(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_queryable_rc_list_free(&zn->_local_queryable); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } #endif diff --git a/src/session/reply.c b/src/session/reply.c index 7eb13194c..6361099ee 100644 --- a/src/session/reply.c +++ b/src/session/reply.c @@ -19,7 +19,7 @@ #include "zenoh-pico/session/query.h" #include "zenoh-pico/utils/logging.h" -z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t key, _z_msg_reply_t *reply) { +z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t *key, _z_msg_reply_t *reply) { z_result_t ret = _Z_RES_OK; // TODO check id to know where to dispatch diff --git a/src/session/resource.c b/src/session/resource.c index b573e600a..2413a1d21 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -87,24 +87,35 @@ _z_resource_t *__z_get_resource_by_key(_z_resource_list_t *rl, const _z_keyexpr_ return ret; } -_z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keyexpr_t *keyexpr) { - _z_keyexpr_t ret = {._id = Z_RESOURCE_ID_NONE, ._suffix = _z_string_null(), ._mapping = _z_keyexpr_mapping(0)}; +static _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keyexpr_t *keyexpr, + bool force_alias) { + _z_zint_t id = keyexpr->_id; + + // Check if ke is already expanded + if (id == Z_RESOURCE_ID_NONE) { + if (!_z_keyexpr_has_suffix(keyexpr)) { + return _z_keyexpr_null(); + } + // Keyexpr can be aliased from a rx buffer + if (force_alias) { + return _z_keyexpr_alias(*keyexpr); + } else { + return _z_keyexpr_duplicate(keyexpr); + } + } // Need to build the complete resource name, by recursively look at RIDs // Resource names are looked up from right to left + _z_keyexpr_t ret = _z_keyexpr_null(); _z_string_list_t *strs = NULL; size_t len = 0; // Append suffix as the right-most segment if (_z_keyexpr_has_suffix(keyexpr)) { len = len + _z_string_len(&keyexpr->_suffix); - strs = _z_string_list_push(strs, (_z_string_t *)&keyexpr->_suffix); // Warning: list must be release with - // _z_list_free(&strs, _z_noop_free); - // or will release the suffix as well + strs = _z_string_list_push(strs, (_z_string_t *)&keyexpr->_suffix); } - // Recursively go through all the RIDs - _z_zint_t id = keyexpr->_id; uint16_t mapping = _z_keyexpr_mapping_id(keyexpr); while (id != Z_RESOURCE_ID_NONE) { _z_resource_t *res = __z_get_resource_by_id(xs, mapping, id); @@ -114,9 +125,7 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye } if (_z_keyexpr_has_suffix(&res->_key)) { len = len + _z_string_len(&res->_key._suffix); - strs = _z_string_list_push(strs, &res->_key._suffix); // Warning: list must be release with - // _z_list_free(&strs, _z_noop_free); - // or will release the suffix as well + strs = _z_string_list_push(strs, &res->_key._suffix); } id = res->_key._id; } @@ -136,6 +145,7 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye } } } + // Warning: list must be released with _z_list_free(&strs, _z_noop_free) or will release the suffix as well _z_list_free(&strs, _z_noop_free); return ret; } @@ -165,17 +175,17 @@ _z_resource_t *__unsafe_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { +_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr, bool force_alias) { _z_resource_list_t *decls = _z_keyexpr_is_local(keyexpr) ? zn->_local_resources : zn->_remote_resources; - return __z_get_expanded_key_from_key(decls, keyexpr); + return __z_get_expanded_key_from_key(decls, keyexpr, force_alias); } _z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t rid) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_t *res = __unsafe_z_get_resource_by_id(zn, mapping, rid); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return res; } @@ -184,20 +194,20 @@ _z_resource_t *_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keye if (!_z_keyexpr_has_suffix(keyexpr)) { return _z_get_resource_by_id(zn, _z_keyexpr_mapping_id(keyexpr), keyexpr->_id); } - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_t *res = __unsafe_z_get_resource_by_key(zn, keyexpr); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return res; } _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { - _zp_session_lock_mutex(zn); - _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); + _z_session_mutex_lock(zn); + _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, false); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return res; } @@ -205,18 +215,17 @@ _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t * /// Returns the ID of the registered keyexpr. Returns 0 if registration failed. uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, uint16_t register_to_mapping) { uint16_t ret = Z_RESOURCE_ID_NONE; - key = _z_keyexpr_alias(key); uint16_t mapping = register_to_mapping; uint16_t parent_mapping = _z_keyexpr_mapping_id(&key); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); if (key._id != Z_RESOURCE_ID_NONE) { if (parent_mapping == mapping) { _z_resource_t *parent = __unsafe_z_get_resource_by_id(zn, parent_mapping, key._id); parent->_refcount++; } else { - key = __unsafe_z_get_expanded_key_from_key(zn, &key); + key = __unsafe_z_get_expanded_key_from_key(zn, &key, false); } } ret = key._id; @@ -226,7 +235,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u ret = Z_RESOURCE_ID_NONE; } else { res->_refcount = 1; - res->_key = _z_keyexpr_duplicate(key); + res->_key = _z_keyexpr_duplicate(&key); ret = id == Z_RESOURCE_ID_NONE ? _z_get_resource_id(zn) : id; res->_id = ret; // Register the resource @@ -238,7 +247,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -246,7 +255,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping) { bool is_local = mapping == _Z_KEYEXPR_MAPPING_LOCAL; _Z_DEBUG("unregistering: id %d, mapping: %d", id, mapping); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_list_t **parent_mut = is_local ? &zn->_local_resources : &zn->_remote_resources; while (id != 0) { _z_resource_list_t *parent = *parent_mut; @@ -268,7 +277,7 @@ void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping) { parent = *parent_mut; } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, const _z_resource_t *ctx) { @@ -276,19 +285,19 @@ bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, cons return _z_keyexpr_mapping_id(&candidate->_key) == mapping; } void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_t ctx = {._id = mapping, ._refcount = 0, ._key = {0}}; zn->_remote_resources = _z_resource_list_drop_filter(zn->_remote_resources, _z_unregister_resource_for_peer_filter, &ctx); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_resources(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_list_free(&zn->_local_resources); _z_resource_list_free(&zn->_remote_resources); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } diff --git a/src/session/rx.c b/src/session/rx.c index afacc75d7..c15e53810 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -32,6 +32,7 @@ #include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" /*------------------ Handle message ------------------*/ @@ -92,8 +93,7 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_REQUEST_QUERY: { #if Z_FEATURE_QUERYABLE == 1 _z_msg_query_t *query = &req->_body._query; - ret = _z_trigger_queryables(zsrc, query, req->_key, (uint32_t)req->_rid, - req->_body._query._ext_attachment); + ret = _z_trigger_queryables(zsrc, query, &req->_key, (uint32_t)req->_rid); #else _Z_DEBUG("_Z_REQUEST_QUERY dropped, queryables not supported"); #endif @@ -101,8 +101,8 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_REQUEST_PUT: { #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_put_t put = req->_body._put; - ret = _z_trigger_subscriptions(zn, req->_key, put._payload, &put._encoding, Z_SAMPLE_KIND_PUT, - &put._commons._timestamp, req->_ext_qos, put._attachment, + ret = _z_trigger_subscriptions(zn, &req->_key, &put._payload, &put._encoding, Z_SAMPLE_KIND_PUT, + &put._commons._timestamp, req->_ext_qos, &put._attachment, msg->_reliability); #endif if (ret == _Z_RES_OK) { @@ -114,8 +114,9 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_del_t del = req->_body._del; _z_encoding_t encoding = _z_encoding_null(); - ret = _z_trigger_subscriptions(zn, req->_key, _z_bytes_null(), &encoding, Z_SAMPLE_KIND_DELETE, - &del._commons._timestamp, req->_ext_qos, del._attachment, + _z_bytes_t empty_payload = _z_bytes_null(); + ret = _z_trigger_subscriptions(zn, &req->_key, &empty_payload, &encoding, Z_SAMPLE_KIND_DELETE, + &del._commons._timestamp, req->_ext_qos, &del._attachment, msg->_reliability); #endif if (ret == _Z_RES_OK) { @@ -131,7 +132,7 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * switch (response->_tag) { case _Z_RESPONSE_BODY_REPLY: { _z_msg_reply_t *reply = &response->_body._reply; - ret = _z_trigger_reply_partial(zn, response->_request_id, response->_key, reply); + ret = _z_trigger_reply_partial(zn, response->_request_id, &response->_key, reply); } break; case _Z_RESPONSE_BODY_ERR: { _z_msg_err_t *error = &response->_body._err; @@ -157,6 +158,5 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * } } } - _z_msg_clear(msg); return ret; } diff --git a/src/session/scout.c b/src/session/scout.c index 7c35d1e21..5badf7201 100644 --- a/src/session/scout.c +++ b/src/session/scout.c @@ -76,7 +76,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, _z_string_t *locator, unsi switch (_Z_MID(s_msg._header)) { case _Z_MID_HELLO: { - _Z_INFO("Received _Z_HELLO message"); + _Z_DEBUG("Received _Z_HELLO message"); _z_hello_t *hello = (_z_hello_t *)z_malloc(sizeof(_z_hello_t)); if (hello != NULL) { hello->_version = s_msg._body._hello._version; @@ -89,7 +89,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, _z_string_t *locator, unsi for (size_t i = 0; i < n_loc; i++) { _z_string_t s = _z_locator_to_string(&s_msg._body._hello._locators._val[i]); - _z_string_svec_append(&hello->_locators, &s); + _z_string_svec_append(&hello->_locators, &s, true); } } else { // @TODO: construct the locator departing from the sock address diff --git a/src/session/subscription.c b/src/session/subscription.c index b7bf19f26..cad4821a5 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -29,6 +29,60 @@ #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_SUBSCRIPTION == 1 + +#define _Z_SUBINFOS_VEC_SIZE 4 // Arbitrary initial size + +#if Z_FEATURE_RX_CACHE == 1 +static inline bool _z_subscription_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_subscription_infos_svec_t *infos_val, size_t *sub_nb) { + if (!_z_keyexpr_equals(ke, &zn->_subscription_cache.ke_in)) { + return false; + } + *ke_val = _z_keyexpr_alias(zn->_subscription_cache.ke_out); + *infos_val = _z_subscription_infos_svec_alias(&zn->_subscription_cache.infos); + *sub_nb = zn->_subscription_cache.sub_nb; + return true; +} + +static inline void _z_subscription_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_subscription_infos_svec_t *infos) { + // Clear previous data + _z_subscription_cache_clear(&zn->_subscription_cache); + // Register new info + zn->_subscription_cache.ke_in = _z_keyexpr_duplicate(ke_in); + zn->_subscription_cache.ke_out = _z_keyexpr_duplicate(ke_out); + zn->_subscription_cache.infos = _z_subscription_infos_svec_alias(infos); + zn->_subscription_cache.sub_nb = _z_subscription_infos_svec_len(infos); +} + +void _z_subscription_cache_clear(_z_subscription_cache_t *cache) { + _z_subscription_infos_svec_clear(&cache->infos); + _z_keyexpr_clear(&cache->ke_in); + _z_keyexpr_clear(&cache->ke_out); +} + +#else +static inline bool _z_subscription_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_subscription_infos_svec_t *infos_val, size_t *sub_nb) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke); + _ZP_UNUSED(ke_val); + _ZP_UNUSED(infos_val); + _ZP_UNUSED(sub_nb); + return false; +} + +static inline void _z_subscription_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_subscription_infos_svec_t *infos) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke_in); + _ZP_UNUSED(ke_out); + _ZP_UNUSED(infos); + return; +} +#endif // Z_FEATURE_RX_CACHE == 1 + +// Subscription bool _z_subscription_eq(const _z_subscription_t *other, const _z_subscription_t *this_) { return this_->_id == other->_id; } @@ -57,22 +111,6 @@ _z_subscription_rc_t *__z_get_subscription_by_id(_z_subscription_rc_list_t *subs return ret; } -_z_subscription_rc_list_t *__z_get_subscriptions_by_key(_z_subscription_rc_list_t *subs, const _z_keyexpr_t *key) { - _z_subscription_rc_list_t *ret = NULL; - - _z_subscription_rc_list_t *xs = subs; - while (xs != NULL) { - _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); - if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(sub)->_key, key) == true) { - ret = _z_subscription_rc_list_push(ret, _z_subscription_rc_clone_as_ptr(sub)); - } - - xs = _z_subscription_rc_list_tail(xs); - } - - return ret; -} - /** * This function is unsafe because it operates in potentially concurrent data. * Make sure that the following mutexes are locked before calling this function: @@ -89,39 +127,42 @@ _z_subscription_rc_t *__unsafe_z_get_subscription_by_id(_z_session_t *zn, uint8_ * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_subscription_rc_list_t *__unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, - const _z_keyexpr_t *key) { +static z_result_t __unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *key, + _z_subscription_infos_svec_t *sub_infos) { _z_subscription_rc_list_t *subs = (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_subscriptions : zn->_remote_subscriptions; - return __z_get_subscriptions_by_key(subs, key); + + *sub_infos = _z_subscription_infos_svec_make(_Z_SUBINFOS_VEC_SIZE); + _z_subscription_rc_list_t *xs = subs; + while (xs != NULL) { + // Parse subscription list + _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); + if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(sub)->_key, key)) { + _z_subscription_infos_t new_sub_info = {.arg = _Z_RC_IN_VAL(sub)->_arg, + .callback = _Z_RC_IN_VAL(sub)->_callback}; + _Z_RETURN_IF_ERR(_z_subscription_infos_svec_append(sub_infos, &new_sub_info, false)); + } + xs = _z_subscription_rc_list_tail(xs); + } + return _Z_RES_OK; } _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_t *sub = __unsafe_z_get_subscription_by_id(zn, is_local, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return sub; } -_z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *key) { - _zp_session_lock_mutex(zn); - - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, is_local, key); - - _zp_session_unlock_mutex(zn); - - return subs; -} - _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *s) { _Z_DEBUG(">>> Allocating sub decl for (%ju:%.*s)", (uintmax_t)s->_key._id, (int)_z_string_len(&s->_key._suffix), _z_string_data(&s->_key._suffix)); _z_subscription_rc_t *ret = NULL; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); ret = (_z_subscription_rc_t *)z_malloc(sizeof(_z_subscription_rc_t)); if (ret != NULL) { @@ -133,58 +174,91 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t attachment, z_reliability_t reliability) { + _z_bytes_t *attachment, z_reliability_t reliability) { z_result_t ret = _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, timestamp, qos, attachment, reliability); (void)ret; } -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, - _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, const _z_bytes_t attachment, z_reliability_t reliability) { - z_result_t ret = _Z_RES_OK; - - _zp_session_lock_mutex(zn); - - _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr._id, (int)_z_string_len(&keyexpr._suffix), - _z_string_data(&keyexpr._suffix), _z_keyexpr_mapping_id(&keyexpr)); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &keyexpr); - _Z_DEBUG("Triggering subs for %d - %.*s", key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); - if (_z_keyexpr_has_suffix(&key)) { - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key); - - _zp_session_unlock_mutex(zn); - - // Build the sample - _z_sample_t sample = _z_sample_create(&key, payload, timestamp, encoding, kind, qos, attachment, reliability); - // Parse subscription list - _z_subscription_rc_list_t *xs = subs; - _Z_DEBUG("Triggering %ju subs", (uintmax_t)_z_subscription_rc_list_len(xs)); - while (xs != NULL) { - _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); - _Z_RC_IN_VAL(sub)->_callback(&sample, _Z_RC_IN_VAL(sub)->_arg); - xs = _z_subscription_rc_list_tail(xs); +static z_result_t _z_subscription_get_infos(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_keyexpr_t *key, + _z_subscription_infos_svec_t *subs, size_t *sub_nb) { + // Check cache + if (!_z_subscription_get_from_cache(zn, keyexpr, key, subs, sub_nb)) { + _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); + _z_session_mutex_lock(zn); + *key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + + if (!_z_keyexpr_has_suffix(key)) { + _z_session_mutex_unlock(zn); + return _Z_ERR_KEYEXPR_UNKNOWN; } - // Clean up - _z_sample_clear(&sample); - _z_subscription_rc_list_free(&subs); - } else { - _zp_session_unlock_mutex(zn); - ret = _Z_ERR_KEYEXPR_UNKNOWN; + // Get subscription list + z_result_t ret = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, key, subs); + _z_session_mutex_unlock(zn); + if (ret != _Z_RES_OK) { + return ret; + } + *sub_nb = _z_subscription_infos_svec_len(subs); + // Update cache + _z_subscription_update_cache(zn, keyexpr, key, subs); } + return _Z_RES_OK; +} + +static z_result_t _z_trigger_subscriptions_inner(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_zint_t kind, + const _z_timestamp_t *timestamp, const _z_n_qos_t qos, + _z_bytes_t *attachment, z_reliability_t reliability) { + _z_keyexpr_t key; + _z_subscription_infos_svec_t subs; + size_t sub_nb; + // Retrieve sub infos + _Z_RETURN_IF_ERR(_z_subscription_get_infos(zn, keyexpr, &key, &subs, &sub_nb)); + // Check if there are subs + _Z_DEBUG("Triggering %ju subs for key %d - %.*s", (uintmax_t)sub_nb, key._id, (int)_z_string_len(&key._suffix), + _z_string_data(&key._suffix)); + if (sub_nb == 0) { + _z_keyexpr_clear(&key); + return _Z_RES_OK; + } + // Create sample + _z_sample_t sample = _z_sample_alias(&key, payload, timestamp, encoding, kind, qos, attachment, reliability); + // Parse subscription infos svec + for (size_t i = 0; i < sub_nb; i++) { + _z_subscription_infos_t *sub_info = _z_subscription_infos_svec_get(&subs, i); + sub_info->callback(&sample, sub_info->arg); + } + // Clean up + _z_keyexpr_clear(&key); +#if Z_FEATURE_RX_CACHE != 1 + _z_subscription_infos_svec_release(&subs); // Otherwise it's released with cache +#endif + return _Z_RES_OK; +} +z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { + z_result_t ret = + _z_trigger_subscriptions_inner(zn, keyexpr, payload, encoding, kind, timestamp, qos, attachment, reliability); + // Clean up + _z_keyexpr_clear(keyexpr); + _z_encoding_clear(encoding); + _z_bytes_aliased_drop(payload); + _z_bytes_drop(attachment); return ret; } void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); if (is_local == _Z_RESOURCE_IS_LOCAL) { zn->_local_subscriptions = @@ -194,22 +268,22 @@ void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscript _z_subscription_rc_list_drop_filter(zn->_remote_subscriptions, _z_subscription_rc_eq, sub); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_subscriptions(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_list_free(&zn->_local_subscriptions); _z_subscription_rc_list_free(&zn->_remote_subscriptions); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t attachment, z_reliability_t reliability) { + _z_bytes_t *attachment, z_reliability_t reliability) { _ZP_UNUSED(zn); _ZP_UNUSED(keyexpr); _ZP_UNUSED(payload); diff --git a/src/session/tx.c b/src/session/tx.c deleted file mode 100644 index 64746930e..000000000 --- a/src/session/tx.c +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/transport/multicast/tx.h" - -#include "zenoh-pico/transport/raweth/tx.h" -#include "zenoh-pico/transport/unicast/tx.h" -#include "zenoh-pico/utils/logging.h" - -z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send network message"); - // Call transport function - switch (zn->_tp._type) { - case _Z_TRANSPORT_UNICAST_TYPE: - ret = _z_unicast_send_n_msg(zn, z_msg, reliability, cong_ctrl); - break; - case _Z_TRANSPORT_MULTICAST_TYPE: - ret = _z_multicast_send_n_msg(zn, z_msg, reliability, cong_ctrl); - break; - case _Z_TRANSPORT_RAWETH_TYPE: - ret = _z_raweth_send_n_msg(zn, z_msg, reliability, cong_ctrl); - break; - default: - ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; - break; - } - return ret; -} diff --git a/src/session/utils.c b/src/session/utils.c index d82f9d84c..84ad8793e 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -26,20 +26,20 @@ #include "zenoh-pico/utils/logging.h" /*------------------ clone helpers ------------------*/ -_z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { - _z_timestamp_t ts; - ts.id = tstamp->id; - ts.time = tstamp->time; - return ts; +void _z_timestamp_copy(_z_timestamp_t *dst, const _z_timestamp_t *src) { *dst = *src; } + +_z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { return *tstamp; } + +void _z_timestamp_move(_z_timestamp_t *dst, _z_timestamp_t *src) { + *dst = *src; + _z_timestamp_clear(src); } void _z_timestamp_clear(_z_timestamp_t *tstamp) { - memset(&tstamp->id, 0, sizeof(_z_id_t)); + tstamp->valid = false; tstamp->time = 0; } -bool _z_timestamp_check(const _z_timestamp_t *stamp) { return _z_id_check(stamp->id); } - z_result_t _z_session_generate_zid(_z_id_t *bs, uint8_t size) { z_result_t ret = _Z_RES_OK; z_random_fill((uint8_t *)bs->id, size); @@ -62,9 +62,15 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { #if Z_FEATURE_SUBSCRIPTION == 1 zn->_local_subscriptions = NULL; zn->_remote_subscriptions = NULL; +#if Z_FEATURE_RX_CACHE == 1 + memset(&zn->_subscription_cache, 0, sizeof(zn->_subscription_cache)); +#endif #endif #if Z_FEATURE_QUERYABLE == 1 zn->_local_queryable = NULL; +#if Z_FEATURE_RX_CACHE == 1 + memset(&zn->_queryable_cache, 0, sizeof(zn->_queryable_cache)); +#endif #endif #if Z_FEATURE_QUERY == 1 zn->_pending_queries = NULL; @@ -82,13 +88,13 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { // Note session in transport switch (zn->_tp._type) { case _Z_TRANSPORT_UNICAST_TYPE: - zn->_tp._transport._unicast._session = zsrc; + zn->_tp._transport._unicast._common._session = zsrc; break; case _Z_TRANSPORT_MULTICAST_TYPE: - zn->_tp._transport._multicast._session = zsrc; + zn->_tp._transport._multicast._common._session = zsrc; break; case _Z_TRANSPORT_RAWETH_TYPE: - zn->_tp._transport._raweth._session = zsrc; + zn->_tp._transport._raweth._common._session = zsrc; break; default: break; @@ -113,9 +119,15 @@ void _z_session_clear(_z_session_t *zn) { _z_flush_resources(zn); #if Z_FEATURE_SUBSCRIPTION == 1 _z_flush_subscriptions(zn); +#if Z_FEATURE_RX_CACHE == 1 + _z_subscription_cache_clear(&zn->_subscription_cache); +#endif #endif #if Z_FEATURE_QUERYABLE == 1 _z_flush_session_queryable(zn); +#if Z_FEATURE_RX_CACHE == 1 + _z_queryable_cache_clear(&zn->_queryable_cache); +#endif #endif #if Z_FEATURE_QUERY == 1 _z_flush_pending_queries(zn); @@ -136,11 +148,3 @@ z_result_t _z_session_close(_z_session_t *zn, uint8_t reason) { return ret; } - -#if Z_FEATURE_MULTI_THREAD == 1 -void _zp_session_lock_mutex(_z_session_t *zn) { (void)_z_mutex_lock(&zn->_mutex_inner); } -void _zp_session_unlock_mutex(_z_session_t *zn) { (void)_z_mutex_unlock(&zn->_mutex_inner); } -#else -void _zp_session_lock_mutex(_z_session_t *zn) { _ZP_UNUSED(zn); } -void _zp_session_unlock_mutex(_z_session_t *zn) { _ZP_UNUSED(zn); } -#endif diff --git a/src/system/arduino/esp32/network.cpp b/src/system/arduino/esp32/network.cpp index 8c88d4dc6..c0a82927d 100644 --- a/src/system/arduino/esp32/network.cpp +++ b/src/system/arduino/esp32/network.cpp @@ -500,7 +500,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(in_addr_t) + sizeof(in_port_t)); + addr->len = sizeof(in_addr_t) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(in_addr_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(in_addr_t)), &b->sin_port, sizeof(in_port_t)); } @@ -513,7 +513,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(&a->sin6_addr, &b->sin6_addr, sizeof(struct in6_addr)) != 0)) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + addr->len = sizeof(struct in6_addr) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(in_port_t)); } diff --git a/src/system/arduino/opencr/network.cpp b/src/system/arduino/opencr/network.cpp index b690559f1..c02765d8c 100644 --- a/src/system/arduino/opencr/network.cpp +++ b/src/system/arduino/opencr/network.cpp @@ -295,8 +295,8 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ IPAddress rip = sock._udp->remoteIP(); uint16_t rport = sock._udp->remotePort(); - *addr = _z_slice_make(strlen((const char *)&rip[0]) + strlen((const char *)&rip[1]) + - strlen((const char *)&rip[2]) + strlen((const char *)&rip[3]) + sizeof(uint16_t)); + addr->len = strlen((const char *)&rip[0]) + strlen((const char *)&rip[1]) + + strlen((const char *)&rip[2]) + strlen((const char *)&rip[3]) + sizeof(uint16_t); uint8_t offset = 0; for (uint8_t i = 0; i < (uint8_t)4; i++) { (void)memcpy(const_cast(addr->start + offset), &rip[i], strlen((const char *)&rip[i])); diff --git a/src/system/emscripten/system.c b/src/system/emscripten/system.c index 9bfa8f7d6..52065d2db 100644 --- a/src/system/emscripten/system.c +++ b/src/system/emscripten/system.c @@ -55,11 +55,7 @@ z_result_t _z_task_detach(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_detach(*ta z_result_t _z_task_cancel(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_cancel(*task)); } -void _z_task_free(_z_task_t **task) { - _z_task_t *ptr = *task; - z_free(ptr); - *task = NULL; -} +void _z_task_free(_z_task_t **task) { *task = NULL; } /*------------------ Mutex ------------------*/ z_result_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } diff --git a/src/system/espidf/network.c b/src/system/espidf/network.c index bc91f50c3..0634d2a23 100644 --- a/src/system/espidf/network.c +++ b/src/system/espidf/network.c @@ -496,7 +496,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(in_addr_t) + sizeof(in_port_t)); + addr->len = sizeof(in_addr_t) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(in_addr_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(in_addr_t)), &b->sin_port, sizeof(in_port_t)); } @@ -509,7 +509,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(&a->sin6_addr, &b->sin6_addr, sizeof(struct in6_addr)) != 0)) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + addr->len = sizeof(struct in6_addr) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(in_port_t)); } diff --git a/src/system/mbed/network.cpp b/src/system/mbed/network.cpp index 310a107af..a9d365782 100644 --- a/src/system/mbed/network.cpp +++ b/src/system/mbed/network.cpp @@ -274,13 +274,13 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } if (raddr.get_ip_version() == NSAPI_IPv4) { - *addr = _z_slice_make(NSAPI_IPv4_BYTES + sizeof(uint16_t)); + addr->len = NSAPI_IPv4_BYTES + sizeof(uint16_t); (void)memcpy(const_cast(addr->start), raddr.get_ip_bytes(), NSAPI_IPv4_BYTES); uint16_t port = raddr.get_port(); (void)memcpy(const_cast(addr->start + NSAPI_IPv4_BYTES), &port, sizeof(uint16_t)); break; } else if (raddr.get_ip_version() == NSAPI_IPv6) { - *addr = _z_slice_make(NSAPI_IPv6_BYTES + sizeof(uint16_t)); + addr->len = NSAPI_IPv6_BYTES + sizeof(uint16_t); (void)memcpy(const_cast(addr->start), raddr.get_ip_bytes(), NSAPI_IPv6_BYTES); uint16_t port = raddr.get_port(); (void)memcpy(const_cast(addr->start + NSAPI_IPv6_BYTES), &port, sizeof(uint16_t)); diff --git a/src/system/unix/link/raweth.c b/src/system/unix/link/raweth.c index f1abcf325..6e15cae0d 100644 --- a/src/system/unix/link/raweth.c +++ b/src/system/unix/link/raweth.c @@ -118,7 +118,7 @@ size_t _z_receive_raweth(const _z_sys_net_socket_t *sock, void *buff, size_t buf // Copy sender mac if needed if (addr != NULL) { uint8_t *header_addr = (uint8_t *)buff; - *addr = _z_slice_make(sizeof(ETH_ALEN)); + addr->len = sizeof(ETH_ALEN); (void)memcpy((uint8_t *)addr->start, (header_addr + ETH_ALEN), sizeof(ETH_ALEN)); } return (size_t)bytesRead; diff --git a/src/system/unix/network.c b/src/system/unix/network.c index 86be15dc0..c822e4aa5 100644 --- a/src/system/unix/network.c +++ b/src/system/unix/network.c @@ -13,6 +13,7 @@ // #include +#include #include #include #include @@ -114,12 +115,69 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re z_result_t _z_listen_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t lep) { z_result_t ret = _Z_RES_OK; - (void)sock; - (void)lep; - - // @TODO: To be implemented - ret = _Z_ERR_GENERIC; - + // Open socket + sock->_fd = socket(lep._iptcp->ai_family, lep._iptcp->ai_socktype, lep._iptcp->ai_protocol); + if (sock->_fd == -1) { + return _Z_ERR_GENERIC; + } + // Set options + int value = true; + if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0)) { + ret = _Z_ERR_GENERIC; + } + int flags = 1; + if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#if Z_FEATURE_TCP_NODELAY == 1 + if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif + struct linger ling; + ling.l_onoff = 1; + ling.l_linger = Z_TRANSPORT_LEASE / 1000; + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(struct linger)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#if defined(ZENOH_MACOS) || defined(ZENOH_BSD) + setsockopt(sock->_fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)0, sizeof(int)); +#endif + if (ret != _Z_RES_OK) { + close(sock->_fd); + return ret; + } + struct addrinfo *it = NULL; + for (it = lep._iptcp; it != NULL; it = it->ai_next) { + if (bind(sock->_fd, it->ai_addr, it->ai_addrlen) < 0) { + if (it->ai_next == NULL) { + ret = _Z_ERR_GENERIC; + break; + } + } + if (listen(sock->_fd, 1) < 0) { + if (it->ai_next == NULL) { + ret = _Z_ERR_GENERIC; + break; + } + } + struct sockaddr naddr; + unsigned int nlen = sizeof(naddr); + int con_socket = accept(sock->_fd, &naddr, &nlen); + if (con_socket < 0) { + if (it->ai_next == NULL) { + ret = _Z_ERR_GENERIC; + break; + } + } else { + sock->_fd = con_socket; + break; + } + } + if (ret != _Z_RES_OK) { + close(sock->_fd); + } return ret; } @@ -535,7 +593,8 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(in_addr_t) + sizeof(in_port_t)); + assert(addr->len >= sizeof(in_addr_t) + sizeof(in_port_t)); + addr->len = sizeof(in_addr_t) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(in_addr_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(in_addr_t)), &b->sin_port, sizeof(in_port_t)); } @@ -548,7 +607,8 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + assert(addr->len >= sizeof(struct in6_addr) + sizeof(in_port_t)); + addr->len = sizeof(struct in6_addr) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(in_port_t)); } diff --git a/src/system/unix/system.c b/src/system/unix/system.c index beb78ceef..d1c0c5886 100644 --- a/src/system/unix/system.c +++ b/src/system/unix/system.c @@ -114,11 +114,7 @@ z_result_t _z_task_detach(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_detach(*ta z_result_t _z_task_cancel(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_cancel(*task)); } -void _z_task_free(_z_task_t **task) { - _z_task_t *ptr = *task; - z_free(ptr); - *task = NULL; -} +void _z_task_free(_z_task_t **task) { *task = NULL; } /*------------------ Mutex ------------------*/ z_result_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } diff --git a/src/system/windows/network.c b/src/system/windows/network.c index b0d9a6990..c3a8a3f27 100644 --- a/src/system/windows/network.c +++ b/src/system/windows/network.c @@ -548,7 +548,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(IN_ADDR) + sizeof(USHORT)); + addr->len = sizeof(IN_ADDR) + sizeof(USHORT); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(IN_ADDR)); (void)memcpy((uint8_t *)(addr->start + sizeof(IN_ADDR)), &b->sin_port, sizeof(USHORT)); } @@ -561,7 +561,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(USHORT)); + addr->len = sizeof(struct in6_addr) + sizeof(USHORT); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(USHORT)); } diff --git a/src/system/zephyr/network.c b/src/system/zephyr/network.c index d8ac405b3..d60555aa2 100644 --- a/src/system/zephyr/network.c +++ b/src/system/zephyr/network.c @@ -510,7 +510,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(uint32_t) + sizeof(uint16_t)); + addr->len = sizeof(uint32_t) + sizeof(uint16_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(uint32_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(uint32_t)), &b->sin_port, sizeof(uint16_t)); } @@ -523,7 +523,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, sizeof(uint32_t) * 4UL) == 0))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make((sizeof(uint32_t) * 4UL) + sizeof(uint16_t)); + addr->len = (sizeof(uint32_t) * 4UL) + sizeof(uint16_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(uint32_t) * 4UL); (void)memcpy((uint8_t *)(addr->start + (sizeof(uint32_t) * 4UL)), &b->sin6_port, sizeof(uint16_t)); } diff --git a/src/system/zephyr/system.c b/src/system/zephyr/system.c index c76e26a02..7818c9993 100644 --- a/src/system/zephyr/system.c +++ b/src/system/zephyr/system.c @@ -89,11 +89,7 @@ z_result_t _z_task_detach(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_detach(*ta z_result_t _z_task_cancel(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_cancel(*task)); } -void _z_task_free(_z_task_t **task) { - _z_task_t *ptr = *task; - z_free(ptr); - *task = NULL; -} +void _z_task_free(_z_task_t **task) { *task = NULL; } /*------------------ Mutex ------------------*/ z_result_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } diff --git a/src/transport/common/rx.c b/src/transport/common/rx.c index 5c5c68073..49a39b6cb 100644 --- a/src/transport/common/rx.c +++ b/src/transport/common/rx.c @@ -72,10 +72,14 @@ z_result_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl } if (ret == _Z_RES_OK) { _z_transport_message_t l_t_msg; - ret = _z_transport_message_decode(&l_t_msg, &zbf); + _z_arc_slice_svec_t arc_pool = _z_arc_slice_svec_make(1); + _z_network_message_svec_t msg_pool = _z_network_message_svec_make(1); + ret = _z_transport_message_decode(&l_t_msg, &zbf, &arc_pool, &msg_pool); if (ret == _Z_RES_OK) { _z_t_msg_copy(t_msg, &l_t_msg); } + _z_arc_slice_svec_clear(&arc_pool); + _z_network_message_svec_clear(&msg_pool); } _z_zbuf_clear(&zbf); diff --git a/src/transport/common/tx.c b/src/transport/common/tx.c index 75a837cbe..4b6d9bf32 100644 --- a/src/transport/common/tx.c +++ b/src/transport/common/tx.c @@ -16,15 +16,244 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/codec/network.h" #include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/protocol/definitions/transport.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/raweth/tx.h" -#include "zenoh-pico/transport/unicast/tx.h" +#include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" /*------------------ Transmission helper ------------------*/ + +static _z_zint_t _z_transport_tx_get_sn(_z_transport_common_t *ztc, z_reliability_t reliability) { + _z_zint_t sn; + if (reliability == Z_RELIABILITY_RELIABLE) { + sn = ztc->_sn_tx_reliable; + ztc->_sn_tx_reliable = _z_sn_increment(ztc->_sn_res, ztc->_sn_tx_reliable); + } else { + sn = ztc->_sn_tx_best_effort; + ztc->_sn_tx_best_effort = _z_sn_increment(ztc->_sn_res, ztc->_sn_tx_best_effort); + } + return sn; +} + +#if Z_FEATURE_FRAGMENTATION == 1 +static z_result_t _z_transport_tx_send_fragment_inner(_z_transport_common_t *ztc, _z_wbuf_t *frag_buff, + const _z_network_message_t *n_msg, z_reliability_t reliability, + _z_zint_t first_sn) { + bool is_first = true; + _z_zint_t sn = first_sn; + // Encode message on temp buffer + _Z_RETURN_IF_ERR(_z_network_message_encode(frag_buff, n_msg)); + // Fragment message + while (_z_wbuf_len(frag_buff) > 0) { + // Get fragment sequence number + if (!is_first) { + sn = _z_transport_tx_get_sn(ztc, reliability); + } + is_first = false; + // Serialize fragment + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + z_result_t ret = __unsafe_z_serialize_zenoh_fragment(&ztc->_wbuf, frag_buff, reliability, sn); + if (ret != _Z_RES_OK) { + _Z_ERROR("Fragment serialization failed with err %d", ret); + return ret; + } + // Send fragment + __unsafe_z_finalize_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztc->_link, &ztc->_wbuf)); + ztc->_transmitted = true; // Tell session we transmitted data + } + return _Z_RES_OK; +} + +static z_result_t _z_transport_tx_send_fragment(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, _z_zint_t first_sn) { + // Create an expandable wbuf for fragmentation + _z_wbuf_t frag_buff = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); + // Send message as fragments + z_result_t ret = _z_transport_tx_send_fragment_inner(ztc, &frag_buff, n_msg, reliability, first_sn); + // Clear the buffer as it's no longer required + _z_wbuf_clear(&frag_buff); + return ret; +} + +#else +static z_result_t _z_transport_tx_send_fragment(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, _z_zint_t first_sn) { + _ZP_UNUSED(ztc); + _ZP_UNUSED(fbf); + _ZP_UNUSED(n_msg); + _ZP_UNUSED(reliability); + _ZP_UNUSED(first_sn); + _Z_INFO("Sending the message required fragmentation feature that is deactivated."); + return _Z_RES_OK; +} +#endif + +static inline bool _z_transport_tx_batch_has_data(_z_transport_common_t *ztc) { +#if Z_FEATURE_BATCHING == 1 + return (ztc->_batch_state == _Z_BATCHING_ACTIVE) && (ztc->_batch_count > 0); +#else + _ZP_UNUSED(ztc); + return false; +#endif +} + +static z_result_t _z_transport_tx_flush_buffer(_z_transport_common_t *ztc) { + // Send network message + __unsafe_z_finalize_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztc->_link, &ztc->_wbuf)); + ztc->_transmitted = true; // Tell session we transmitted data +#if Z_FEATURE_BATCHING == 1 + ztc->_batch_count = 0; +#endif + return _Z_RES_OK; +} + +static z_result_t _z_transport_tx_flush_or_incr_batch(_z_transport_common_t *ztc) { +#if Z_FEATURE_BATCHING == 1 + if (ztc->_batch_state == _Z_BATCHING_ACTIVE) { + // Increment batch count + ztc->_batch_count++; + return _Z_RES_OK; + } else { + return _z_transport_tx_flush_buffer(ztc); + } +#else + return _z_transport_tx_flush_buffer(ztc); +#endif +} + +static z_result_t _z_transport_tx_batch_overflow(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, _z_zint_t sn, size_t prev_wpos) { +#if Z_FEATURE_BATCHING == 1 + // Remove partially encoded data + _z_wbuf_set_wpos(&ztc->_wbuf, prev_wpos); + // Send batch + _Z_RETURN_IF_ERR(_z_transport_tx_flush_buffer(ztc)); + // Init buffer + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + sn = _z_transport_tx_get_sn(ztc, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztc->_wbuf, &t_msg)); + // Retry encode + z_result_t ret = _z_network_message_encode(&ztc->_wbuf, n_msg); + if (ret != _Z_RES_OK) { + // Message still doesn't fit in buffer, send as fragments + return _z_transport_tx_send_fragment(ztc, n_msg, reliability, sn); + } else { + // Increment batch + ztc->_batch_count++; + } + return _Z_RES_OK; +#else + _ZP_UNUSED(ztc); + _ZP_UNUSED(n_msg); + _ZP_UNUSED(reliability); + _ZP_UNUSED(sn); + _ZP_UNUSED(prev_wpos); + return _Z_RES_OK; +#endif +} + +static size_t _z_transport_tx_save_wpos(_z_wbuf_t *wbuf) { +#if Z_FEATURE_BATCHING == 1 + return _z_wbuf_get_wpos(wbuf); +#else + _ZP_UNUSED(wbuf); + return 0; +#endif +} + +static z_result_t _z_transport_tx_send_n_msg_inner(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability) { + // Init buffer + _z_zint_t sn = 0; + bool batch_has_data = _z_transport_tx_batch_has_data(ztc); + if (!batch_has_data) { + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + sn = _z_transport_tx_get_sn(ztc, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztc->_wbuf, &t_msg)); + } + // Try encoding the network message + size_t prev_wpos = _z_transport_tx_save_wpos(&ztc->_wbuf); + z_result_t ret = _z_network_message_encode(&ztc->_wbuf, n_msg); + if (ret == _Z_RES_OK) { + // Flush buffer or increase batch + return _z_transport_tx_flush_or_incr_batch(ztc); + } else if (!batch_has_data) { + // Message doesn't fit in buffer, send as fragments + return _z_transport_tx_send_fragment(ztc, n_msg, reliability, sn); + } else { + // Buffer is too full for message + return _z_transport_tx_batch_overflow(ztc, n_msg, reliability, sn, prev_wpos); + } +} + +z_result_t _z_transport_tx_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg) { + z_result_t ret = _Z_RES_OK; + _Z_DEBUG("Send session message"); + _z_transport_tx_mutex_lock(ztc, true); + + // Encode transport message + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + ret = _z_transport_message_encode(&ztc->_wbuf, t_msg); + if (ret == _Z_RES_OK) { + // Send message + __unsafe_z_finalize_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + ret = _z_link_send_wbuf(&ztc->_link, &ztc->_wbuf); + if (ret == _Z_RES_OK) { + ztc->_transmitted = true; // Tell session we transmitted data + } + } + _z_transport_tx_mutex_unlock(ztc); + return ret; +} + +static z_result_t _z_transport_tx_send_n_msg(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + _Z_DEBUG("Send network message"); + + // Acquire the lock and drop the message if needed + ret = _z_transport_tx_mutex_lock(ztc, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh message because of congestion control"); + return ret; + } + // Process message + ret = _z_transport_tx_send_n_msg_inner(ztc, n_msg, reliability); + _z_transport_tx_mutex_unlock(ztc); + return ret; +} + +static z_result_t _z_transport_tx_send_n_batch(_z_transport_common_t *ztc, z_congestion_control_t cong_ctrl) { +#if Z_FEATURE_BATCHING == 1 + // Check batch size + if (ztc->_batch_count > 0) { + // Acquire the lock and drop the message if needed + z_result_t ret = _z_transport_tx_mutex_lock(ztc, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh batch because of congestion control"); + return ret; + } + // Send batch + _Z_DEBUG("Send network batch"); + ret = _z_transport_tx_flush_buffer(ztc); + _z_transport_tx_mutex_unlock(ztc); + return ret; + } + return _Z_RES_OK; +#else + _ZP_UNUSED(ztc); + _ZP_UNUSED(cong_ctrl); + return _Z_RES_OK; +#endif +} + /** * This function is unsafe because it operates in potentially concurrent data. * Make sure that the following mutexes are locked before calling this function: @@ -74,13 +303,13 @@ z_result_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg z_result_t ret = _Z_RES_OK; switch (zt->_type) { case _Z_TRANSPORT_UNICAST_TYPE: - ret = _z_unicast_send_t_msg(&zt->_transport._unicast, t_msg); + ret = _z_transport_tx_send_t_msg(&zt->_transport._unicast._common, t_msg); break; case _Z_TRANSPORT_MULTICAST_TYPE: - ret = _z_multicast_send_t_msg(&zt->_transport._multicast, t_msg); + ret = _z_transport_tx_send_t_msg(&zt->_transport._multicast._common, t_msg); break; case _Z_TRANSPORT_RAWETH_TYPE: - ret = _z_raweth_send_t_msg(&zt->_transport._raweth, t_msg); + ret = _z_raweth_send_t_msg(&zt->_transport._raweth._common, t_msg); break; default: ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; @@ -164,3 +393,45 @@ z_result_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z return ret; } + +z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, + z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + // Call transport function + switch (zn->_tp._type) { + case _Z_TRANSPORT_UNICAST_TYPE: + ret = _z_transport_tx_send_n_msg(&zn->_tp._transport._unicast._common, z_msg, reliability, cong_ctrl); + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + ret = _z_transport_tx_send_n_msg(&zn->_tp._transport._multicast._common, z_msg, reliability, cong_ctrl); + break; + case _Z_TRANSPORT_RAWETH_TYPE: + ret = _z_raweth_send_n_msg(zn, z_msg, reliability, cong_ctrl); + break; + default: + ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; + break; + } + return ret; +} + +z_result_t _z_send_n_batch(_z_session_t *zn, z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + // Call transport function + switch (zn->_tp._type) { + case _Z_TRANSPORT_UNICAST_TYPE: + ret = _z_transport_tx_send_n_batch(&zn->_tp._transport._unicast._common, cong_ctrl); + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + ret = _z_transport_tx_send_n_batch(&zn->_tp._transport._multicast._common, cong_ctrl); + break; + case _Z_TRANSPORT_RAWETH_TYPE: + _Z_INFO("Batching not yet supported on raweth transport"); + ret = _Z_ERR_TRANSPORT_TX_FAILED; + break; + default: + ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; + break; + } + return ret; +} diff --git a/src/transport/manager.c b/src/transport/manager.c index 360f5329d..6b2447eea 100644 --- a/src/transport/manager.c +++ b/src/transport/manager.c @@ -20,7 +20,7 @@ #include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/unicast/transport.h" -z_result_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { +static z_result_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { z_result_t ret = _Z_RES_OK; // Init link _z_link_t zl; @@ -62,20 +62,24 @@ z_result_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_ return ret; } -z_result_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { +static z_result_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid, int peer_op) { z_result_t ret = _Z_RES_OK; // Init link _z_link_t zl; memset(&zl, 0, sizeof(_z_link_t)); // Listen link - ret = _z_listen_link(&zl, locator); + if (peer_op == _Z_PEER_OP_OPEN) { + ret = _z_open_link(&zl, locator); + } else { + ret = _z_listen_link(&zl, locator); + } if (ret != _Z_RES_OK) { return ret; } switch (zl._cap._transport) { case Z_LINK_CAP_TRANSPORT_UNICAST: { _z_transport_unicast_establish_param_t tp_param; - ret = _z_unicast_open_peer(&tp_param, &zl, local_zid); + ret = _z_unicast_open_peer(&tp_param, &zl, local_zid, peer_op); if (ret != _Z_RES_OK) { _z_link_clear(&zl); return ret; @@ -101,13 +105,13 @@ z_result_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id return ret; } -z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode) { +z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode, int peer_op) { z_result_t ret; if (mode == Z_WHATAMI_CLIENT) { ret = _z_new_transport_client(zt, locator, bs); } else { - ret = _z_new_transport_peer(zt, locator, bs); + ret = _z_new_transport_peer(zt, locator, bs, peer_op); } return ret; diff --git a/src/transport/multicast.c b/src/transport/multicast.c index 42059f6dc..eae7f7bc7 100644 --- a/src/transport/multicast.c +++ b/src/transport/multicast.c @@ -24,10 +24,10 @@ #include "zenoh-pico/transport/common/read.h" #include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/multicast/rx.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/uuid.h" #if Z_FEATURE_MULTICAST_TRANSPORT == 1 void _zp_multicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { @@ -45,9 +45,8 @@ void _zp_multicast_info_session(const _z_transport_t *zt, _z_config_t *ps) { _z_transport_peer_entry_list_t *xs = zt->_transport._multicast._peers; while (xs != NULL) { _z_transport_peer_entry_t *peer = _z_transport_peer_entry_list_head(xs); - _z_slice_t remote_zid = _z_slice_alias_buf(peer->_remote_zid.id, _z_id_len(peer->_remote_zid)); - _z_string_t remote_zid_str = _z_string_convert_bytes(&remote_zid); - _zp_config_insert(ps, Z_INFO_PEER_PID_KEY, _z_string_data(&remote_zid_str)); + _z_string_t remote_zid_str = _z_id_to_string(&peer->_remote_zid); + _zp_config_insert_string(ps, Z_INFO_PEER_PID_KEY, &remote_zid_str); _z_string_clear(&remote_zid_str); xs = _z_transport_peer_entry_list_tail(xs); diff --git a/src/transport/multicast/lease.c b/src/transport/multicast/lease.c index 50c299f3a..b8f98cd19 100644 --- a/src/transport/multicast/lease.c +++ b/src/transport/multicast/lease.c @@ -17,6 +17,7 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/session/query.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/multicast/lease.h" #include "zenoh-pico/utils/logging.h" @@ -26,18 +27,18 @@ z_result_t _zp_multicast_send_join(_z_transport_multicast_t *ztm) { _z_conduit_sn_list_t next_sn; next_sn._is_qos = false; - next_sn._val._plain._best_effort = ztm->_sn_tx_best_effort; - next_sn._val._plain._reliable = ztm->_sn_tx_reliable; + next_sn._val._plain._best_effort = ztm->_common._sn_tx_best_effort; + next_sn._val._plain._reliable = ztm->_common._sn_tx_reliable; - _z_id_t zid = _Z_RC_IN_VAL(ztm->_session)->_local_zid; + _z_id_t zid = _Z_RC_IN_VAL(ztm->_common._session)->_local_zid; _z_transport_message_t jsm = _z_t_msg_make_join(Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, zid, next_sn); - return ztm->_send_f(ztm, &jsm); + return ztm->_send_f(&ztm->_common, &jsm); } z_result_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm) { _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(); - return ztm->_send_f(ztm, &t_msg); + return ztm->_send_f(&ztm->_common, &t_msg); } #else @@ -90,15 +91,15 @@ static _z_zint_t _z_get_next_lease(_z_transport_peer_entry_list_t *peers) { void *_zp_multicast_lease_task(void *ztm_arg) { _z_transport_multicast_t *ztm = (_z_transport_multicast_t *)ztm_arg; - ztm->_transmitted = false; + ztm->_common._transmitted = false; // From all peers, get the next lease time (minimum) - int next_lease = (int)_z_get_minimum_lease(ztm->_peers, ztm->_lease); + int next_lease = (int)_z_get_minimum_lease(ztm->_peers, ztm->_common._lease); int next_keep_alive = (int)(next_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); int next_join = Z_JOIN_INTERVAL; _z_transport_peer_entry_list_t *it = NULL; - while (ztm->_lease_task_running == true) { + while (ztm->_common._lease_task_running == true) { _z_mutex_lock(&ztm->_mutex_peer); if (next_lease <= 0) { @@ -121,7 +122,7 @@ void *_zp_multicast_lease_task(void *ztm_arg) { if (next_join <= 0) { _zp_multicast_send_join(ztm); - ztm->_transmitted = true; + ztm->_common._transmitted = true; // Reset the join parameters next_join = Z_JOIN_INTERVAL; @@ -129,16 +130,18 @@ void *_zp_multicast_lease_task(void *ztm_arg) { if (next_keep_alive <= 0) { // Check if need to send a keep alive - if (ztm->_transmitted == false) { + if (ztm->_common._transmitted == false) { if (_zp_multicast_send_keep_alive(ztm) < 0) { - // TODO: Handle retransmission or error + _Z_INFO("Send keep alive failed."); } } - // Reset the keep alive parameters - ztm->_transmitted = false; - next_keep_alive = (int)(_z_get_minimum_lease(ztm->_peers, ztm->_lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + ztm->_common._transmitted = false; + next_keep_alive = + (int)(_z_get_minimum_lease(ztm->_peers, ztm->_common._lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } + // Query timeout process + _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztm->_common._session)); // Compute the target interval to sleep int interval; @@ -189,19 +192,19 @@ void *_zp_multicast_lease_task(void *ztm_arg) { z_result_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - ztm->_lease_task_running = true; // Init before z_task_init for concurrency issue + ztm->_common._lease_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_multicast_lease_task, ztm) != _Z_RES_OK) { - ztm->_lease_task_running = false; + ztm->_common._lease_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - ztm->_lease_task = task; + ztm->_common._lease_task = task; return _Z_RES_OK; } z_result_t _zp_multicast_stop_lease_task(_z_transport_multicast_t *ztm) { - ztm->_lease_task_running = false; + ztm->_common._lease_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index 965f11a32..bea0b82f3 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -26,17 +26,23 @@ #if Z_FEATURE_MULTICAST_TRANSPORT == 1 +#define _Z_MULTICAST_ADDR_BUFF_SIZE 32 // Arbitrary size that must be able to contain any link address. + z_result_t _zp_multicast_read(_z_transport_multicast_t *ztm) { z_result_t ret = _Z_RES_OK; - _z_slice_t addr; + static uint8_t addr_buff[_Z_MULTICAST_ADDR_BUFF_SIZE] = {0}; + _z_slice_t addr = _z_slice_alias_buf(addr_buff, sizeof(addr_buff)); _z_transport_message_t t_msg; ret = _z_multicast_recv_t_msg(ztm, &t_msg, &addr); if (ret == _Z_RES_OK) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); _z_t_msg_clear(&t_msg); } - + ret = _z_multicast_update_rx_buffer(ztm); + if (ret != _Z_RES_OK) { + _Z_ERROR("Failed to allocate rx buffer"); + } return ret; } #else @@ -52,41 +58,42 @@ void *_zp_multicast_read_task(void *ztm_arg) { _z_transport_multicast_t *ztm = (_z_transport_multicast_t *)ztm_arg; // Acquire and keep the lock - _z_mutex_lock(&ztm->_mutex_rx); + _z_mutex_lock(&ztm->_common._mutex_rx); // Prepare the buffer - _z_zbuf_reset(&ztm->_zbuf); + _z_zbuf_reset(&ztm->_common._zbuf); - _z_slice_t addr = _z_slice_alias_buf(NULL, 0); - while (ztm->_read_task_running == true) { - // Read bytes from socket to the main buffer + uint8_t addr_buff[_Z_MULTICAST_ADDR_BUFF_SIZE] = {0}; + _z_slice_t addr = _z_slice_alias_buf(addr_buff, sizeof(addr_buff)); + while (ztm->_common._read_task_running == true) { size_t to_read = 0; - switch (ztm->_link._cap._flow) { + // Read bytes from socket to the main buffer + switch (ztm->_common._link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, &addr); - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_slice_clear(&addr); - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, &addr); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztm->_common._zbuf); continue; } } // Get stream size - to_read = _z_read_stream_size(&ztm->_zbuf); + to_read = _z_read_stream_size(&ztm->_common._zbuf); // Read data - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, NULL); - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, NULL); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztm->_common._zbuf, + _z_zbuf_get_rpos(&ztm->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztm->_common._zbuf); continue; } } break; case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztm->_zbuf); - to_read = _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, &addr); + _z_zbuf_compact(&ztm->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, &addr); if (to_read == SIZE_MAX) { continue; } @@ -94,55 +101,56 @@ void *_zp_multicast_read_task(void *ztm_arg) { default: break; } - // Wrap the main buffer for to_read bytes - _z_zbuf_t zbuf = _z_zbuf_view(&ztm->_zbuf, to_read); + // Wrap the main buffer to_read bytes + _z_zbuf_t zbuf = _z_zbuf_view(&ztm->_common._zbuf, to_read); while (_z_zbuf_len(&zbuf) > 0) { - z_result_t ret = _Z_RES_OK; - // Decode one session message _z_transport_message_t t_msg; - ret = _z_transport_message_decode(&t_msg, &zbuf); + z_result_t ret = + _z_transport_message_decode(&t_msg, &zbuf, &ztm->_common._arc_pool, &ztm->_common._msg_pool); if (ret == _Z_RES_OK) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); if (ret == _Z_RES_OK) { _z_t_msg_clear(&t_msg); - _z_slice_clear(&addr); } else { - ztm->_read_task_running = false; + _Z_ERROR("Dropping message due to processing error: %d", ret); continue; } } else { - _Z_ERROR("Connection closed due to malformed message"); - ztm->_read_task_running = false; + _Z_ERROR("Connection closed due to malformed message: %d", ret); + ztm->_common._read_task_running = false; continue; } } - // Move the read position of the read buffer - _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) + to_read); + _z_zbuf_set_rpos(&ztm->_common._zbuf, _z_zbuf_get_rpos(&ztm->_common._zbuf) + to_read); + if (_z_multicast_update_rx_buffer(ztm) != _Z_RES_OK) { + _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); + ztm->_common._read_task_running = false; + } } - _z_mutex_unlock(&ztm->_mutex_rx); + _z_mutex_unlock(&ztm->_common._mutex_rx); return NULL; } z_result_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._multicast._read_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._multicast._common._read_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_multicast_read_task, &zt->_transport._multicast) != _Z_RES_OK) { - zt->_transport._multicast._read_task_running = false; + zt->_transport._multicast._common._read_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._multicast._read_task = task; + zt->_transport._multicast._common._read_task = task; return _Z_RES_OK; } z_result_t _zp_multicast_stop_read_task(_z_transport_t *zt) { - zt->_transport._multicast._read_task_running = false; + zt->_transport._multicast._common._read_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index d531c6199..1ab13f161 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -25,6 +25,7 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/multicast/rx.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -34,31 +35,28 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_transport_rx_mutex_lock(&ztm->_common); size_t to_read = 0; do { - switch (ztm->_link._cap._flow) { + switch (ztm->_common._link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztm->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; break; } } // Get stream size - to_read = _z_read_stream_size(&ztm->_zbuf); + to_read = _z_read_stream_size(&ztm->_common._zbuf); // Read data - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztm->_common._zbuf, + _z_zbuf_get_rpos(&ztm->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztm->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; break; } @@ -66,8 +64,8 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t break; // Datagram capable links case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztm->_zbuf); - to_read = _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); + _z_zbuf_compact(&ztm->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); if (to_read == SIZE_MAX) { ret = _Z_ERR_TRANSPORT_RX_FAILED; } @@ -78,14 +76,10 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t } while (false); // The 1-iteration loop to use continue to break the entire loop on error if (ret == _Z_RES_OK) { - _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); - ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); + _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_common._zbuf)); + ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf, &ztm->_common._arc_pool, &ztm->_common._msg_pool); } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_transport_rx_mutex_unlock(&ztm->_common); return ret; } @@ -124,23 +118,22 @@ static _z_transport_peer_entry_t *_z_find_peer_entry(_z_transport_peer_entry_lis z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire and keep the lock - _z_mutex_lock(&ztm->_mutex_peer); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_peer_mutex_lock(ztm); // Mark the session that we have received data from this peer _z_transport_peer_entry_t *entry = _z_find_peer_entry(ztm->_peers, addr); switch (_Z_MID(t_msg->_header)) { case _Z_MID_T_FRAME: { - _Z_INFO("Received _Z_FRAME message"); + _Z_DEBUG("Received _Z_FRAME message"); if (entry == NULL) { + _Z_INFO("Dropping _Z_FRAME from unknown peer"); break; } + // Note that we receive data from peer entry->_received = true; - + z_reliability_t tmsg_reliability; // Check if the SN is correct if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; // @TODO: amend once reliability is in place. For the time being only // monotonic SNs are ensured if (_z_sn_precedes(entry->_sn_res, entry->_sn_rx_sns._val._plain._reliable, t_msg->_body._frame._sn) == @@ -148,17 +141,20 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, entry->_sn_rx_sns._val._plain._reliable = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 + entry->_state_reliable = _Z_DBUF_STATE_NULL; _z_wbuf_clear(&entry->_dbuf_reliable); #endif _Z_INFO("Reliable message dropped because it is out of order"); break; } } else { + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; if (_z_sn_precedes(entry->_sn_res, entry->_sn_rx_sns._val._plain._best_effort, t_msg->_body._frame._sn) == true) { entry->_sn_rx_sns._val._plain._best_effort = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 + entry->_state_best_effort = _Z_DBUF_STATE_NULL; _z_wbuf_clear(&entry->_dbuf_best_effort); #endif _Z_INFO("Best effort message dropped because it is out of order"); @@ -168,64 +164,99 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, // Handle all the zenoh message, one by one uint16_t mapping = entry->_peer_id; - size_t len = _z_vec_len(&t_msg->_body._frame._messages); + size_t len = _z_svec_len(&t_msg->_body._frame._messages); for (size_t i = 0; i < len; i++) { - _z_network_message_t *zm = _z_network_message_vec_get(&t_msg->_body._frame._messages, i); - zm->_reliability = _z_t_msg_get_reliability(t_msg); + _z_network_message_t *zm = _z_network_message_svec_get(&t_msg->_body._frame._messages, i); + zm->_reliability = tmsg_reliability; _z_msg_fix_mapping(zm, mapping); - _z_handle_network_message(ztm->_session, zm, mapping); + _z_handle_network_message(ztm->_common._session, zm, mapping); } break; } case _Z_MID_T_FRAGMENT: { - _Z_INFO("Received Z_FRAGMENT message"); + _Z_DEBUG("Received Z_FRAGMENT message"); #if Z_FEATURE_FRAGMENTATION == 1 if (entry == NULL) { + _Z_INFO("Dropping Z_FRAGMENT from unknown peer"); break; } + // Note that we receive data from the peer entry->_received = true; - _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) - ? &entry->_dbuf_reliable - : &entry->_dbuf_best_effort; // Select the right defragmentation buffer - - bool drop = false; - if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { - // Filling the wbuf capacity as a way to signaling the last fragment to reset the dbuf - // Otherwise, last (smaller) fragments can be understood as a complete message - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, _z_wbuf_space_left(dbuf)); - drop = true; + _z_wbuf_t *dbuf; + uint8_t *dbuf_state; + z_reliability_t tmsg_reliability; + // Select the right defragmentation buffer + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R)) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; + dbuf = &entry->_dbuf_reliable; + dbuf_state = &entry->_state_reliable; } else { - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, - t_msg->_body._fragment._payload.len); + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; + dbuf = &entry->_dbuf_best_effort; + dbuf_state = &entry->_state_best_effort; } - + // Allocate buffer if needed + if (*dbuf_state == _Z_DBUF_STATE_NULL) { + *dbuf = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); + if (_z_wbuf_capacity(dbuf) != Z_FRAG_MAX_SIZE) { + _Z_ERROR("Not enough memory to allocate peer defragmentation buffer"); + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + *dbuf_state = _Z_DBUF_STATE_INIT; + } + // Process fragment data + if (*dbuf_state == _Z_DBUF_STATE_INIT) { + // Check overflow + if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { + *dbuf_state = _Z_DBUF_STATE_OVERFLOW; + } else { + // Fill buffer + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, + t_msg->_body._fragment._payload.len); + } + } + // Process final fragment if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_M) == false) { - if (drop == true) { // Drop message if it exceeds the fragmentation size - _z_wbuf_reset(dbuf); + // Drop message if it exceeds the fragmentation size + if (*dbuf_state == _Z_DBUF_STATE_OVERFLOW) { + _Z_INFO("Fragment dropped because defragmentation buffer has overflown"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; break; } - - _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); // Convert the defragmentation buffer into a decoding buffer - - _z_zenoh_message_t zm; - ret = _z_network_message_decode(&zm, &zbf); - zm._reliability = _z_t_msg_get_reliability(t_msg); + // Convert the defragmentation buffer into a decoding buffer + _z_zbuf_t zbf = _z_wbuf_moved_as_zbuf(dbuf); + if (_z_zbuf_capacity(&zbf) == 0) { + _Z_ERROR("Failed to convert defragmentation buffer into a decoding buffer!"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + // Decode message + _z_zenoh_message_t zm = {0}; + assert(ztm->_common._arc_pool._capacity >= 1); + _z_arc_slice_t *arcs = _z_arc_slice_svec_get_mut(&ztm->_common._arc_pool, 0); + ret = _z_network_message_decode(&zm, &zbf, arcs); + zm._reliability = tmsg_reliability; if (ret == _Z_RES_OK) { uint16_t mapping = entry->_peer_id; _z_msg_fix_mapping(&zm, mapping); - _z_handle_network_message(ztm->_session, &zm, mapping); - _z_msg_clear(&zm); // Clear must be explicitly called for fragmented zenoh messages. Non-fragmented - // zenoh messages are released when their transport message is released. + _z_handle_network_message(ztm->_common._session, &zm, mapping); + } else { + _Z_INFO("Failed to decode defragmented message"); + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - + // Fragmented messages must be cleared. Non-fragmented messages are released with their transport. + _z_msg_clear(&zm); // Free the decoding buffer _z_zbuf_clear(&zbf); - // Reset the defragmentation buffer - _z_wbuf_reset(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; } #else _Z_INFO("Fragment dropped because fragmentation feature is deactivated"); @@ -234,7 +265,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } case _Z_MID_T_KEEP_ALIVE: { - _Z_INFO("Received _Z_KEEP_ALIVE message"); + _Z_DEBUG("Received _Z_KEEP_ALIVE message"); if (entry == NULL) { break; } @@ -254,7 +285,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } case _Z_MID_T_JOIN: { - _Z_INFO("Received _Z_JOIN message"); + _Z_DEBUG("Received _Z_JOIN message"); if (t_msg->_body._join._version != Z_PROTO_VERSION) { break; } @@ -280,18 +311,10 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_conduit_sn_list_decrement(entry->_sn_res, &entry->_sn_rx_sns); #if Z_FEATURE_FRAGMENTATION == 1 -#if Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION == 1 - entry->_dbuf_reliable = _z_wbuf_make(0, true); - entry->_dbuf_best_effort = _z_wbuf_make(0, true); -#else - entry->_dbuf_reliable = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); - entry->_dbuf_best_effort = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); - - if ((_z_wbuf_capacity(&entry->_dbuf_reliable) != Z_FRAG_MAX_SIZE) || - (_z_wbuf_capacity(&entry->_dbuf_best_effort) != Z_FRAG_MAX_SIZE)) { - _Z_ERROR("Not enough memory to allocate peer defragmentation buffers!"); - } -#endif + entry->_state_reliable = _Z_DBUF_STATE_NULL; + entry->_state_best_effort = _Z_DBUF_STATE_NULL; + entry->_dbuf_reliable = _z_wbuf_null(); + entry->_dbuf_best_effort = _z_wbuf_null(); #endif // Update lease time (set as ms during) entry->_lease = t_msg->_body._join._lease; @@ -343,13 +366,30 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, break; } } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_peer); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_peer_mutex_unlock(ztm); return ret; } + +z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm) { + // Check if user or defragment buffer took ownership of buffer + if (_z_zbuf_get_ref_count(&ztm->_common._zbuf) != 1) { + // Allocate a new buffer + _z_zbuf_t new_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + if (_z_zbuf_capacity(&new_zbuf) != Z_BATCH_MULTICAST_SIZE) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Recopy leftover bytes + size_t leftovers = _z_zbuf_len(&ztm->_common._zbuf); + if (leftovers > 0) { + _z_zbuf_copy_bytes(&new_zbuf, &ztm->_common._zbuf); + } + // Drop buffer & update + _z_zbuf_clear(&ztm->_common._zbuf); + ztm->_common._zbuf = new_zbuf; + } + return _Z_RES_OK; +} + #else z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index d0f6abb3a..bbe13bf19 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -11,6 +11,8 @@ // Contributors: // ZettaScale Zenoh Team, +#include "zenoh-pico/transport/multicast/transport.h" + #include #include #include @@ -23,7 +25,6 @@ #include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/multicast.h" #include "zenoh-pico/transport/multicast/rx.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/raweth/tx.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/utils.h" @@ -40,7 +41,7 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, case Z_LINK_CAP_TRANSPORT_MULTICAST: zt->_type = _Z_TRANSPORT_MULTICAST_TYPE; ztm = &zt->_transport._multicast; - ztm->_send_f = _z_multicast_send_t_msg; + ztm->_send_f = _z_transport_tx_send_t_msg; break; case Z_LINK_CAP_TRANSPORT_RAWETH: zt->_type = _Z_TRANSPORT_RAWETH_TYPE; @@ -50,19 +51,26 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, default: return _Z_ERR_GENERIC; } + +// Initialize batching data +#if Z_FEATURE_BATCHING == 1 + ztm->_common._batch_state = _Z_BATCHING_IDLE; + ztm->_common._batch_count = 0; +#endif + #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = _z_mutex_init(&ztm->_mutex_tx); + ret = _z_mutex_init(&ztm->_common._mutex_tx); if (ret == _Z_RES_OK) { - ret = _z_mutex_init(&ztm->_mutex_rx); + ret = _z_mutex_init(&ztm->_common._mutex_rx); if (ret == _Z_RES_OK) { ret = _z_mutex_init(&ztm->_mutex_peer); if (ret != _Z_RES_OK) { - _z_mutex_drop(&ztm->_mutex_tx); - _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_common._mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_rx); } } else { - _z_mutex_drop(&ztm->_mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 @@ -70,51 +78,57 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, // Initialize the read and write buffers if (ret == _Z_RES_OK) { uint16_t mtu = (zl->_mtu < Z_BATCH_MULTICAST_SIZE) ? zl->_mtu : Z_BATCH_MULTICAST_SIZE; - ztm->_wbuf = _z_wbuf_make(mtu, false); - ztm->_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + ztm->_common._wbuf = _z_wbuf_make(mtu, false); + ztm->_common._zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + + // Initialize resource pool + ztm->_common._arc_pool = _z_arc_slice_svec_make(_Z_RES_POOL_INIT_SIZE); + ztm->_common._msg_pool = _z_network_message_svec_make(_Z_RES_POOL_INIT_SIZE); // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&ztm->_wbuf) != mtu) || (_z_zbuf_capacity(&ztm->_zbuf) != Z_BATCH_MULTICAST_SIZE)) { + if ((ztm->_common._msg_pool._capacity == 0) || (ztm->_common._arc_pool._capacity == 0) || + (_z_wbuf_capacity(&ztm->_common._wbuf) != mtu) || + (_z_zbuf_capacity(&ztm->_common._zbuf) != Z_BATCH_MULTICAST_SIZE)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&ztm->_mutex_tx); - _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_common._mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_rx); _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 - _z_wbuf_clear(&ztm->_wbuf); - _z_zbuf_clear(&ztm->_zbuf); + _z_wbuf_clear(&ztm->_common._wbuf); + _z_zbuf_clear(&ztm->_common._zbuf); } } if (ret == _Z_RES_OK) { // Set default SN resolution - ztm->_sn_res = _z_sn_max(param->_seq_num_res); + ztm->_common._sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side - ztm->_sn_tx_reliable = param->_initial_sn_tx._val._plain._reliable; - ztm->_sn_tx_best_effort = param->_initial_sn_tx._val._plain._best_effort; + ztm->_common._sn_tx_reliable = param->_initial_sn_tx._val._plain._reliable; + ztm->_common._sn_tx_best_effort = param->_initial_sn_tx._val._plain._best_effort; // Initialize peer list ztm->_peers = _z_transport_peer_entry_list_new(); #if Z_FEATURE_MULTI_THREAD == 1 // Tasks - ztm->_read_task_running = false; - ztm->_read_task = NULL; - ztm->_lease_task_running = false; - ztm->_lease_task = NULL; + ztm->_common._read_task_running = false; + ztm->_common._read_task = NULL; + ztm->_common._lease_task_running = false; + ztm->_common._lease_task = NULL; #endif // Z_FEATURE_MULTI_THREAD == 1 - ztm->_lease = Z_TRANSPORT_LEASE; + ztm->_common._lease = Z_TRANSPORT_LEASE; // Notifiers - ztm->_transmitted = false; + ztm->_common._transmitted = false; // Transport link for multicast - ztm->_link = *zl; + ztm->_common._link = *zl; } return ret; } @@ -136,7 +150,7 @@ z_result_t _z_multicast_open_peer(_z_transport_multicast_establish_param_t *para _z_transport_message_t jsm = _z_t_msg_make_join(Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, zid, next_sn); // Encode and send the message - _Z_INFO("Sending Z_JOIN message"); + _Z_DEBUG("Sending Z_JOIN message"); switch (zl->_cap._transport) { case Z_LINK_CAP_TRANSPORT_MULTICAST: ret = _z_link_send_t_msg(zl, &jsm); @@ -170,7 +184,7 @@ z_result_t _z_multicast_send_close(_z_transport_multicast_t *ztm, uint8_t reason z_result_t ret = _Z_RES_OK; // Send and clear message _z_transport_message_t cm = _z_t_msg_make_close(reason, link_only); - ret = ztm->_send_f(ztm, &cm); + ret = ztm->_send_f(&ztm->_common, &cm); _z_t_msg_clear(&cm); return ret; } @@ -183,27 +197,29 @@ void _z_multicast_transport_clear(_z_transport_t *zt) { _z_transport_multicast_t *ztm = &zt->_transport._multicast; #if Z_FEATURE_MULTI_THREAD == 1 // Clean up tasks - if (ztm->_read_task != NULL) { - _z_task_join(ztm->_read_task); - _z_task_free(&ztm->_read_task); + if (ztm->_common._read_task != NULL) { + _z_task_join(ztm->_common._read_task); + z_free(ztm->_common._read_task); } - if (ztm->_lease_task != NULL) { - _z_task_join(ztm->_lease_task); - _z_task_free(&ztm->_lease_task); + if (ztm->_common._lease_task != NULL) { + _z_task_join(ztm->_common._lease_task); + z_free(ztm->_common._lease_task); } // Clean up the mutexes - _z_mutex_drop(&ztm->_mutex_tx); - _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_common._mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_rx); _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 // Clean up the buffers - _z_wbuf_clear(&ztm->_wbuf); - _z_zbuf_clear(&ztm->_zbuf); + _z_wbuf_clear(&ztm->_common._wbuf); + _z_zbuf_clear(&ztm->_common._zbuf); + _z_arc_slice_svec_release(&ztm->_common._arc_pool); + _z_network_message_svec_release(&ztm->_common._msg_pool); // Clean up peer list _z_transport_peer_entry_list_free(&ztm->_peers); - _z_link_clear(&ztm->_link); + _z_link_clear(&ztm->_common._link); } #else @@ -243,7 +259,6 @@ z_result_t _z_multicast_transport_close(_z_transport_multicast_t *ztm, uint8_t r _ZP_UNUSED(ztm); _ZP_UNUSED(reason); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; - ; } void _z_multicast_transport_clear(_z_transport_t *zt) { _ZP_UNUSED(zt); } diff --git a/src/transport/multicast/tx.c b/src/transport/multicast/tx.c deleted file mode 100644 index df5b3bcdc..000000000 --- a/src/transport/multicast/tx.c +++ /dev/null @@ -1,180 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/transport/common/tx.h" - -#include "zenoh-pico/config.h" -#include "zenoh-pico/protocol/codec/network.h" -#include "zenoh-pico/protocol/codec/transport.h" -#include "zenoh-pico/transport/multicast/tx.h" -#include "zenoh-pico/transport/utils.h" -#include "zenoh-pico/utils/logging.h" - -#if Z_FEATURE_MULTICAST_TRANSPORT == 1 - -/** - * This function is unsafe because it operates in potentially concurrent data. - * Make sure that the following mutexes are locked before calling this function: - * - ztm->_mutex_inner - */ -_z_zint_t __unsafe_z_multicast_get_sn(_z_transport_multicast_t *ztm, z_reliability_t reliability) { - _z_zint_t sn; - if (reliability == Z_RELIABILITY_RELIABLE) { - sn = ztm->_sn_tx_reliable; - ztm->_sn_tx_reliable = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_reliable); - } else { - sn = ztm->_sn_tx_best_effort; - ztm->_sn_tx_best_effort = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_best_effort); - } - return sn; -} - -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send session message"); - -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - // Prepare the buffer eventually reserving space for the message length - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - // Encode the session message - ret = _z_transport_message_encode(&ztm->_wbuf, t_msg); - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - // Send the wbuf on the socket - ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); - if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Mark the session that we have transmitted data - } - } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - return ret; -} - -z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send network message"); - - _z_transport_multicast_t *ztm = &zn->_tp._transport._multicast; - - // Acquire the lock and drop the message if needed - bool drop = false; - if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_lock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - } else { -#if Z_FEATURE_MULTI_THREAD == 1 - z_result_t locked = _z_mutex_try_lock(&ztm->_mutex_tx); - if (locked != 0) { - _Z_INFO("Dropping zenoh message because of congestion control"); - // We failed to acquire the lock, drop the message - drop = true; - } -#endif // Z_FEATURE_MULTI_THREAD == 1 - } - - if (drop == false) { - // Prepare the buffer eventually reserving space for the message length - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); // Get the next sequence number - - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - ret = _z_transport_message_encode(&ztm->_wbuf, &t_msg); // Encode the frame header - if (ret == _Z_RES_OK) { - ret = _z_network_message_encode(&ztm->_wbuf, n_msg); // Encode the network message - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); // Send the wbuf on the socket - if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Mark the session that we have transmitted data - } - } else { -#if Z_FEATURE_FRAGMENTATION == 1 - // The message does not fit in the current batch, let's fragment it - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - - ret = _z_network_message_encode(&fbf, n_msg); // Encode the message on the expandable wbuf - if (ret == _Z_RES_OK) { - bool is_first = true; // Fragment and send the message - while (_z_wbuf_len(&fbf) > 0) { - if (is_first == false) { // Get the fragment sequence number - sn = __unsafe_z_multicast_get_sn(ztm, reliability); - } - is_first = false; - - // Clear the buffer for serialization - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - // Serialize one fragment - ret = __unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, &fbf, reliability, sn); - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); // Send the wbuf on the socket - if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Mark the session that we have transmitted data - } - } else { - _Z_ERROR("Fragment serialization failed with err %d", ret); - } - } - } - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); -#else - _Z_INFO("Sending the message required fragmentation feature that is deactivated."); -#endif - } - } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - } - - return ret; -} - -#else -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - _ZP_UNUSED(ztm); - _ZP_UNUSED(t_msg); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - _ZP_UNUSED(zn); - _ZP_UNUSED(n_msg); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} -#endif // Z_FEATURE_MULTICAST_TRANSPORT == 1 diff --git a/src/transport/peer_entry.c b/src/transport/peer_entry.c index 7d72604e3..b5feffcdb 100644 --- a/src/transport/peer_entry.c +++ b/src/transport/peer_entry.c @@ -28,6 +28,8 @@ void _z_transport_peer_entry_clear(_z_transport_peer_entry_t *src) { void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_transport_peer_entry_t *src) { #if Z_FEATURE_FRAGMENTATION == 1 + dst->_state_reliable = src->_state_reliable; + dst->_state_best_effort = src->_state_best_effort; _z_wbuf_copy(&dst->_dbuf_reliable, &src->_dbuf_reliable); _z_wbuf_copy(&dst->_dbuf_best_effort, &src->_dbuf_best_effort); #endif diff --git a/src/transport/raweth/read.c b/src/transport/raweth/read.c index a2f080e7b..aa9995562 100644 --- a/src/transport/raweth/read.c +++ b/src/transport/raweth/read.c @@ -37,6 +37,10 @@ z_result_t _zp_raweth_read(_z_transport_multicast_t *ztm) { _z_t_msg_clear(&t_msg); } _z_slice_clear(&addr); + ret = _z_raweth_update_rx_buff(ztm); + if (ret != _Z_RES_OK) { + _Z_ERROR("Failed to allocate rx buffer"); + } return ret; } #else @@ -55,7 +59,7 @@ void *_zp_raweth_read_task(void *ztm_arg) { _z_slice_t addr = _z_slice_alias_buf(NULL, 0); // Task loop - while (ztm->_read_task_running == true) { + while (ztm->_common._read_task_running == true) { // Read message from link z_result_t ret = _z_raweth_recv_t_msg(ztm, &t_msg, &addr); switch (ret) { @@ -69,20 +73,26 @@ void *_zp_raweth_read_task(void *ztm_arg) { break; default: // Drop message & stop task - _Z_ERROR("Connection closed due to malformed message"); - ztm->_read_task_running = false; + _Z_ERROR("Connection closed due to malformed message: %d", ret); + ztm->_common._read_task_running = false; _z_slice_clear(&addr); continue; break; } // Process message - if (_z_multicast_handle_transport_message(ztm, &t_msg, &addr) != _Z_RES_OK) { - ztm->_read_task_running = false; + ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); + if (ret != _Z_RES_OK) { + _Z_ERROR("Connection closed due to message processing error: %d", ret); + ztm->_common._read_task_running = false; _z_slice_clear(&addr); continue; } _z_t_msg_clear(&t_msg); _z_slice_clear(&addr); + if (_z_raweth_update_rx_buff(ztm) != _Z_RES_OK) { + _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); + ztm->_common._read_task_running = false; + } } return NULL; } @@ -90,19 +100,19 @@ void *_zp_raweth_read_task(void *ztm_arg) { z_result_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._unicast._lease_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._unicast._common._lease_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_raweth_read_task, &zt->_transport._raweth) != _Z_RES_OK) { - zt->_transport._unicast._lease_task_running = false; + zt->_transport._unicast._common._lease_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._raweth._read_task = task; + zt->_transport._raweth._common._read_task = task; return _Z_RES_OK; } z_result_t _zp_raweth_stop_read_task(_z_transport_t *zt) { - zt->_transport._raweth._read_task_running = false; + zt->_transport._raweth._common._read_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/raweth/rx.c b/src/transport/raweth/rx.c index 59b57e512..fdec282f8 100644 --- a/src/transport/raweth/rx.c +++ b/src/transport/raweth/rx.c @@ -22,6 +22,7 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -77,20 +78,16 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_transport_rx_mutex_lock(&ztm->_common); // Prepare the buffer - _z_zbuf_reset(&ztm->_zbuf); + _z_zbuf_reset(&ztm->_common._zbuf); - switch (ztm->_link._cap._flow) { + switch (ztm->_common._link._cap._flow) { // Datagram capable links case Z_LINK_CAP_FLOW_DATAGRAM: { - _z_zbuf_compact(&ztm->_zbuf); + _z_zbuf_compact(&ztm->_common._zbuf); // Read from link - size_t to_read = _z_raweth_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); + size_t to_read = _z_raweth_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); if (to_read == SIZE_MAX) { ret = _Z_ERR_TRANSPORT_RX_FAILED; } @@ -102,14 +99,10 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m } // Decode message if (ret == _Z_RES_OK) { - _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); - ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); + _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_common._zbuf)); + ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf, &ztm->_common._arc_pool, &ztm->_common._msg_pool); } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_transport_rx_mutex_unlock(&ztm->_common); return ret; } @@ -117,6 +110,26 @@ z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_mess return _z_raweth_recv_t_msg_na(ztm, t_msg, addr); } +z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm) { + // Check if user or defragment buffer took ownership of buffer + if (_z_zbuf_get_ref_count(&ztm->_common._zbuf) != 1) { + // Allocate a new buffer + _z_zbuf_t new_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + if (_z_zbuf_capacity(&new_zbuf) != Z_BATCH_MULTICAST_SIZE) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Recopy leftover bytes + size_t leftovers = _z_zbuf_len(&ztm->_common._zbuf); + if (leftovers > 0) { + _z_zbuf_copy_bytes(&new_zbuf, &ztm->_common._zbuf); + } + // Drop buffer & update + _z_zbuf_clear(&ztm->_common._zbuf); + ztm->_common._zbuf = new_zbuf; + } + return _Z_RES_OK; +} + #else z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { _ZP_UNUSED(ztm); diff --git a/src/transport/raweth/tx.c b/src/transport/raweth/tx.c index b4ddc5def..e44d5bdab 100644 --- a/src/transport/raweth/tx.c +++ b/src/transport/raweth/tx.c @@ -24,18 +24,13 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/system/link/raweth.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_RAWETH_TRANSPORT == 1 -#if Z_FEATURE_MULTI_THREAD == 1 -static void _zp_raweth_unlock_tx_mutex(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_tx); } -#else -static void _zp_raweth_unlock_tx_mutex(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } -#endif - static int _zp_raweth_find_map_entry(const _z_keyexpr_t *keyexpr, _z_raweth_socket_t *sock) { for (size_t i = 0; i < _zp_raweth_mapping_array_len(&sock->_mapping); i++) { // Find matching keyexpr @@ -92,11 +87,11 @@ static z_result_t _zp_raweth_set_socket(const _z_keyexpr_t *keyexpr, _z_raweth_s static _z_zint_t __unsafe_z_raweth_get_sn(_z_transport_multicast_t *ztm, z_reliability_t reliability) { _z_zint_t sn; if (reliability == Z_RELIABILITY_RELIABLE) { - sn = ztm->_sn_tx_reliable; - ztm->_sn_tx_reliable = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_reliable); + sn = ztm->_common._sn_tx_reliable; + ztm->_common._sn_tx_reliable = _z_sn_increment(ztm->_common._sn_res, ztm->_common._sn_tx_reliable); } else { - sn = ztm->_sn_tx_best_effort; - ztm->_sn_tx_best_effort = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_best_effort); + sn = ztm->_common._sn_tx_best_effort; + ztm->_common._sn_tx_best_effort = _z_sn_increment(ztm->_common._sn_res, ztm->_common._sn_tx_best_effort); } return sn; } @@ -192,32 +187,26 @@ z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_mes return ret; } -z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { +z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg) { z_result_t ret = _Z_RES_OK; _Z_DEBUG(">> send session message"); -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_lock(&ztm->_mutex_tx); -#endif + _z_transport_tx_mutex_lock(ztc, true); // Reset wbuf - _z_wbuf_reset(&ztm->_wbuf); + _z_wbuf_reset(&ztc->_wbuf); // Set socket info - _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(NULL, &ztm->_link._socket._raweth), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(NULL, &ztc->_link._socket._raweth), _z_transport_tx_mutex_unlock(ztc)); // Prepare buff - __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); + __unsafe_z_raweth_prepare_header(&ztc->_link, &ztc->_wbuf); // Encode the session message - _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, t_msg), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztc->_wbuf, t_msg), _z_transport_tx_mutex_unlock(ztc)); // Write the message header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztc->_link, &ztc->_wbuf), _z_transport_tx_mutex_unlock(ztc)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztc->_link, &ztc->_wbuf), _z_transport_tx_mutex_unlock(ztc)); // Mark the session that we have transmitted data - ztm->_transmitted = true; - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif - + ztc->_transmitted = true; + _z_transport_tx_mutex_unlock(ztc); return ret; } @@ -228,20 +217,11 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ _Z_DEBUG(">> send network message"); // Acquire the lock and drop the message if needed -#if Z_FEATURE_MULTI_THREAD == 1 - if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { - _z_mutex_lock(&ztm->_mutex_tx); - } else { - if (_z_mutex_try_lock(&ztm->_mutex_tx) != 0) { - _Z_INFO("Dropping zenoh message because of congestion control"); - // We failed to acquire the lock, drop the message - return ret; - } + ret = _z_transport_tx_mutex_lock(&ztm->_common, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh message because of congestion control"); + return ret; } -#else - _ZP_UNUSED(cong_ctrl); -#endif // Z_FEATURE_MULTI_THREAD == 1 - const _z_keyexpr_t *keyexpr = NULL; switch (n_msg->_tag) { case _Z_N_PUSH: @@ -259,32 +239,34 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ break; } // Reset wbuf - _z_wbuf_reset(&ztm->_wbuf); + _z_wbuf_reset(&ztm->_common._wbuf); // Set socket info - _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(keyexpr, &ztm->_link._socket._raweth), - _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(keyexpr, &ztm->_common._link._socket._raweth), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Prepare buff - __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); + __unsafe_z_raweth_prepare_header(&ztm->_common._link, &ztm->_common._wbuf); // Set the frame header _z_zint_t sn = __unsafe_z_raweth_get_sn(ztm, reliability); _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); // Encode the frame header - _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_common._wbuf, &t_msg), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Encode the network message - if (_z_network_message_encode(&ztm->_wbuf, n_msg) == _Z_RES_OK) { + if (_z_network_message_encode(&ztm->_common._wbuf, n_msg) == _Z_RES_OK) { // Write the eth header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), - _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Mark the session that we have transmitted data - ztm->_transmitted = true; + ztm->_common._transmitted = true; } else { // The message does not fit in the current batch, let's fragment it #if Z_FEATURE_FRAGMENTATION == 1 // Create an expandable wbuf for fragmentation _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); // Encode the message on the expandable wbuf - _Z_CLEAN_RETURN_IF_ERR(_z_network_message_encode(&fbf, n_msg), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_network_message_encode(&fbf, n_msg), _z_transport_tx_mutex_unlock(&ztm->_common)); // Fragment and send the message bool is_first = true; while (_z_wbuf_len(&fbf) > 0) { @@ -294,19 +276,20 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ } is_first = false; // Reset wbuf - _z_wbuf_reset(&ztm->_wbuf); + _z_wbuf_reset(&ztm->_common._wbuf); // Prepare buff - __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); + __unsafe_z_raweth_prepare_header(&ztm->_common._link, &ztm->_common._wbuf); // Serialize one fragment - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, &fbf, reliability, sn), - _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_serialize_zenoh_fragment(&ztm->_common._wbuf, &fbf, reliability, sn), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Write the eth header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), - _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Mark the session that we have transmitted data - ztm->_transmitted = true; + ztm->_common._transmitted = true; } // Clear the expandable buffer _z_wbuf_clear(&fbf); @@ -314,9 +297,7 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ _Z_INFO("Sending the message required fragmentation feature that is deactivated."); #endif } -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _z_transport_tx_mutex_unlock(&ztm->_common); return ret; } @@ -326,8 +307,8 @@ z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_mes _ZP_UNUSED(t_msg); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } -z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - _ZP_UNUSED(ztm); +z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg) { + _ZP_UNUSED(ztc); _ZP_UNUSED(t_msg); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } diff --git a/src/transport/transport.c b/src/transport/transport.c index 5aee622c6..2540ec5ac 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -22,13 +22,11 @@ #include "zenoh-pico/link/link.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/multicast/rx.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/raweth/rx.h" #include "zenoh-pico/transport/raweth/tx.h" #include "zenoh-pico/transport/transport.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/unicast/transport.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -78,6 +76,53 @@ void _z_transport_free(_z_transport_t **zt) { *zt = NULL; } +#if Z_FEATURE_BATCHING == 1 +bool _z_transport_start_batching(_z_transport_t *zt) { + uint8_t *batch_state = NULL; + size_t *batch_count = NULL; + switch (zt->_type) { + case _Z_TRANSPORT_UNICAST_TYPE: + batch_state = &zt->_transport._unicast._common._batch_state; + batch_count = &zt->_transport._unicast._common._batch_count; + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + batch_state = &zt->_transport._multicast._common._batch_state; + batch_count = &zt->_transport._multicast._common._batch_count; + break; + case _Z_TRANSPORT_RAWETH_TYPE: + batch_state = &zt->_transport._raweth._common._batch_state; + batch_count = &zt->_transport._raweth._common._batch_count; + break; + default: + break; + } + if (*batch_state == _Z_BATCHING_ACTIVE) { + return false; + } + *batch_count = 0; + *batch_state = _Z_BATCHING_ACTIVE; + return true; +} + +void _z_transport_stop_batching(_z_transport_t *zt) { + uint8_t *batch_state = NULL; + switch (zt->_type) { + case _Z_TRANSPORT_UNICAST_TYPE: + batch_state = &zt->_transport._unicast._common._batch_state; + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + batch_state = &zt->_transport._multicast._common._batch_state; + break; + case _Z_TRANSPORT_RAWETH_TYPE: + batch_state = &zt->_transport._raweth._common._batch_state; + break; + default: + break; + } + *batch_state = _Z_BATCHING_IDLE; +} +#endif + /** * @brief Inserts an entry into `root`, allocating it a `_peer_id` * diff --git a/src/transport/unicast.c b/src/transport/unicast.c index dca9ae0ea..2387565cc 100644 --- a/src/transport/unicast.c +++ b/src/transport/unicast.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include "zenoh-pico/link/link.h" #include "zenoh-pico/transport/common/rx.h" @@ -26,9 +24,9 @@ #include "zenoh-pico/transport/unicast/lease.h" #include "zenoh-pico/transport/unicast/read.h" #include "zenoh-pico/transport/unicast/rx.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/uuid.h" #if Z_FEATURE_UNICAST_TRANSPORT == 1 void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { @@ -39,9 +37,9 @@ void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) void _zp_unicast_info_session(const _z_transport_t *zt, _z_config_t *ps) { _z_id_t remote_zid = zt->_transport._unicast._remote_zid; - _z_slice_t remote_zid_bytes = _z_slice_alias_buf(remote_zid.id, _z_id_len(remote_zid)); - _z_string_t remote_zid_str = _z_string_convert_bytes(&remote_zid_bytes); - _zp_config_insert(ps, Z_INFO_ROUTER_PID_KEY, _z_string_data(&remote_zid_str)); + + _z_string_t remote_zid_str = _z_id_to_string(&remote_zid); + _zp_config_insert_string(ps, Z_INFO_ROUTER_PID_KEY, &remote_zid_str); _z_string_clear(&remote_zid_str); } diff --git a/src/transport/unicast/lease.c b/src/transport/unicast/lease.c index 32358eaba..c4cd362f1 100644 --- a/src/transport/unicast/lease.c +++ b/src/transport/unicast/lease.c @@ -14,8 +14,10 @@ #include "zenoh-pico/transport/unicast/lease.h" +#include "zenoh-pico/session/query.h" +#include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/unicast/transport.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_UNICAST_TRANSPORT == 1 @@ -24,7 +26,7 @@ z_result_t _zp_unicast_send_keep_alive(_z_transport_unicast_t *ztu) { z_result_t ret = _Z_RES_OK; _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(); - ret = _z_unicast_send_t_msg(ztu, &t_msg); + ret = _z_transport_tx_send_t_msg(&ztu->_common, &t_msg); return ret; } @@ -42,11 +44,11 @@ void *_zp_unicast_lease_task(void *ztu_arg) { _z_transport_unicast_t *ztu = (_z_transport_unicast_t *)ztu_arg; ztu->_received = false; - ztu->_transmitted = false; + ztu->_common._transmitted = false; - int next_lease = (int)ztu->_lease; - int next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); - while (ztu->_lease_task_running == true) { + int next_lease = (int)ztu->_common._lease; + int next_keep_alive = (int)(ztu->_common._lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + while (ztu->_common._lease_task_running == true) { // Next lease process if (next_lease <= 0) { // Check if received data @@ -54,26 +56,27 @@ void *_zp_unicast_lease_task(void *ztu_arg) { // Reset the lease parameters ztu->_received = false; } else { - _Z_INFO("Closing session because it has expired after %zums", ztu->_lease); - ztu->_lease_task_running = false; + _Z_INFO("Closing session because it has expired after %zums", ztu->_common._lease); + ztu->_common._lease_task_running = false; _z_unicast_transport_close(ztu, _Z_CLOSE_EXPIRED); break; } - next_lease = (int)ztu->_lease; + next_lease = (int)ztu->_common._lease; } // Next keep alive process if (next_keep_alive <= 0) { // Check if need to send a keep alive - if (ztu->_transmitted == false) { + if (ztu->_common._transmitted == false) { if (_zp_unicast_send_keep_alive(ztu) < 0) { - // TODO: Handle retransmission or error + _Z_INFO("Send keep alive failed."); } } - // Reset the keep alive parameters - ztu->_transmitted = false; - next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + ztu->_common._transmitted = false; + next_keep_alive = (int)(ztu->_common._lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } + // Query timeout process + _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztu->_common._session)); // Compute the target interval int interval; @@ -98,18 +101,18 @@ void *_zp_unicast_lease_task(void *ztu_arg) { z_result_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._unicast._lease_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._unicast._common._lease_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_unicast_lease_task, &zt->_transport._unicast) != _Z_RES_OK) { return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._unicast._lease_task = task; + zt->_transport._unicast._common._lease_task = task; return _Z_RES_OK; } z_result_t _zp_unicast_stop_lease_task(_z_transport_t *zt) { - zt->_transport._unicast._lease_task_running = false; + zt->_transport._unicast._common._lease_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index a43f1404c..5851f3146 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -33,7 +33,10 @@ z_result_t _zp_unicast_read(_z_transport_unicast_t *ztu) { ret = _z_unicast_handle_transport_message(ztu, &t_msg); _z_t_msg_clear(&t_msg); } - + ret = _z_unicast_update_rx_buffer(ztu); + if (ret != _Z_RES_OK) { + _Z_ERROR("Failed to allocate rx buffer"); + } return ret; } #else @@ -50,38 +53,39 @@ void *_zp_unicast_read_task(void *ztu_arg) { _z_transport_unicast_t *ztu = (_z_transport_unicast_t *)ztu_arg; // Acquire and keep the lock - _z_mutex_lock(&ztu->_mutex_rx); + _z_mutex_lock(&ztu->_common._mutex_rx); // Prepare the buffer - _z_zbuf_reset(&ztu->_zbuf); + _z_zbuf_reset(&ztu->_common._zbuf); - while (ztu->_read_task_running == true) { + while (ztu->_common._read_task_running == true) { // Read bytes from socket to the main buffer size_t to_read = 0; - switch (ztu->_link._cap._flow) { + switch (ztu->_common._link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztu->_common._zbuf); continue; } } // Get stream size - to_read = _z_read_stream_size(&ztu->_zbuf); + to_read = _z_read_stream_size(&ztu->_common._zbuf); // Read data - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztu->_common._zbuf, + _z_zbuf_get_rpos(&ztu->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztu->_common._zbuf); continue; } } break; case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztu->_zbuf); - to_read = _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); + _z_zbuf_compact(&ztu->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); if (to_read == SIZE_MAX) { continue; } @@ -90,52 +94,62 @@ void *_zp_unicast_read_task(void *ztu_arg) { break; } // Wrap the main buffer for to_read bytes - _z_zbuf_t zbuf = _z_zbuf_view(&ztu->_zbuf, to_read); + _z_zbuf_t zbuf = _z_zbuf_view(&ztu->_common._zbuf, to_read); // Mark the session that we have received data ztu->_received = true; - // Decode one session message - _z_transport_message_t t_msg; - z_result_t ret = _z_transport_message_decode(&t_msg, &zbuf); + while (_z_zbuf_len(&zbuf) > 0) { + // Decode one session message + _z_transport_message_t t_msg; + z_result_t ret = + _z_transport_message_decode(&t_msg, &zbuf, &ztu->_common._arc_pool, &ztu->_common._msg_pool); - if (ret == _Z_RES_OK) { - ret = _z_unicast_handle_transport_message(ztu, &t_msg); if (ret == _Z_RES_OK) { - _z_t_msg_clear(&t_msg); + ret = _z_unicast_handle_transport_message(ztu, &t_msg); + if (ret == _Z_RES_OK) { + _z_t_msg_clear(&t_msg); + } else { + if (ret != _Z_ERR_CONNECTION_CLOSED) { + _Z_ERROR("Connection closed due to message processing error: %d", ret); + } + ztu->_common._read_task_running = false; + continue; + } } else { - ztu->_read_task_running = false; + _Z_ERROR("Connection closed due to malformed message: %d", ret); + ztu->_common._read_task_running = false; continue; } - } else { - _Z_ERROR("Connection closed due to malformed message"); - ztu->_read_task_running = false; - continue; } - // Move the read position of the read buffer - _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) + to_read); + _z_zbuf_set_rpos(&ztu->_common._zbuf, _z_zbuf_get_rpos(&ztu->_common._zbuf) + to_read); + + if (_z_unicast_update_rx_buffer(ztu) != _Z_RES_OK) { + _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); + ztu->_common._read_task_running = false; + } } - _z_mutex_unlock(&ztu->_mutex_rx); + _z_mutex_unlock(&ztu->_common._mutex_rx); return NULL; } z_result_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._unicast._read_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._unicast._common._read_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_unicast_read_task, &zt->_transport._unicast) != _Z_RES_OK) { - zt->_transport._unicast._read_task_running = false; + zt->_transport._unicast._common._read_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._unicast._read_task = task; + zt->_transport._unicast._common._read_task = task; return _Z_RES_OK; } z_result_t _zp_unicast_stop_read_task(_z_transport_t *zt) { - zt->_transport._unicast._read_task_running = false; + zt->_transport._unicast._common._read_task_running = false; return _Z_RES_OK; } diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index 23c6859b9..628f2815d 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -23,6 +23,7 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/unicast/rx.h" +#include "zenoh-pico/transport/unicast/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -31,32 +32,29 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg) { _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztu->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_transport_rx_mutex_lock(&ztu->_common); size_t to_read = 0; do { - switch (ztu->_link._cap._flow) { + switch (ztu->_common._link._cap._flow) { // Stream capable links case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztu->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; continue; } } // Get stream size - to_read = _z_read_stream_size(&ztu->_zbuf); + to_read = _z_read_stream_size(&ztu->_common._zbuf); // Read data - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztu->_common._zbuf, + _z_zbuf_get_rpos(&ztu->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztu->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; continue; } @@ -64,8 +62,8 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me break; // Datagram capable links case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztu->_zbuf); - to_read = _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); + _z_zbuf_compact(&ztu->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); if (to_read == SIZE_MAX) { ret = _Z_ERR_TRANSPORT_RX_FAILED; } @@ -77,18 +75,14 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me if (ret == _Z_RES_OK) { _Z_DEBUG(">> \t transport_message_decode"); - ret = _z_transport_message_decode(t_msg, &ztu->_zbuf); + ret = _z_transport_message_decode(t_msg, &ztu->_common._zbuf, &ztu->_common._arc_pool, &ztu->_common._msg_pool); // Mark the session that we have received data if (ret == _Z_RES_OK) { ztu->_received = true; } } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztu->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_transport_rx_mutex_unlock(&ztu->_common); return ret; } @@ -101,26 +95,31 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t switch (_Z_MID(t_msg->_header)) { case _Z_MID_T_FRAME: { - _Z_INFO("Received Z_FRAME message"); + _Z_DEBUG("Received Z_FRAME message"); + z_reliability_t tmsg_reliability; // Check if the SN is correct if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; // @TODO: amend once reliability is in place. For the time being only // monotonic SNs are ensured - if (_z_sn_precedes(ztu->_sn_res, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { + if (_z_sn_precedes(ztu->_common._sn_res, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_reliable = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_reliable); + ztu->_state_reliable = _Z_DBUF_STATE_NULL; #endif _Z_INFO("Reliable message dropped because it is out of order"); break; } } else { - if (_z_sn_precedes(ztu->_sn_res, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == true) { + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; + if (_z_sn_precedes(ztu->_common._sn_res, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_best_effort = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_best_effort); + ztu->_state_best_effort = _Z_DBUF_STATE_NULL; #endif _Z_INFO("Best effort message dropped because it is out of order"); break; @@ -128,57 +127,88 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } // Handle all the zenoh message, one by one - size_t len = _z_vec_len(&t_msg->_body._frame._messages); + size_t len = _z_svec_len(&t_msg->_body._frame._messages); for (size_t i = 0; i < len; i++) { - _z_network_message_t *zm = _z_network_message_vec_get(&t_msg->_body._frame._messages, i); - zm->_reliability = _z_t_msg_get_reliability(t_msg); - _z_handle_network_message(ztu->_session, zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + _z_network_message_t *zm = _z_network_message_svec_get(&t_msg->_body._frame._messages, i); + zm->_reliability = tmsg_reliability; + _z_handle_network_message(ztu->_common._session, zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); } break; } case _Z_MID_T_FRAGMENT: { - _Z_INFO("Received Z_FRAGMENT message"); + _Z_DEBUG("Received Z_FRAGMENT message"); #if Z_FEATURE_FRAGMENTATION == 1 - _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) - ? &ztu->_dbuf_reliable - : &ztu->_dbuf_best_effort; // Select the right defragmentation buffer - - bool drop = false; - if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { - // Filling the wbuf capacity as a way to signal the last fragment to reset the dbuf - // Otherwise, last (smaller) fragments can be understood as a complete message - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, _z_wbuf_space_left(dbuf)); - drop = true; + _z_wbuf_t *dbuf; + uint8_t *dbuf_state; + z_reliability_t tmsg_reliability; + // Select the right defragmentation buffer + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R)) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; + dbuf = &ztu->_dbuf_reliable; + dbuf_state = &ztu->_state_reliable; } else { - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, - t_msg->_body._fragment._payload.len); + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; + dbuf = &ztu->_dbuf_best_effort; + dbuf_state = &ztu->_state_best_effort; } - + // Allocate buffer if needed + if (*dbuf_state == _Z_DBUF_STATE_NULL) { + *dbuf = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); + if (_z_wbuf_capacity(dbuf) != Z_FRAG_MAX_SIZE) { + _Z_ERROR("Not enough memory to allocate transport defragmentation buffer"); + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + *dbuf_state = _Z_DBUF_STATE_INIT; + } + // Process fragment data + if (*dbuf_state == _Z_DBUF_STATE_INIT) { + // Check overflow + if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { + *dbuf_state = _Z_DBUF_STATE_OVERFLOW; + } else { + // Fill buffer + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, + t_msg->_body._fragment._payload.len); + } + } + // Process final fragment if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_M) == false) { - if (drop == true) { // Drop message if it exceeds the fragmentation size - _z_wbuf_reset(dbuf); + // Drop message if it exceeds the fragmentation size + if (*dbuf_state == _Z_DBUF_STATE_OVERFLOW) { + _Z_INFO("Fragment dropped because defragmentation buffer has overflown"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; break; } - - _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); // Convert the defragmentation buffer into a decoding buffer - - _z_zenoh_message_t zm; - ret = _z_network_message_decode(&zm, &zbf); - zm._reliability = _z_t_msg_get_reliability(t_msg); + // Convert the defragmentation buffer into a decoding buffer + _z_zbuf_t zbf = _z_wbuf_moved_as_zbuf(dbuf); + if (_z_zbuf_capacity(&zbf) == 0) { + _Z_ERROR("Failed to convert defragmentation buffer into a decoding buffer!"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + // Decode message + _z_zenoh_message_t zm = {0}; + assert(ztu->_common._arc_pool._capacity >= 1); + _z_arc_slice_t *arcs = _z_arc_slice_svec_get_mut(&ztu->_common._arc_pool, 0); + ret = _z_network_message_decode(&zm, &zbf, arcs); + zm._reliability = tmsg_reliability; if (ret == _Z_RES_OK) { - _z_handle_network_message(ztu->_session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); - _z_msg_clear(&zm); // Clear must be explicitly called for fragmented zenoh messages. Non-fragmented - // zenoh messages are released when their transport message is released. + _z_handle_network_message(ztu->_common._session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); } else { - _Z_DEBUG("Failed to decode defragmented message"); + _Z_INFO("Failed to decode defragmented message"); + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - + // Fragmented messages must be cleared. Non-fragmented messages are released with their transport. + _z_msg_clear(&zm); // Free the decoding buffer _z_zbuf_clear(&zbf); - // Reset the defragmentation buffer - _z_wbuf_reset(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; } #else _Z_INFO("Fragment dropped because fragmentation feature is deactivated"); @@ -187,7 +217,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } case _Z_MID_T_KEEP_ALIVE: { - _Z_INFO("Received Z_KEEP_ALIVE message"); + _Z_DEBUG("Received Z_KEEP_ALIVE message"); break; } @@ -215,6 +245,28 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t return ret; } + +z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu) { + // Check if user or defragment buffer took ownership of buffer + if (_z_zbuf_get_ref_count(&ztu->_common._zbuf) != 1) { + // Allocate a new buffer + size_t buff_capacity = _z_zbuf_capacity(&ztu->_common._zbuf); + _z_zbuf_t new_zbuf = _z_zbuf_make(buff_capacity); + if (_z_zbuf_capacity(&new_zbuf) != buff_capacity) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Recopy leftover bytes + size_t leftovers = _z_zbuf_len(&ztu->_common._zbuf); + if (leftovers > 0) { + _z_zbuf_copy_bytes(&new_zbuf, &ztu->_common._zbuf); + } + // Drop buffer & update + _z_zbuf_clear(&ztu->_common._zbuf); + ztu->_common._zbuf = new_zbuf; + } + return _Z_RES_OK; +} + #else z_result_t _z_unicast_recv_t_msg(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg) { _ZP_UNUSED(ztu); diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index c4433ac1a..9ae20a38c 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -25,7 +25,6 @@ #include "zenoh-pico/transport/unicast/lease.h" #include "zenoh-pico/transport/unicast/read.h" #include "zenoh-pico/transport/unicast/rx.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -36,14 +35,21 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, z_result_t ret = _Z_RES_OK; zt->_type = _Z_TRANSPORT_UNICAST_TYPE; + _z_transport_unicast_t *ztu = &zt->_transport._unicast; + +// Initialize batching data +#if Z_FEATURE_BATCHING == 1 + ztu->_common._batch_state = _Z_BATCHING_IDLE; + ztu->_common._batch_count = 0; +#endif #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = _z_mutex_init(&zt->_transport._unicast._mutex_tx); + ret = _z_mutex_init(&ztu->_common._mutex_tx); if (ret == _Z_RES_OK) { - ret = _z_mutex_init(&zt->_transport._unicast._mutex_rx); + ret = _z_mutex_init(&ztu->_common._mutex_rx); if (ret != _Z_RES_OK) { - _z_mutex_drop(&zt->_transport._unicast._mutex_tx); + _z_mutex_drop(&ztu->_common._mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 @@ -51,106 +57,75 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, // Initialize the read and write buffers if (ret == _Z_RES_OK) { uint16_t mtu = (zl->_mtu < param->_batch_size) ? zl->_mtu : param->_batch_size; - size_t dbuf_size = 0; size_t wbuf_size = mtu; size_t zbuf_size = param->_batch_size; - bool expandable = false; - - // Set expandable on stream link - if (zl->_cap._flow == Z_LINK_CAP_FLOW_STREAM) { - expandable = true; - } -#if Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION == 0 - expandable = false; - dbuf_size = Z_FRAG_MAX_SIZE; -#endif // Initialize tx rx buffers - zt->_transport._unicast._wbuf = _z_wbuf_make(wbuf_size, false); - zt->_transport._unicast._zbuf = _z_zbuf_make(zbuf_size); + ztu->_common._wbuf = _z_wbuf_make(wbuf_size, false); + ztu->_common._zbuf = _z_zbuf_make(zbuf_size); + + // Initialize resources pool + ztu->_common._arc_pool = _z_arc_slice_svec_make(_Z_RES_POOL_INIT_SIZE); + ztu->_common._msg_pool = _z_network_message_svec_make(_Z_RES_POOL_INIT_SIZE); // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&zt->_transport._unicast._wbuf) != wbuf_size) || - (_z_zbuf_capacity(&zt->_transport._unicast._zbuf) != zbuf_size)) { + if ((ztu->_common._msg_pool._capacity == 0) || (ztu->_common._arc_pool._capacity == 0) || + (_z_wbuf_capacity(&ztu->_common._wbuf) != wbuf_size) || + (_z_zbuf_capacity(&ztu->_common._zbuf) != zbuf_size)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&zt->_transport._unicast._mutex_tx); - _z_mutex_drop(&zt->_transport._unicast._mutex_rx); + _z_mutex_drop(&ztu->_common._mutex_tx); + _z_mutex_drop(&ztu->_common._mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 - _z_wbuf_clear(&zt->_transport._unicast._wbuf); - _z_zbuf_clear(&zt->_transport._unicast._zbuf); + _z_wbuf_clear(&ztu->_common._wbuf); + _z_zbuf_clear(&ztu->_common._zbuf); } #if Z_FEATURE_FRAGMENTATION == 1 // Initialize the defragmentation buffers - zt->_transport._unicast._dbuf_reliable = _z_wbuf_make(dbuf_size, expandable); - zt->_transport._unicast._dbuf_best_effort = _z_wbuf_make(dbuf_size, expandable); - - // Clean up the buffers if one of them failed to be allocated - if ( -#if Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION == 0 - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_reliable) != dbuf_size) || - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_best_effort) != dbuf_size)) { -#else - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_reliable) != Z_IOSLICE_SIZE) || - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_best_effort) != Z_IOSLICE_SIZE)) { -#endif - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; - _Z_ERROR("Not enough memory to allocate transport defragmentation buffers!"); - - _z_wbuf_clear(&zt->_transport._unicast._dbuf_reliable); - _z_wbuf_clear(&zt->_transport._unicast._dbuf_best_effort); - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&zt->_transport._unicast._mutex_tx); - _z_mutex_drop(&zt->_transport._unicast._mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - _z_wbuf_clear(&zt->_transport._unicast._wbuf); - _z_zbuf_clear(&zt->_transport._unicast._zbuf); - } -#else - _ZP_UNUSED(dbuf_size); - _ZP_UNUSED(expandable); + ztu->_state_reliable = _Z_DBUF_STATE_NULL; + ztu->_state_best_effort = _Z_DBUF_STATE_NULL; + ztu->_dbuf_reliable = _z_wbuf_null(); + ztu->_dbuf_best_effort = _z_wbuf_null(); #endif // Z_FEATURE_FRAGMENTATION == 1 } if (ret == _Z_RES_OK) { // Set default SN resolution - zt->_transport._unicast._sn_res = _z_sn_max(param->_seq_num_res); + ztu->_common._sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side - zt->_transport._unicast._sn_tx_reliable = param->_initial_sn_tx; - zt->_transport._unicast._sn_tx_best_effort = param->_initial_sn_tx; + ztu->_common._sn_tx_reliable = param->_initial_sn_tx; + ztu->_common._sn_tx_best_effort = param->_initial_sn_tx; // The initial SN at RX side - _z_zint_t initial_sn_rx = _z_sn_decrement(zt->_transport._unicast._sn_res, param->_initial_sn_rx); - zt->_transport._unicast._sn_rx_reliable = initial_sn_rx; - zt->_transport._unicast._sn_rx_best_effort = initial_sn_rx; + _z_zint_t initial_sn_rx = _z_sn_decrement(ztu->_common._sn_res, param->_initial_sn_rx); + ztu->_sn_rx_reliable = initial_sn_rx; + ztu->_sn_rx_best_effort = initial_sn_rx; #if Z_FEATURE_MULTI_THREAD == 1 // Tasks - zt->_transport._unicast._read_task_running = false; - zt->_transport._unicast._read_task = NULL; - zt->_transport._unicast._lease_task_running = false; - zt->_transport._unicast._lease_task = NULL; + ztu->_common._read_task_running = false; + ztu->_common._read_task = NULL; + ztu->_common._lease_task_running = false; + ztu->_common._lease_task = NULL; #endif // Z_FEATURE_MULTI_THREAD == 1 // Notifiers - zt->_transport._unicast._received = 0; - zt->_transport._unicast._transmitted = 0; + ztu->_received = 0; + ztu->_common._transmitted = 0; // Transport lease - zt->_transport._unicast._lease = param->_lease; + ztu->_common._lease = param->_lease; // Transport link for unicast - zt->_transport._unicast._link = *zl; + ztu->_common._link = *zl; // Remote peer PID - zt->_transport._unicast._remote_zid = param->_remote_zid; + ztu->_remote_zid = param->_remote_zid; } else { param->_remote_zid = _z_id_empty(); } @@ -158,107 +133,180 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, return ret; } -z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid) { - z_result_t ret = _Z_RES_OK; - - _z_id_t zid = *local_zid; - _z_transport_message_t ism = _z_t_msg_make_init_syn(Z_WHATAMI_CLIENT, zid); +static z_result_t _z_unicast_handshake_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid, enum z_whatami_t whatami) { + _z_transport_message_t ism = _z_t_msg_make_init_syn(whatami, *local_zid); param->_seq_num_res = ism._body._init._seq_num_res; // The announced sn resolution param->_req_id_res = ism._body._init._req_id_res; // The announced req id resolution param->_batch_size = ism._body._init._batch_size; // The announced batch size // Encode and send the message - _Z_INFO("Sending Z_INIT(Syn)"); - ret = _z_link_send_t_msg(zl, &ism); + _Z_DEBUG("Sending Z_INIT(Syn)"); + z_result_t ret = _z_link_send_t_msg(zl, &ism); _z_t_msg_clear(&ism); - if (ret == _Z_RES_OK) { - _z_transport_message_t iam; - ret = _z_link_recv_t_msg(&iam, zl); - if (ret == _Z_RES_OK) { - if ((_Z_MID(iam._header) == _Z_MID_T_INIT) && (_Z_HAS_FLAG(iam._header, _Z_FLAG_T_INIT_A) == true)) { - _Z_INFO("Received Z_INIT(Ack)"); - - // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, - // otherwise the InitAck message is considered invalid and it should be treated as a - // CLOSE message with L==0 by the Initiating Peer -- the recipient of the InitAck message. - if (iam._body._init._seq_num_res <= param->_seq_num_res) { - param->_seq_num_res = iam._body._init._seq_num_res; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } - - if (iam._body._init._req_id_res <= param->_req_id_res) { - param->_req_id_res = iam._body._init._req_id_res; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } - - if (iam._body._init._batch_size <= param->_batch_size) { - param->_batch_size = iam._body._init._batch_size; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } - - if (ret == _Z_RES_OK) { - param->_key_id_res = 0x08 << param->_key_id_res; - param->_req_id_res = 0x08 << param->_req_id_res; - - // The initial SN at TX side - z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); - param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); - - // Initialize the Local and Remote Peer IDs - param->_remote_zid = iam._body._init._zid; - - // Create the OpenSyn message - _z_zint_t lease = Z_TRANSPORT_LEASE; - _z_zint_t initial_sn = param->_initial_sn_tx; - _z_slice_t cookie; - _z_slice_copy(&cookie, &iam._body._init._cookie); - - _z_transport_message_t osm = _z_t_msg_make_open_syn(lease, initial_sn, cookie); - - // Encode and send the message - _Z_INFO("Sending Z_OPEN(Syn)"); - ret = _z_link_send_t_msg(zl, &osm); - if (ret == _Z_RES_OK) { - _z_transport_message_t oam; - ret = _z_link_recv_t_msg(&oam, zl); - if (ret == _Z_RES_OK) { - if ((_Z_MID(oam._header) == _Z_MID_T_OPEN) && - (_Z_HAS_FLAG(oam._header, _Z_FLAG_T_OPEN_A) == true)) { - _Z_INFO("Received Z_OPEN(Ack)"); - param->_lease = oam._body._open._lease; // The session lease - - // The initial SN at RX side. Initialize the session as we had already received - // a message with a SN equal to initial_sn - 1. - param->_initial_sn_rx = oam._body._open._initial_sn; - } else { - ret = _Z_ERR_MESSAGE_UNEXPECTED; - } - _z_t_msg_clear(&oam); - } - } - _z_t_msg_clear(&osm); - } - } else { - ret = _Z_ERR_MESSAGE_UNEXPECTED; - } - _z_t_msg_clear(&iam); - } + if (ret != _Z_RES_OK) { + return ret; + } + // Try to receive response + _z_transport_message_t iam; + _Z_RETURN_IF_ERR(_z_link_recv_t_msg(&iam, zl)); + if ((_Z_MID(iam._header) != _Z_MID_T_INIT) || !_Z_HAS_FLAG(iam._header, _Z_FLAG_T_INIT_A)) { + _z_t_msg_clear(&iam); + return _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_INIT(Ack)"); + // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, + // otherwise the InitAck message is considered invalid and it should be treated as a + // CLOSE message with L==0 by the Initiating Peer -- the recipient of the InitAck message. + if (iam._body._init._seq_num_res <= param->_seq_num_res) { + param->_seq_num_res = iam._body._init._seq_num_res; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; } + if (iam._body._init._req_id_res <= param->_req_id_res) { + param->_req_id_res = iam._body._init._req_id_res; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; + } + if (iam._body._init._batch_size <= param->_batch_size) { + param->_batch_size = iam._body._init._batch_size; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; + } + if (ret != _Z_RES_OK) { + _z_t_msg_clear(&iam); + return ret; + } + param->_key_id_res = 0x08 << param->_key_id_res; + param->_req_id_res = 0x08 << param->_req_id_res; + + // The initial SN at TX side + z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); + param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); + + // Initialize the Local and Remote Peer IDs + param->_remote_zid = iam._body._init._zid; + + // Create the OpenSyn message + _z_zint_t lease = Z_TRANSPORT_LEASE; + _z_zint_t initial_sn = param->_initial_sn_tx; + _z_slice_t cookie; + _z_slice_copy(&cookie, &iam._body._init._cookie); + _z_transport_message_t osm = _z_t_msg_make_open_syn(lease, initial_sn, cookie); + _z_t_msg_clear(&iam); + // Encode and send the message + _Z_DEBUG("Sending Z_OPEN(Syn)"); + ret = _z_link_send_t_msg(zl, &osm); + _z_t_msg_clear(&osm); + if (ret != _Z_RES_OK) { + return ret; + } + // Try to receive response + _z_transport_message_t oam; + _Z_RETURN_IF_ERR(_z_link_recv_t_msg(&oam, zl)); + if ((_Z_MID(oam._header) != _Z_MID_T_OPEN) || !_Z_HAS_FLAG(oam._header, _Z_FLAG_T_OPEN_A)) { + _z_t_msg_clear(&oam); + ret = _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_OPEN(Ack)"); + param->_lease = oam._body._open._lease; // The session lease + // The initial SN at RX side. Initialize the session as we had already received + // a message with a SN equal to initial_sn - 1. + param->_initial_sn_rx = oam._body._open._initial_sn; + _z_t_msg_clear(&oam); + return _Z_RES_OK; +} - return ret; +static z_result_t _z_unicast_handshake_listener(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid, enum z_whatami_t whatami) { + // Read t message from link + _z_transport_message_t tmsg; + z_result_t ret = _z_link_recv_t_msg(&tmsg, zl); + if (ret != _Z_RES_OK) { + return ret; + } + // Receive InitSyn + if (_Z_MID(tmsg._header) != _Z_MID_T_INIT || _Z_HAS_FLAG(tmsg._header, _Z_FLAG_T_INIT_A)) { + _z_t_msg_clear(&tmsg); + return _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_INIT(Syn)"); + // Encode InitAck + _z_slice_t cookie = _z_slice_null(); + _z_transport_message_t iam = _z_t_msg_make_init_ack(whatami, *local_zid, cookie); + // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, + if (iam._body._init._seq_num_res > tmsg._body._init._seq_num_res) { + iam._body._init._seq_num_res = tmsg._body._init._seq_num_res; + } + if (iam._body._init._req_id_res > tmsg._body._init._req_id_res) { + iam._body._init._req_id_res = tmsg._body._init._req_id_res; + } + if (iam._body._init._batch_size > tmsg._body._init._batch_size) { + iam._body._init._batch_size = tmsg._body._init._batch_size; + } + param->_remote_zid = tmsg._body._init._zid; + param->_seq_num_res = iam._body._init._seq_num_res; + param->_req_id_res = iam._body._init._req_id_res; + param->_batch_size = iam._body._init._batch_size; + param->_key_id_res = 0x08 << param->_key_id_res; + param->_req_id_res = 0x08 << param->_req_id_res; + _z_t_msg_clear(&tmsg); + // Send InitAck + _Z_DEBUG("Sending Z_INIT(Ack)"); + ret = _z_link_send_t_msg(zl, &iam); + _z_t_msg_clear(&iam); + if (ret != _Z_RES_OK) { + return ret; + } + // Read t message from link + ret = _z_link_recv_t_msg(&tmsg, zl); + if (ret != _Z_RES_OK) { + return ret; + } + // Receive OpenSyn + if (_Z_MID(tmsg._header) != _Z_MID_T_OPEN || _Z_HAS_FLAG(tmsg._header, _Z_FLAG_T_INIT_A)) { + _z_t_msg_clear(&tmsg); + return _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_OPEN(Syn)"); + // Process message + param->_lease = tmsg._body._open._lease; + param->_initial_sn_rx = tmsg._body._open._initial_sn; + _z_t_msg_clear(&tmsg); + + // Init sn, tx side + z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); + param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); + + // Encode OpenAck + _z_zint_t lease = Z_TRANSPORT_LEASE; + _z_zint_t initial_sn = param->_initial_sn_tx; + _z_transport_message_t oam = _z_t_msg_make_open_ack(lease, initial_sn); + + // Encode and send the message + _Z_DEBUG("Sending Z_OPEN(Ack)"); + ret = _z_link_send_t_msg(zl, &oam); + _z_t_msg_clear(&oam); + if (ret != _Z_RES_OK) { + return ret; + } + // Handshake finished + return _Z_RES_OK; +} + +z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid) { + return _z_unicast_handshake_client(param, zl, local_zid, Z_WHATAMI_CLIENT); } z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid) { - _ZP_UNUSED(param); - _ZP_UNUSED(zl); - _ZP_UNUSED(local_zid); - z_result_t ret = _Z_ERR_CONFIG_UNSUPPORTED_PEER_UNICAST; - // @TODO: not implemented + const _z_id_t *local_zid, int peer_op) { + z_result_t ret = _Z_RES_OK; + if (peer_op == _Z_PEER_OP_OPEN) { + ret = _z_unicast_handshake_client(param, zl, local_zid, Z_WHATAMI_PEER); + } else { + ret = _z_unicast_handshake_listener(param, zl, local_zid, Z_WHATAMI_PEER); + } return ret; } @@ -266,7 +314,7 @@ z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bo z_result_t ret = _Z_RES_OK; // Send and clear message _z_transport_message_t cm = _z_t_msg_make_close(reason, link_only); - ret = _z_unicast_send_t_msg(ztu, &cm); + ret = _z_transport_tx_send_t_msg(&ztu->_common, &cm); _z_t_msg_clear(&cm); return ret; } @@ -279,23 +327,25 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { _z_transport_unicast_t *ztu = &zt->_transport._unicast; #if Z_FEATURE_MULTI_THREAD == 1 // Clean up tasks - if (ztu->_read_task != NULL) { - _z_task_join(ztu->_read_task); - _z_task_free(&ztu->_read_task); + if (ztu->_common._read_task != NULL) { + _z_task_join(ztu->_common._read_task); + z_free(ztu->_common._read_task); } - if (ztu->_lease_task != NULL) { - _z_task_join(ztu->_lease_task); - _z_task_free(&ztu->_lease_task); + if (ztu->_common._lease_task != NULL) { + _z_task_join(ztu->_common._lease_task); + z_free(ztu->_common._lease_task); } // Clean up the mutexes - _z_mutex_drop(&ztu->_mutex_tx); - _z_mutex_drop(&ztu->_mutex_rx); + _z_mutex_drop(&ztu->_common._mutex_tx); + _z_mutex_drop(&ztu->_common._mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 // Clean up the buffers - _z_wbuf_clear(&ztu->_wbuf); - _z_zbuf_clear(&ztu->_zbuf); + _z_wbuf_clear(&ztu->_common._wbuf); + _z_zbuf_clear(&ztu->_common._zbuf); + _z_arc_slice_svec_release(&ztu->_common._arc_pool); + _z_network_message_svec_release(&ztu->_common._msg_pool); #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_reliable); _z_wbuf_clear(&ztu->_dbuf_best_effort); @@ -303,7 +353,7 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { // Clean up PIDs ztu->_remote_zid = _z_id_empty(); - _z_link_clear(&ztu->_link); + _z_link_clear(&ztu->_common._link); } #else @@ -325,10 +375,11 @@ z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, } z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid) { + const _z_id_t *local_zid, int peer_op) { _ZP_UNUSED(param); _ZP_UNUSED(zl); _ZP_UNUSED(local_zid); + _ZP_UNUSED(peer_op); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } diff --git a/src/transport/unicast/tx.c b/src/transport/unicast/tx.c deleted file mode 100644 index 5ed555794..000000000 --- a/src/transport/unicast/tx.c +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/transport/common/tx.h" - -#include - -#include "zenoh-pico/config.h" -#include "zenoh-pico/protocol/codec/network.h" -#include "zenoh-pico/protocol/codec/transport.h" -#include "zenoh-pico/protocol/iobuf.h" -#include "zenoh-pico/transport/unicast/tx.h" -#include "zenoh-pico/transport/utils.h" -#include "zenoh-pico/utils/logging.h" - -#if Z_FEATURE_UNICAST_TRANSPORT == 1 - -/** - * This function is unsafe because it operates in potentially concurrent data. - * Make sure that the following mutexes are locked before calling this function: - * - ztu->_mutex_inner - */ -_z_zint_t __unsafe_z_unicast_get_sn(_z_transport_unicast_t *ztu, z_reliability_t reliability) { - _z_zint_t sn; - if (reliability == Z_RELIABILITY_RELIABLE) { - sn = ztu->_sn_tx_reliable; - ztu->_sn_tx_reliable = _z_sn_increment(ztu->_sn_res, ztu->_sn_tx_reliable); - } else { - sn = ztu->_sn_tx_best_effort; - ztu->_sn_tx_best_effort = _z_sn_increment(ztu->_sn_res, ztu->_sn_tx_best_effort); - } - return sn; -} - -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send session message"); - -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - // Prepare the buffer eventually reserving space for the message length - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - // Encode the session message - ret = _z_transport_message_encode(&ztu->_wbuf, t_msg); - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - // Send the wbuf on the socket - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); - if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Mark the session that we have transmitted data - } - } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - return ret; -} - -z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send network message"); - - _z_transport_unicast_t *ztu = &zn->_tp._transport._unicast; - - // Acquire the lock and drop the message if needed - bool drop = false; - if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_lock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - } else { -#if Z_FEATURE_MULTI_THREAD == 1 - z_result_t locked = _z_mutex_try_lock(&ztu->_mutex_tx); - if (locked != 0) { - _Z_INFO("Dropping zenoh message because of congestion control"); - // We failed to acquire the lock, drop the message - drop = true; - } -#endif // Z_FEATURE_MULTI_THREAD == 1 - } - - if (drop == false) { - // Prepare the buffer eventually reserving space for the message length - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); // Get the next sequence number - - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - ret = _z_transport_message_encode(&ztu->_wbuf, &t_msg); // Encode the frame header - if (ret == _Z_RES_OK) { - ret = _z_network_message_encode(&ztu->_wbuf, n_msg); // Encode the network message - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - if (ztu->_wbuf._ioss._len == 1) { - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); // Send the wbuf on the socket - } else { - // Change the MID - - // for () - } - if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Mark the session that we have transmitted data - } - } else { -#if Z_FEATURE_FRAGMENTATION == 1 - // The message does not fit in the current batch, let's fragment it - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - - ret = _z_network_message_encode(&fbf, n_msg); // Encode the message on the expandable wbuf - if (ret == _Z_RES_OK) { - bool is_first = true; // Fragment and send the message - while (_z_wbuf_len(&fbf) > 0) { - if (is_first == false) { // Get the fragment sequence number - sn = __unsafe_z_unicast_get_sn(ztu, reliability); - } - is_first = false; - - // Clear the buffer for serialization - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - // Serialize one fragment - ret = __unsafe_z_serialize_zenoh_fragment(&ztu->_wbuf, &fbf, reliability, sn); - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); // Send the wbuf on the socket - if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Mark the session that we have transmitted data - } - } else { - _Z_ERROR("Fragment serialization failed with err %d", ret); - } - } - } - - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); -#else - _Z_INFO("Sending the message required fragmentation feature that is deactivated."); -#endif - } - } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - } - - return ret; -} -#else -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { - _ZP_UNUSED(ztu); - _ZP_UNUSED(t_msg); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - _ZP_UNUSED(zn); - _ZP_UNUSED(n_msg); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} -#endif // Z_FEATURE_UNICAST_TRANSPORT == 1 diff --git a/src/utils/uuid.c b/src/utils/uuid.c index 7b9984871..1f2d97fe6 100644 --- a/src/utils/uuid.c +++ b/src/utils/uuid.c @@ -17,6 +17,7 @@ #include #include +#include "zenoh-pico/api/types.h" #include "zenoh-pico/utils/pointers.h" #define UUID_SIZE 16 @@ -32,3 +33,8 @@ void _z_uuid_to_bytes(uint8_t *bytes, const char *uuid_str) { bytes = _z_ptr_u8_offset(bytes, 1); } } + +_z_string_t _z_id_to_string(const z_id_t *id) { + _z_slice_t buf = _z_slice_alias_buf(id->id, sizeof(id->id)); + return _z_string_convert_bytes_le(&buf); +} diff --git a/tests/modularity.py b/tests/modularity.py index 7350ae70a..be18d86c1 100644 --- a/tests/modularity.py +++ b/tests/modularity.py @@ -47,8 +47,8 @@ def pub_and_sub(args): # Expected z_sub output & status if args.sub == 1: - z_sub_expected_status = -2 if args.pub == 1: + z_sub_expected_status = [0, -2] z_sub_expected_output = """Opening session... Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit... @@ -63,16 +63,17 @@ def pub_and_sub(args): >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 8] Pub from Pico!') >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')""" else: + z_sub_expected_status = [-2] z_sub_expected_output = """Opening session... Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit...""" else: - z_sub_expected_status = 254 + z_sub_expected_status = [254] z_sub_expected_output = "ERROR: Zenoh pico was compiled without " "Z_FEATURE_SUBSCRIPTION but this example requires it." print("Start subscriber") # Start z_sub in the background - z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub" + z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub -n 10" z_sub_process = subprocess.Popen( z_sub_command, shell=True, @@ -132,7 +133,7 @@ def pub_and_sub(args): print("Check subscriber status & output") # Check the exit status of z_sub z_sub_status = z_sub_process.returncode - if z_sub_status == z_sub_expected_status: + if z_sub_status in z_sub_expected_status: print("z_sub status valid") else: print(f"z_sub status invalid, expected: {z_sub_expected_status}, received: {z_sub_status}") @@ -175,24 +176,25 @@ def query_and_queryable(args): # Expected z_queryable output & status if args.queryable == 1: - z_queryable_expected_status = -2 if args.query == 1: + z_queryable_expected_status = [0, -2] z_queryable_expected_output = """Opening session... Creating Queryable on 'demo/example/zenoh-pico-queryable'... Press CTRL-C to quit... >> [Queryable handler] Received Query 'demo/example/**' """ else: + z_queryable_expected_status = [-2] z_queryable_expected_output = """Opening session... Creating Queryable on 'demo/example/zenoh-pico-queryable'... Press CTRL-C to quit...""" else: - z_queryable_expected_status = 254 + z_queryable_expected_status = [254] z_queryable_expected_output = "ERROR: Zenoh pico was compiled without " "Z_FEATURE_QUERYABLE but this example requires it." print("Start queryable") # Start z_queryable in the background - z_queryable_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_queryable" + z_queryable_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_queryable -n 1" z_queryable_process = subprocess.Popen( z_queryable_command, shell=True, @@ -252,7 +254,7 @@ def query_and_queryable(args): print("Check queryable status & output") # Check the exit status of z_queryable z_queryable_status = z_queryable_process.returncode - if z_queryable_status == z_queryable_expected_status: + if z_queryable_status in z_queryable_expected_status: print("z_queryable status valid") else: print(f"z_queryable status invalid, expected: {z_queryable_expected_status}," f" received: {z_queryable_status}") diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index a8b48eb3e..abef93a46 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -132,11 +132,9 @@ int main(int argc, char **argv) { zc_init_logger(); const char *encoding_expected = z_sample_kind(sample) == Z_SAMPLE_KIND_PUT ? "zenoh/bytes" : "zenoh/bytes;test_encoding"; - z_pu #endif - z_view_keyexpr_t key_demo_example, - key_demo_example_a, key_demo_example_starstar; + z_view_keyexpr_t key_demo_example, key_demo_example_a, key_demo_example_starstar; z_view_keyexpr_from_str(&key_demo_example, "demo/example"); z_view_keyexpr_from_str(&key_demo_example_a, "demo/example/a"); z_view_keyexpr_from_str(&key_demo_example_starstar, "demo/example/**"); @@ -199,10 +197,9 @@ int main(int argc, char **argv) { assert(z_internal_check(s1)); z_id_t _ret_zid = z_info_zid(z_loan(s1)); printf("Session 1 with PID: 0x"); - for (unsigned long i = 0; i < sizeof(_ret_zid); i++) { - printf("%.2X", _ret_zid.id[i]); - } - printf("\n"); + z_owned_string_t id_str; + z_id_to_string(&_ret_zid, &id_str); + printf("%.*s\n", (int)z_string_len(z_loan(id_str)), z_string_data(z_loan(id_str))); z_owned_closure_zid_t _ret_closure_zid; z_closure(&_ret_closure_zid, zid_handler, NULL, NULL); @@ -243,10 +240,8 @@ int main(int argc, char **argv) { assert(z_internal_check(s2)); _ret_zid = z_info_zid(z_loan(s2)); printf("Session 2 with PID: 0x"); - for (unsigned long i = 0; i < sizeof(_ret_zid); i++) { - printf("%.2X", _ret_zid.id[i]); - } - printf("\n"); + z_id_to_string(&_ret_zid, &id_str); + printf("%.*s\n", (int)z_string_len(z_loan(id_str)), z_string_data(z_loan(id_str))); #ifdef ZENOH_PICO zp_start_read_task(z_loan_mut(s2), NULL); diff --git a/tests/z_client_test.c b/tests/z_client_test.c index d073bc554..ca230002c 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -20,6 +20,7 @@ #include "zenoh-pico.h" #include "zenoh-pico/api/types.h" #include "zenoh-pico/collections/string.h" +#include "zenoh-pico/utils/uuid.h" #undef NDEBUG #include @@ -116,11 +117,6 @@ void data_handler(z_loaned_sample_t *sample, void *arg) { free(res); } -_z_string_t format_id(const z_id_t *id) { - _z_slice_t id_as_bytes = _z_slice_alias_buf(id->id, _z_id_len(*id)); - return _z_string_convert_bytes(&id_as_bytes); -} - int main(int argc, char **argv) { setvbuf(stdout, NULL, _IOLBF, 1024); @@ -137,8 +133,8 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); - _z_string_t zid1 = format_id(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - printf("Session 1 with PID: %s\n", _z_string_data(&zid1)); + _z_string_t zid1 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); + printf("Session 1 with PID: %*.s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -153,8 +149,8 @@ int main(int argc, char **argv) { z_owned_session_t s2; assert(z_open(&s2, z_move(config), NULL) == Z_OK); assert(z_internal_check(s2)); - _z_string_t zid2 = format_id(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - printf("Session 2 with PID: %s\n", _z_string_data(&zid2)); + _z_string_t zid2 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); + printf("Session 2 with PID: %*.s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops @@ -213,7 +209,7 @@ int main(int argc, char **argv) { z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, s1_res); assert(z_declare_queryable(z_loan(s2), qle, z_loan(ke), z_move(callback), NULL) == _Z_RES_OK); - printf("Declared queryable on session 2: %ju %zu %s\n", (uintmax_t)qle->_val._entity_id, (z_zint_t)0, s1_res); + printf("Declared queryable on session 2: %ju %i %s\n", (uintmax_t)qle->_val._entity_id, 0, s1_res); qles2 = _z_list_push(qles2, qle); } @@ -315,7 +311,7 @@ int main(int argc, char **argv) { z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, s1_res); z_get(z_loan(s1), z_loan(ke), "", z_move(callback), NULL); - printf("Queried data from session 1: %zu %s\n", (z_zint_t)0, s1_res); + printf("Queried data from session 1: %i %s\n", 0, s1_res); } } diff --git a/tests/z_data_struct_test.c b/tests/z_data_struct_test.c index 0b7cfa702..e3dff0fa5 100644 --- a/tests/z_data_struct_test.c +++ b/tests/z_data_struct_test.c @@ -233,11 +233,24 @@ void z_string_array_test(void) { z_string_array_drop(z_string_array_move(&a)); } +void z_id_to_string_test(void) { + z_id_t id; + for (uint8_t i = 0; i < sizeof(id.id); i++) { + id.id[i] = i; + } + z_owned_string_t id_str; + z_id_to_string(&id, &id_str); + assert(z_string_len(z_string_loan(&id_str)) == 32); + assert(strncmp("0f0e0d0c0b0a09080706050403020100", z_string_data(z_string_loan(&id_str)), + z_string_len(z_string_loan(&id_str))) == 0); +} + int main(void) { entry_list_test(); str_vec_list_intmap_test(); z_slice_custom_delete_test(); z_string_array_test(); + z_id_to_string_test(); return 0; } diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index 81f16f50c..1b0b134c5 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -172,7 +172,7 @@ _z_wbuf_t gen_wbuf(size_t len) { _z_slice_t gen_slice(size_t len) { if (len == 0) { - return _z_slice_empty(); + return _z_slice_null(); } uint8_t *p = (uint8_t *)z_malloc(sizeof(uint8_t) * len); @@ -225,7 +225,7 @@ _z_string_svec_t gen_str_array(size_t size) { _z_string_svec_t sa = _z_string_svec_make(size); for (size_t i = 0; i < size; i++) { _z_string_t s = _z_string_copy_from_str(gen_str(16)); - _z_string_svec_append(&sa, &s); + _z_string_svec_append(&sa, &s, true); } return sa; @@ -341,7 +341,7 @@ void assert_eq_locator_array(const _z_locator_array_t *left, const _z_locator_ar _z_string_t ls = _z_locator_to_string(l); _z_string_t rs = _z_locator_to_string(r); - printf("%s:%s", _z_string_data(&ls), _z_string_data(&rs)); + printf("%.*s:%.*s", (int)_z_string_len(&ls), _z_string_data(&ls), (int)_z_string_len(&rs), _z_string_data(&rs)); if (i < left->_len - 1) printf(" "); _z_string_clear(&ls); @@ -554,8 +554,9 @@ void payload_field(void) { // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_bytes_t d_pld; - res = _z_bytes_decode(&d_pld, &zbf); + _z_bytes_t d_pld = _z_bytes_null(); + _z_arc_slice_t arcs = {0}; + res = _z_bytes_decode(&d_pld, &zbf, &arcs); assert(res == _Z_RES_OK); printf(" "); assert_eq_bytes(&e_pld, &d_pld); @@ -563,7 +564,7 @@ void payload_field(void) { // Free _z_bytes_drop(&e_pld); - _z_bytes_drop(&d_pld); + _z_bytes_aliased_drop(&d_pld); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } @@ -589,6 +590,7 @@ void assert_eq_value(const _z_value_t *left, const _z_value_t *right) { /*------------------ Timestamp field ------------------*/ _z_timestamp_t gen_timestamp(void) { _z_timestamp_t ts; + ts.valid = true; ts.time = gen_uint64(); for (size_t i = 0; i < 16; i++) { ts.id.id[i] = gen_uint8() & 0x7f; // 0b01111111 @@ -1067,7 +1069,8 @@ void declare_message(void) { // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); _z_network_message_t d_dcl = {0}; - res = _z_network_message_decode(&d_dcl, &zbf); + _z_arc_slice_t arcs = {0}; + res = _z_network_message_decode(&d_dcl, &zbf, &arcs); assert(res == _Z_RES_OK); assert_eq_declare_message(&n_msg._body._declare, &d_dcl._body._declare); @@ -1139,7 +1142,7 @@ void interest_message(void) { // Encode assert(_z_n_interest_encode(&wbf, &expected._body._interest) == _Z_RES_OK); // Decode - _z_n_msg_interest_t decoded; + _z_n_msg_interest_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); assert(_z_n_interest_decode(&decoded, &zbf, header) == _Z_RES_OK); @@ -1201,8 +1204,9 @@ void push_body_message(void) { // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); _z_push_body_t d_da = {0}; + _z_arc_slice_t arcs = {0}; uint8_t header = _z_zbuf_read(&zbf); - res = _z_push_body_decode(&d_da, &zbf, header); + res = _z_push_body_decode(&d_da, &zbf, header, &arcs); assert(res == _Z_RES_OK); assert_eq_push_body(&e_da, &d_da); @@ -1235,7 +1239,7 @@ void query_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_msg_query_t expected = gen_query(); assert(_z_query_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_query_t decoded; + _z_msg_query_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); z_result_t res = _z_query_decode(&decoded, &zbf, header); @@ -1267,10 +1271,11 @@ void err_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_msg_err_t expected = gen_err(); assert(_z_err_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_err_t decoded; + _z_msg_err_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_err_decode(&decoded, &zbf, header)); + assert(_Z_RES_OK == _z_err_decode(&decoded, &zbf, header, &arcs)); assert_eq_err(&expected, &decoded); _z_msg_err_clear(&decoded); _z_msg_err_clear(&expected); @@ -1295,10 +1300,11 @@ void reply_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_msg_reply_t expected = gen_reply(); assert(_z_reply_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_reply_t decoded; + _z_msg_reply_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_reply_decode(&decoded, &zbf, header)); + assert(_Z_RES_OK == _z_reply_decode(&decoded, &zbf, header, &arcs)); assert_eq_reply(&expected, &decoded); _z_msg_reply_clear(&decoded); _z_msg_reply_clear(&expected); @@ -1327,10 +1333,11 @@ void push_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_push_t expected = gen_push(); assert(_z_push_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_push_t decoded; + _z_n_msg_push_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_push_decode(&decoded, &zbf, header)); + assert(_Z_RES_OK == _z_push_decode(&decoded, &zbf, header, &arcs)); assert_eq_push(&expected, &decoded); _z_n_msg_push_clear(&decoded); _z_n_msg_push_clear(&expected); @@ -1397,10 +1404,11 @@ void request_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_request_t expected = gen_request(); assert(_z_request_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_request_t decoded; + _z_n_msg_request_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - z_result_t ret = _z_request_decode(&decoded, &zbf, header); + z_result_t ret = _z_request_decode(&decoded, &zbf, header, &arcs); assert(_Z_RES_OK == ret); assert_eq_request(&expected, &decoded); _z_n_msg_request_clear(&decoded); @@ -1455,10 +1463,11 @@ void response_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_response_t expected = gen_response(); assert(_z_response_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_response_t decoded; + _z_n_msg_response_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - z_result_t ret = _z_response_decode(&decoded, &zbf, header); + z_result_t ret = _z_response_decode(&decoded, &zbf, header, &arcs); assert(_Z_RES_OK == ret); assert_eq_response(&expected, &decoded); _z_n_msg_response_clear(&decoded); @@ -1476,7 +1485,7 @@ void response_final_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_response_final_t expected = gen_response_final(); assert(_z_response_final_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_response_final_t decoded; + _z_n_msg_response_final_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); z_result_t ret = _z_response_final_decode(&decoded, &zbf, header); @@ -1525,7 +1534,7 @@ void join_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_join(); assert(_z_join_encode(&wbf, expected._header, &expected._body._join) == _Z_RES_OK); - _z_t_msg_join_t decoded; + _z_t_msg_join_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_join_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1557,7 +1566,7 @@ void init_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_init(); assert(_z_init_encode(&wbf, expected._header, &expected._body._init) == _Z_RES_OK); - _z_t_msg_init_t decoded; + _z_t_msg_init_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_init_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1585,7 +1594,7 @@ void open_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_open(); assert(_z_open_encode(&wbf, expected._header, &expected._body._open) == _Z_RES_OK); - _z_t_msg_open_t decoded; + _z_t_msg_open_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_open_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1605,7 +1614,7 @@ void close_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_close(); assert(_z_close_encode(&wbf, expected._header, &expected._body._close) == _Z_RES_OK); - _z_t_msg_close_t decoded; + _z_t_msg_close_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_close_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1626,7 +1635,7 @@ void keep_alive_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_keep_alive(); assert(_z_keep_alive_encode(&wbf, expected._header, &expected._body._keep_alive) == _Z_RES_OK); - _z_t_msg_keep_alive_t decoded; + _z_t_msg_keep_alive_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_keep_alive_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1687,13 +1696,12 @@ void assert_eq_net_msg(const _z_network_message_t *left, const _z_network_messag break; } } -_z_network_message_vec_t gen_net_msgs(size_t n) { - _z_network_message_vec_t ret = _z_network_message_vec_make(n); +_z_network_message_svec_t gen_net_msgs(size_t n) { + _z_network_message_svec_t ret = _z_network_message_svec_make(n); for (size_t i = 0; i < n; i++) { - _z_network_message_t *msg = (_z_network_message_t *)z_malloc(sizeof(_z_network_message_t)); + _z_network_message_t *msg = _z_network_message_svec_get_mut(&ret, i); memset(msg, 0, sizeof(_z_network_message_t)); *msg = gen_net_msg(); - _z_network_message_vec_append(&ret, msg); } return ret; } @@ -1705,7 +1713,8 @@ void assert_eq_frame(const _z_t_msg_frame_t *left, const _z_t_msg_frame_t *right assert(left->_sn == right->_sn); assert(left->_messages._len == right->_messages._len); for (size_t i = 0; i < left->_messages._len; i++) { - assert_eq_net_msg(left->_messages._val[i], right->_messages._val[i]); + assert_eq_net_msg(_z_network_message_svec_get(&left->_messages, i), + _z_network_message_svec_get(&right->_messages, i)); } } void frame_message(void) { @@ -1713,9 +1722,11 @@ void frame_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_frame(); assert(_z_frame_encode(&wbf, expected._header, &expected._body._frame) == _Z_RES_OK); - _z_t_msg_frame_t decoded; + _z_t_msg_frame_t decoded = {0}; + _z_arc_slice_svec_t arcs = _z_arc_slice_svec_make(1); + _z_network_message_svec_t msg = _z_network_message_svec_make(1); _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - z_result_t ret = _z_frame_decode(&decoded, &zbf, expected._header); + z_result_t ret = _z_frame_decode(&decoded, &zbf, expected._header, &arcs, &msg); assert(_Z_RES_OK == ret); assert_eq_frame(&expected._body._frame, &decoded); _z_t_msg_frame_clear(&decoded); @@ -1736,7 +1747,7 @@ void fragment_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_fragment(); assert(_z_fragment_encode(&wbf, expected._header, &expected._body._fragment) == _Z_RES_OK); - _z_t_msg_fragment_t decoded; + _z_t_msg_fragment_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_fragment_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1806,9 +1817,11 @@ void transport_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_transport(); assert(_z_transport_message_encode(&wbf, &expected) == _Z_RES_OK); - _z_transport_message_t decoded; + _z_transport_message_t decoded = {0}; + _z_arc_slice_svec_t arcs = _z_arc_slice_svec_make(1); + _z_network_message_svec_t msg = _z_network_message_svec_make(1); _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - z_result_t ret = _z_transport_message_decode(&decoded, &zbf); + z_result_t ret = _z_transport_message_decode(&decoded, &zbf, &arcs, &msg); assert(_Z_RES_OK == ret); assert_eq_transport(&expected, &decoded); _z_t_msg_clear(&decoded); @@ -1848,7 +1861,7 @@ void scouting_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_scouting_message_t expected = gen_scouting(); assert(_z_scouting_message_encode(&wbf, &expected) == _Z_RES_OK); - _z_scouting_message_t decoded; + _z_scouting_message_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_scouting_message_decode(&decoded, &zbf); assert(_Z_RES_OK == ret); diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index 383ba799d..b0cf8e699 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -20,6 +20,7 @@ #include "zenoh-pico.h" #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/utils/uuid.h" #undef NDEBUG #include @@ -76,10 +77,8 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); - _z_slice_t id_as_bytes = - _z_slice_alias_buf(_Z_RC_IN_VAL(z_loan(s1))->_local_zid.id, _z_id_len(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - _z_string_t zid1 = _z_string_convert_bytes(&id_as_bytes); - printf("Session 1 with PID: %s\n", z_string_data(&zid1)); + _z_string_t zid1 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); + printf("Session 1 with PID: %*.s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -90,15 +89,13 @@ int main(int argc, char **argv) { z_config_default(&config); zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, "peer"); - zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[1]); z_owned_session_t s2; assert(z_open(&s2, z_move(config), NULL) == Z_OK); - id_as_bytes = - _z_slice_alias_buf(_Z_RC_IN_VAL(z_loan(s2))->_local_zid.id, _z_id_len(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - _z_string_t zid2 = _z_string_convert_bytes(&id_as_bytes); - printf("Session 2 with PID: %s\n", z_string_data(&zid2)); + _z_string_t zid2 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); + printf("Session 2 with PID: %*.s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops @@ -119,8 +116,8 @@ int main(int argc, char **argv) { z_view_keyexpr_from_str(&ke, s1_res); z_result_t res = z_declare_subscriber(z_loan(s2), sub, z_loan(ke), z_move(callback), NULL); assert(res == _Z_RES_OK); - printf("Declared subscription on session 2: %ju %zu %s\n", (uintmax_t)z_subscriber_loan(sub)->_entity_id, - (z_zint_t)0, s1_res); + printf("Declared subscription on session 2: %ju %i %s\n", (uintmax_t)z_subscriber_loan(sub)->_entity_id, 0, + s1_res); subs2 = _z_list_push(subs2, sub); } diff --git a/tests/z_refcount_test.c b/tests/z_refcount_test.c index 27cb84d9a..7935b6c63 100644 --- a/tests/z_refcount_test.c +++ b/tests/z_refcount_test.c @@ -36,6 +36,11 @@ void _dummy_clear(_dummy_t *val) { _Z_REFCOUNT_DEFINE(_dummy, _dummy) +typedef struct { + unsigned int _strong_cnt; + unsigned int _weak_cnt; +} _dummy_inner_rc_t; + void test_rc_null(void) { _dummy_rc_t drc = _dummy_rc_null(); assert(drc._cnt == NULL); @@ -231,9 +236,9 @@ void test_overflow(void) { _dummy_t val = {.foo = 42}; _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); // Artificially set weak count to max value - for (size_t i = 0; i < INT32_MAX; i++) { - _z_rc_increase_strong(drc1._cnt); - } + _dummy_inner_rc_t *dcnt = (_dummy_inner_rc_t *)drc1._cnt; + dcnt->_strong_cnt = INT32_MAX; + dcnt->_weak_cnt = INT32_MAX; _dummy_rc_t drc2 = _dummy_rc_clone(&drc1); assert(_Z_RC_IS_NULL(&drc2)); @@ -250,6 +255,105 @@ void test_decr(void) { assert(_dummy_rc_decr(&drc1)); } +_Z_SIMPLE_REFCOUNT_DEFINE(_dummy, _dummy) + +void test_simple_rc_null(void) { + _dummy_simple_rc_t drc = _dummy_simple_rc_null(); + assert(drc._cnt == NULL); + assert(drc._val == NULL); +} + +void test_simple_rc_size(void) { assert(_dummy_simple_rc_size(NULL) == sizeof(_dummy_simple_rc_t)); } + +void test_simple_rc_drop(void) { + _dummy_simple_rc_t drc = _dummy_simple_rc_null(); + assert(!_dummy_simple_rc_drop(NULL)); + assert(!_dummy_simple_rc_drop(&drc)); +} + +void test_simple_rc_new(void) { + _dummy_t *val = z_malloc(sizeof(_dummy_t)); + val->foo = 42; + _dummy_simple_rc_t drc = _dummy_simple_rc_new(val); + assert(!_Z_RC_IS_NULL(&drc)); + assert(_z_simple_rc_strong_count(drc._cnt) == 1); + assert(drc._val->foo == 42); + drc._val->foo = 0; + assert(val->foo == 0); + assert(_dummy_simple_rc_drop(&drc)); +} + +void test_simple_rc_new_from_val(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc = _dummy_simple_rc_new_from_val(&val); + assert(!_Z_RC_IS_NULL(&drc)); + assert(_z_simple_rc_strong_count(drc._cnt) == 1); + assert(drc._val->foo == 42); + drc._val->foo = 0; + assert(val.foo == 42); + assert(_dummy_simple_rc_drop(&drc)); +} + +void test_simple_rc_clone(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + assert(_z_simple_rc_strong_count(drc1._cnt) == 1); + + _dummy_simple_rc_t drc2 = _dummy_simple_rc_clone(&drc1); + assert(!_Z_RC_IS_NULL(&drc2)); + assert(_z_simple_rc_strong_count(drc2._cnt) == 2); + assert(_z_simple_rc_strong_count(drc2._cnt) == _z_simple_rc_strong_count(drc1._cnt)); + assert(drc2._val->foo == drc1._val->foo); + + assert(!_dummy_simple_rc_drop(&drc1)); + assert(_z_simple_rc_strong_count(drc2._cnt) == 1); + assert(drc2._val->foo == 42); + assert(_dummy_simple_rc_drop(&drc2)); +} + +void test_simple_rc_eq(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t drc2 = _dummy_simple_rc_clone(&drc1); + assert(_dummy_simple_rc_eq(&drc1, &drc2)); + assert(!_dummy_simple_rc_drop(&drc1)); + assert(_dummy_simple_rc_drop(&drc2)); +} + +void test_simple_rc_clone_as_ptr(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t *drc2 = _dummy_simple_rc_clone_as_ptr(&drc1); + assert(drc2->_val != NULL); + assert(!_Z_RC_IS_NULL(drc2)); + assert(_dummy_simple_rc_count(drc2) == 2); + assert(_dummy_simple_rc_eq(&drc1, drc2)); + assert(!_dummy_simple_rc_drop(&drc1)); + assert(_dummy_simple_rc_count(drc2) == 1); + assert(_dummy_simple_rc_drop(drc2)); + z_free(drc2); +} + +void test_simple_rc_copy(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t drc2 = _dummy_simple_rc_null(); + assert(!_dummy_simple_rc_eq(&drc1, &drc2)); + _dummy_simple_rc_copy(&drc2, &drc1); + assert(_dummy_simple_rc_count(&drc2) == 2); + assert(_dummy_simple_rc_eq(&drc1, &drc2)); + assert(!_dummy_simple_rc_drop(&drc2)); + assert(_dummy_simple_rc_drop(&drc1)); +} + +void test_simple_rc_decr(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t drc2 = _dummy_simple_rc_clone(&drc1); + assert(!_dummy_simple_rc_decr(&drc2)); + assert(_dummy_simple_rc_decr(&drc1)); +} + int main(void) { test_rc_null(); test_rc_size(); @@ -268,5 +372,17 @@ int main(void) { test_weak_upgrade(); test_overflow(); test_decr(); + + test_simple_rc_null(); + test_simple_rc_size(); + test_simple_rc_drop(); + test_simple_rc_new(); + test_simple_rc_new_from_val(); + test_simple_rc_clone(); + test_simple_rc_eq(); + test_simple_rc_clone_as_ptr(); + test_simple_rc_copy(); + test_simple_rc_decr(); + return 0; } diff --git a/tests/z_test_fragment_rx.c b/tests/z_test_fragment_rx.c index 21184df52..d5dde99a3 100644 --- a/tests/z_test_fragment_rx.c +++ b/tests/z_test_fragment_rx.c @@ -80,7 +80,7 @@ int main(int argc, char **argv) { } // Declare subscriber z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); z_owned_subscriber_t sub; z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, keyexpr); diff --git a/zenohpico.pc b/zenohpico.pc index f3f450c20..0bfb73da3 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20241004dev +Version: 1.0.20241113dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 3559a1c90..f358d4659 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -37,6 +37,7 @@ file(GLOB_RECURSE Sources "../src/session/*.c" "../src/transport/*.c" "../src/utils/*.c" + "../src/system/platform_common.c" ) file (GLOB Sources_Zephyr "../src/system/zephyr/*.c")